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

Error thrown from parsing a partial application of a method application chain #746

Open
dead-claudia opened this issue Jul 7, 2015 · 4 comments

Comments

@dead-claudia
Copy link
Contributor

As in, the following throws on both the latest NPM version and the website:

(a.b _ .c)
(a.b _ .c!)
(a.b _ .c d)

Here's the stack trace for each from lsc (same output):

TypeError: Cannot read property 'length' of undefined
    at Chain.exports.Chain.prototype.add (/home/isiah/.npm/.global/lib/node_modules/livescript/lib/ast.js:950:110)
    at Object.anonymous (/home/isiah/.npm/.global/lib/node_modules/livescript/lib/parser.js:96:41)
    at Object.parse (/home/isiah/.npm/.global/lib/node_modules/livescript/lib/parser.js:840:36)
    at Object.exports.compile (/home/isiah/.npm/.global/lib/node_modules/livescript/lib/index.js:45:20)
    at compileScript (/home/isiah/.npm/.global/lib/node_modules/livescript/lib/command.js:197:31)
    at /home/isiah/.npm/.global/lib/node_modules/livescript/lib/command.js:97:9
    at Object.<anonymous> (/home/isiah/.npm/.global/lib/node_modules/livescript/bin/lsc:7:26)
    at Module._compile (module.js:430:26)
    at Object.Module._extensions..js (module.js:448:10)
    at Module.load (module.js:355:32)

By the looks of it, there's no parsing support for this.

@dead-claudia
Copy link
Contributor Author

@vendethiel Any ideas? Still failing.

dead-claudia pushed a commit to dead-claudia/LiveScript that referenced this issue Feb 16, 2016
@rhendric
Copy link
Collaborator

So, the crash is easily fixed—all it takes is changing one . to a ?. Unfortunately, while this now lets those expressions compile, they don't have the semantics that I presume you want—the docs make no mention of the meaningfulness of parentheses when compiling partial applications, and so the compiler dutifully treats (a.b _ .c) as equivalent to (a.b _).c, the same way that (a.b x .c) would be equivalent to (a.b x).c. I see from your tests that you were expecting something closer to the way Scala handles underscore placeholders, where the nearest bounding parentheses help determine the extent of the anonymous function created.

If that's indeed what you're proposing, you should probably flesh out the feature request a little more. One potential niggle is what gets captured at the time of partial function creation; right now, everything does:

a = b: (x, y) -> x + 2*y
c = 10
f = a.b _, c
a.b = (x, y) -> 2*x + y
c = 1000
f 1 #=> 21

Contrast with the similar but non-capturing version:

a = b: (x, y) -> x + 2*y
c = 10
f = -> a.b it, c
a.b = (x, y) -> 2*x + y
c = 1000
f 1 #=> 1002

In an expression like (a.b _ .c d .e f), in your proposal, does a.b still get captured? Do d and f? Or do you abandon the capturing semantics to make (any expression including _ as an argument somewhere but not inside any deeper parentheses) semantically equivalent to (-> that same expression with _ replaced by it)?

@dead-claudia
Copy link
Contributor Author

First, I thought I'd clarify with my current stance. In my opinion, it
would be best rejected, since it's not just a simple method call, function
call, or property access. Otherwise, it's nearly impossible to infer
reliably. By that point, you probably should already be using a normal
function, since even if it's trivial to the programmer, it's no longer
trivial to the compiler. To my knowledge, even Haskell's GHC would reject
that kind of thing.

The reason I didn't was because I was uncertain at the time, and hadn't yet
put much thought into it. I hadn't really thought about which was the
better route.

I'll have to convert the tests, but I'm not sure exactly what the message
should be in the rejection.

On Fri, Feb 19, 2016, 00:43 Ryan Hendrickson [email protected]
wrote:

So, the crash is easily fixed—all it takes is changing one . to a ?.
Unfortunately, while this now lets those expressions compile, they don't
have the semantics that I presume you want—the docs make no mention of the
meaningfulness of parentheses when compiling partial applications, and so
the compiler dutifully treats (a.b _ .c) as equivalent to (a.b _).c, the
same way that (a.b x .c) would be equivalent to (a.b x).c. I see from
your tests that you were expecting something closer to the way Scala
handles underscore placeholders, where the nearest bounding parentheses
help determine the extent of the anonymous function created.

If that's indeed what you're proposing, you should probably flesh out the
feature request a little more. One potential niggle is what gets captured
at the time of partial function creation; right now, everything does:

a = b: (x, y) -> x + 2_yc = 10f = a.b _, ca.b = (x, y) -> 2_x + yc = 1000
f 1 #=> 21

Contrast with the similar but non-capturing version:

a = b: (x, y) -> x + 2_yc = 10f = -> a.b it, ca.b = (x, y) -> 2_x + yc = 1000
f 1 #=> 1002

In an expression like (a.b _ .c d .e f), in your proposal, does a.b still
get captured? Do d and f? Or do you abandon the capturing semantics to
make (any expression including _ as an argument somewhere but not inside
any deeper parentheses) semantically equivalent to (-> that same
expression with _ replaced by it)?


Reply to this email directly or view it on GitHub
#746 (comment).

@vendethiel
Copy link
Contributor

So, first: https://github.com/taku0/placeholder_syntax_for_coffeescript/blob/master/src/placeholder.coffee
https://github.com/taku0/placeholder_syntax_for_coffeescript#scopes-of-placeholders spells out the Scala-like rules (they're not quite like Scala, apparently), but they're fairly complex.
Also, this was discussed (a bit) in #19.
It doesn't actually support a(_).b, though, so...:

In an expression like (a.b _ .c d .e f), in your proposal, does a.b still get captured?

That's basically the difference in LS between partial application and currying (f _ does capture, (+ f) doesn't).
I seem to misremenbering that we transformed f _ to -> f it in some cases... It doesn't really matter to me either way. I'd say capture a.b but not f and d ("where the execution stops"), but I don't mind either.

Or do you abandon the capturing semantics to make (any expression including _ as an argument somewhere but not inside any deeper parentheses) semantically equivalent to (-> that same expression with _ replaced byit)?

I'd like that, but I think making a.b _ and a.b _ .c too different would be a mistake.

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

No branches or pull requests

3 participants