4 ms·
I appreciate both Forth (and Lisp) and have both used and implemented several (mostly naive) versions of both, but IMHO with something OCaml/F#/Reason you get p
by thelazydogsback 6y ago
I appreciate both Forth (and Lisp) and have both used and implemented several (mostly naive) versions of both, but IMHO with something OCaml/F#/Reason you get pretty close. Sure, it's not concatenative, but you can certainly code point-free if you like so rather than:
c(b(a(42), 2))
You can write either:
42 |> a |> b 2 |> c
or a reverse pipeline:
c <| b 2 <| a <| 42
with complete type-safety. Note quite as concise as:
42 a 2 b c
But I that's good for the most part. I think programming with higher-order curried functions and closures gives similar power but much more readability -- every time I've gone past the toy program stage with concatenative languages, my head ends up exploding -- but maybe I never had the appropriate epiphany.
With that said, I certainly appreciate the power of Forth and compile-time words -- amazing power for such a minimal system.
- nivertech 6y agoagree, I'm using pipelines in Elm, which is almost the same syntax as in OCaml (piping into the last argument). I dislike "<|" b/c of the flexibility syndrome. It's frequently used in Elm in order to avoid parentheses. Same with Elixir, but it's missing currying, so it does piping into the first argument. Clojure has both thread-first and thread-last macros. The problem with these approaches is that they are optional. Ideally the point-free programming will be the default, not an optional style. I agree that pipelines in Elm and Elixir are much more readable than point-free code in Forth and APL ;) Unlike the ML-family languages, in APL/J/K/q you can omit any combination of arguments: f:{x-y} f[1] same as f[1; ] f[;1] same as f[ ;1] f same as f[ ; ]
- thelazydogsback 6y agoMost Lisps (incl. clojure), Scala, and probably others also allow placed or numbered "holes", so something like: 42 |> f 3 would be the same as 42 |> f 3 _ but you could do: 42 |> f _ 3 to get at the first arg. or even to swap args: 42,43 ||> f %1 %0 which would essentially get expanded to: 42,43 |> fun a b -> f b a (Of course, in this case the closure should get erased by the optimizer to simply "f 43 42".) I really miss not having this in F# (and C# for that matter)