Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implicit argument #739

Closed
satyr opened this issue Oct 2, 2010 · 16 comments
Closed

Implicit argument #739

satyr opened this issue Oct 2, 2010 · 16 comments

Comments

@satyr
Copy link
Collaborator

satyr commented Oct 2, 2010

Many modern/popular languages adopt syntax sugars for simpler functions. Could we as well?

Arc
(= squared [* _ ])
Clojure
(def squared #(* % %))
Groovy
squared = {it * it}
Perl6
$mul = {$^a * $^b}
Scala
var sixty = List(3, 4, 5).reduceLeft(
* _)
Scheme
(define mul (cut * <> <>))

Behaviors vary, but the basic idea is same: to DRY.
Among above, Arc/Groovy's is the simplest and easy to implement:
$ bin/coffee --no-wrap -pe 'compact = -> it.filter -> it?'
var compact;
compact = function(it) {
return it.filter(function(it) {
return (it != null);
});
};
See also: #111 #330

@michaelficarra
Copy link
Collaborator

What identifier do you suggest using? I believe _ is the most user-friendly, but most of these implementations would reserve legal JS identifiers. An example of a use case is in my FunctionalJS library where I define an _ function as an argument accessor after being inspired by scala. Is there any GOOD way to add this to the language? It'd be a nice feature, but not worth adding yet another reserved word to JS.

@satyr
Copy link
Collaborator Author

satyr commented Oct 2, 2010

What identifier do you suggest using?

I think it suits well to other parts of language (which are English-heavy) and makes for nicer DSLs.

not worth adding yet another reserved word to JS

It'll become available only when you omit arguments and use it under the function, so not really reserved.

Just see: http://github.com/satyr/coffee-script/compare/master...it

@michaelficarra
Copy link
Collaborator

Wouldn't it change the functionality here: (it) -> -> it? Also, I think it is ugly. I'd rather something that looks more syntax-y, like _, <>, or %. But that's pretty much entirely subjective.

@satyr
Copy link
Collaborator Author

satyr commented Oct 2, 2010

(it) -> -> it

Same deal as Groovy:
f = { it -> ({ it }) }
assert f(1)() == null
which is an analog to [this case](http://satyr.github.com/cup/#e:f%20=%20(arguments%29%20-%3E%20-%3E%20arguments%0Aputs%20f(1%29(%29):
f = (arguments) -> -> arguments
puts f(1)()

@yfeldblum
Copy link

I'm not a fan of this syntax sugar in these other languages. I think it makes up for the lack of the right syntax sugars. As an example, I particularly dislike the Scala example in the OP because it shows that operators are not first-class values in Scala in the same way that a function or the number 1 might be a first-class value in CoffeeScript or another language. In Haskell, one has squared a = a * a and sixty = foldl1 (*) [3, 4, 5]; in CoffeeScript, squared = (a) -> a * a but there is no immediate reduce function or way to treat operators as first-class values (i.e., some simple syntax (*) for (a, b) -> a * b), which is what is really missing.

@TrevorBurnham
Copy link
Collaborator

So, basically the proposal is to have a keyword that works as shorthand for arguments[0], right? I'm not sure that it's worth adding it as a keyword just to save folks from writing (it) in front of -> (or, better yet, a more descriptive argument name).

What kind of DSLs were you thinking of?

@michaelficarra
Copy link
Collaborator

@TrevorBurnham: It's not just arguments[0], it works as a successive argument accessor.

[3,4,5].reduce (-> _ * _)

becomes

[3,4,5].reduce(function(){ return arguments[0] * arguments[1]; })

or if we wanted to skip the array accesses

[3,4,5].reduce(function(_ref,_ref2){ return _ref * _ref2; })

@TrevorBurnham
Copy link
Collaborator

Wait, wasn't satyr proposing that -> _ * _ should define a squaring function? In either case, the syntax seems a bit confusing to me. Some kind of shorthand for the arguments pseudo-array would be nice; perhaps

[3,4,5].reduce (-> %0 * %1)

could compile to

[3,4,5].reduce (-> arguments[0] * arguments[1])

Wouldn't that be clearer than using the same symbol to reference multiple arguments?

@michaelficarra
Copy link
Collaborator

Actually, I like the scheme syntax:

-> <> * <>
function(_ref,_ref2){ return _ref * _ref2; }

And it may also lend itself to an arguments shorthand like this:

-> <1> + <0> + <>
function(_ref){ return arguments[1] + arguments[0] + _ref; }

But I'm not sure yet if that would cause syntactic problems with the less-than and greater-than operators.

@danielribeiro
Copy link

Great idea. Ruby doesn't have one, but with Syntax Tree metaprogramming, you can hook it into the langauge (I am writting such extension, which can be plugged in runtime)

@hen-x
Copy link

hen-x commented Oct 5, 2010

At the risk of scope creep, I really like the idea of an arguments shorthand, albeit for a different reason: function binding and argument forwarding.
If we had a hypothetical syntax like %2 expanding into arguments[2], we could have %... expanding into arguments..., which would give us this:
boundCallback = -> object.doThing %...
which is a nice, concise syntax for an inline function that just forwards its arguments somewhere else. I like how it looks like a function, and doesn't have the redundancy of object.doThing.bind(object).

@StanAngeloff
Copy link
Contributor

I reckon there is enough magic in the language as it is and there is no need for another keyword, special character or what not for the extra convenience, no ? It just doesn't bring enough on the table.

@jashkenas
Copy link
Owner

I'm with Stan and Trevor on this one. This is a great ticket, and there are a large number of proposals in it, but in the end the most-coffee-ish one is this:

square = -> it * it

And looking at our current definition:

square = (x) -> x * x

It really doesn't seem like a good idea. It's not flexible, in that naming anything other than the first argument would be an ugly hack; and is not readable, in that it encourages all arguments to be named "it", instead of something descriptive.

Closing as a wontfix.

@danielribeiro
Copy link

Too bad. With RubyUnderscore, now even ruby has it. Guess the workaround for coffeescript will be the same: injected into coffeescrip by manipulating AST(--nodes can be of great help here).

@satyr
Copy link
Collaborator Author

satyr commented Dec 10, 2010

For the record, Coco ended up doing both.

@danielribeiro
Copy link

@satyr

nice!

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants