4 ms·
> uniform function call syntax that is : a.foo(b) vs foo(a, b) being interchangeable. Ive written a lot of c++ in the past but I'm not particularly knowledgeab
by andyjohnson0 1y ago
> uniform function call syntax that is : a.foo(b) vs foo(a, b) being interchangeable.
Ive written a lot of c++ in the past but I'm not particularly knowledgeable about fp, so I'm wondering why this is important. Is it syntactic sugar or something more significant?
- fredrikholm 1y agoIt allows existing method-heavy code to be used in a functional style without bending the knee to more OOP inspired patterns. Think of a fluid API, but instead of chaining method calls you'd pass data to several functions "chained" together similar to how UNIX pipes work. With this type of API, you can pass one argument into the function and pipe the other such that: data |> foo(bar) |> baz Is a more FP friendly version of: return baz(foo.bar(data))
- andyjohnson0 1y agoMakes sense. Thank you!
- warkdarrior 1y agoShouldn't that be? data |> bar(foo) |> baz Or maybe: data |> bar(&foo) |> baz
- fredrikholm 1y agoIn Clojure it's: (.-> foo bar baz) So you might be right in correcting me, it's been a while since I've used another FP language in anger. With regards to taking the address of foo, pointers are generally not a (user space) concept in FP languages. The compiler/runtime usually optimizes cases like this as passing function pointers is a very large corner stone of FP. For mutation semantics you often approach it similar to how atomics works in non-FP languages. When opting into mutation you lose one of the pillars of FP which is idempotency and purity via immutability. Treating it as a special case helps scope it down to "here be dragons" areas.
- fooker 1y agoThinking about this a bit more, foo could be a ‘context’ object here! data |foo> bar |> baz This almost gets us to a point where you can express a dataflow DAG in code.