Change the auto-return hushing syntax to a literal !->
Opened this issue · 11 comments
Whenever I start out with a hushed function
thing.onclick !-> console.log \clicked
And then want to add a parameter, I usually end up doing this:
thing.onclick (e) !-> console.log \clicked e
Which, unlike (e) -> ....
, actually compiles to:
thing.onclick(e(function(){
console.log('clicked', e);
}));
This is--given how auto-return hushing works--how that code should compile, but I'd much rather it compile to what I expected, and I've been bitten enough times by it to care.
Proposal
Let the literal !->
define a function without auto-return:
<arglist> !-> <fn body>
In the same way ->
defines auto-returned functions.
Why
I think of !->
as analogous to the ruby convention of appending !
to functions that mutate in place, e.g. array.uniq!
; !->
defines functions that usually change state, not return values.
But since !->
is really not ->
, a hushed function with arguments becomes !(args) ->
, which loses most of that distinction.
Using the english form of hushing also reads really strangely:
thing.onclick not -> console.log \click
not function doStuff => do stuff
With a literal !->
marking hushed functions instead, there's no chance of a confusing-looking not
being used, nor is there a break in muscle memory when changing -> it.stuff
to (thing) -> thing.stuff
or !-> it.method!
to (thing) !-> thing.method!
.
For named functions, the literal function!
could be used unambiguously:
function! mutate-stuff a b c
...
Furthermore, this change doesn't have to immediately break backwards compatability, since not <fn literal>
still would otherwise evaluate to a useless false
. The old hushing method could be deprecated while still introducing the new hushing literals.
Other thought is that the literal could instead be !>
, but that loses the distinctive arrow look of regular ->
.
I believe it was made for this kind of case : get-fn! ->
.
What does get-fn! ->
signify? I don't see how that effects the proposal.
get-fn
returns a function, which is then called with the parameter ->
I understood that part, but nothing about that effects hushing auto-return.
get-fn! !->
is still unambiguous.
Needs {up,down}-votes.
Other thought is that the literal could instead be !>
That leaves out ~>
and <~
. See #91.
Avoiding symbol-bikeshed was one of the reasons to choose the current syntax.
That leaves out
~>
and<~
. See #91.
True, which is another reason I didn't like !>
as much. Promoting !->
to a single token is less of a bike-shed problem, given that it's already in wide use as two symbols.
More succinctly, here are my arguments for a literal !->
:
!->
already looks like a standalone symbol and it's used plenty of places in the coco source--as well as my own projects.- unlike
@prop
or&method
,!->
is entirely made up of special symbols, so it's harder to recognize that it is, in fact, two symbols (as a comparison, haskell makes all-symbol identifiers auto-inflix). - Adding arguments to a hushed function doesn't feel the same as a non-hushed function, since the optional arglist is actually squeezed between the
!
and the->
instead of in a space, e.g.fn = -> it
=>fn = (arg) -> arg
. - Having
! <fn literal>
hush the auto-return is a clever way to make compilation simple, but given that nobody really uses the englishnot
form, I think it's clear that human coders aren't thinkingnot ->
, they're thinking!->
. See also:not function
and<- not expression
. - Recognizing
!->
as a standalone literal is backwards compatible, and given its widespread usage (as two symbols), much of the code that has hushed functions wouldn't be deprecated either.
And the full list of changes are:
!-> <body>
: hushed function symbol.!~> <body>
: hushed bound-this symbol.<-! <expression>
: hushed backcall symbol.function! <args> => <body>
: hushed function literal.
I'm actually less sure about function!
. !function
would be more backwards-compatible (if only in how it looks), but function!
is more english-like or ruby-like.
Not sure about function!
as well, but +1 for unified !->
👍 for unified !->
and why not function!
too. Don't see anything wrong with that.
!->
would put !
just before the actual function syntax (->
). !function
already works that way.
I support this, though I feel it should be !function
rather than function!