Yes this is why I picked it: assurance that implementing it in the language wouldn’t cause any breaking changes.
Much too inconvenient. If I had to recite the Lord’s Prayer every time I expressed my thoughts, I’d never express my thoughts.
Better yet, we could use ↦ (\mapsto<tab>
) for anonymous function definitions, to be consistent with mathematics (as everyone knows, → is used for specifying a function’s domain and codomain, e.g. 𝑓 : ℝ → ℝ⁺, while ↦ is used for function definitions, e.g. 𝑥 ↦ 𝑥² )
I’m kidding, I’m kidding. Maybe. I appreciate the openness to changing the language. But imo, there would need to be a very compelling reason to break anonymous function syntax. I’d rather break ..
than ->
, but I’m growing partial to using --
for UFCS method calls since it wouldn’t need any breaking changes, is reasonably easy to type, and can easily be verbalized as “dash.”
Another reminder: UFCS is not an object-oriented concept, so let’s not confuse it with OOP. (I might have to append this reminder to every message. )
Yeah, I get the hangup on map
, reduce
, filter
, etc.: functions that describe sentences of the form, “Do something when applying this behavior to that collection.” Perhaps they could have as easily followed the form, “Do something when taking this collection and applying that behavior to it,” but that’s not how the language authors decided to do it. [Not true; a function call of the former form is transformed into the latter form when using the do
statement! ]
UFCS syntax isn’t optimal for chaining using these methods, I agree. However,
- most functions don’t follow this form of taking a function as a first argument,
- broadcasting covers most use cases you’d otherwise use
map
for, and - there are additional benefits to UFCS beyond chaining, such as autocomplete and the simple ability to express thoughts in noun→verb form,
so let’s not throw the babies out with the bathwater.
Further, so long as the object is captured, UFCS can still bring some convenience. Example:
arr = collect(-2:2)
# cube each element and filter by positives
let cube(x) = x^3, ispositive(x) = x > 0
arr--(cube--map)()--(ispositive--filter)() == [1, 8] # true
end
In English it’d read like: “Take the array, apply a cube mapping, and then apply a positive filtering.” Unfortunately it gets ugly if the anonymous functions aren’t named.
Or since these are now single-argument functions, one could chain with pipes to avoid parentheses:
arr |> cube--map |> ispositive--filter
or compose a function as:
newfunc = ispositive--filter ∘ cube--map
newfunc(arr)
Admittedly it’d be nicer to say “Take the array, map onto it the cubing function, then filter it by positives” but I’m working with what I’ve got until I can find good syntax for sending the object to the last argument.
You would never ever ever want to do this, but for illustration:
mapreduce(√, +, arr) == (arr |> (+ -- (√ -- mapreduce)))
Again though, UFCS is better suited to the greater universe of functions that don’t take a function as a first argument, such as
"Hello, world!"--split(",")--replace.("o"=>"e")--join(":") == "Helle: werld!" # true
document--root()--firstelement()--setnodecontent!("Hello, world!")
There’s a big world of functions out there structured like this.
Oh! I am honored. My favorite bit is the syntax of any expression of _
becoming a single-argument anonymous function. That feels like it should be a core language feature.
The point of discussion is which features that make common human thought patterns convenient, concise, and easy to express should be in the language, regardless what specific problem is being solved with the code and what packages are loaded for it. Being careful of course to select only the thought patterns which are so common and so useful that it’d be silly not to implement them, especially as we approach a new major version.
Imagine if the “if you want convenience just make a macro and package it” attitude was applied to list comprehensions, matrices, broadcasting, or any of Julia’s best and most frequently used syntax sugar. Imagine all the syntax clashes with other packages!
P.S. Taking inspiration DataPipes.jl and from Clojure’s ->
threading into first argument and ->>
threading into last argument, I’m contemplating ---
to pass the object into the last non-keyword argument. Maybe?
arr---map(cube)---filter(ispositive)
Then the ugly example from above could be
mapreduce(√, +, arr) == arr---mapreduce(√, +)
---
could be verbalized as “em-dash,” which appropriately sounds like “end-dash.”