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

Different rules for conditional function call (e.g. fn? x ) #4292

Closed
tad-lispy opened this issue Aug 2, 2016 · 5 comments
Closed

Different rules for conditional function call (e.g. fn? x ) #4292

tad-lispy opened this issue Aug 2, 2016 · 5 comments

Comments

@tad-lispy
Copy link

I was very much surprised today to learn that this code doesn't throw:

fn = 5
fn? 10

I was expecting it to throw TypeError: fn is not a function. Turns out it compiles to:

if (typeof fn === "function") {
  fn(x);
}

IMO the language is too lenient here for it's user's own sake. The above example is quite certainly an application developers mistake and an error would be very helpful. Current implementation can lead to a very subtle bugs.

I suggest it compiles to this instead:

if (typeof fn !== "undefined" && fn !== null) {
  fn(x);
}

Real life example

I had a perfectly good piece of code like this:

if data.value? then do_something_with data.value
else default_value

Then I decided that it will read better if I put the conditional logic on new lines:

if data.value? th # <-- but by mistake I left th out of then, a stupid typo!
  do_something_with data.value
else
 default_value

Now my code was compiling and running without errors, but the left branch of the if statement was never being executed. You can imagine that in a large codebase it was quite hard to figure out where does the wrong value come from.

@carlmathisen
Copy link

carlmathisen commented Aug 2, 2016

This is a feature, not a bug, and IMO a very important feature of CoffeeScript.

An example usage of the existential operator from the CS docs:

zip = lottery.drawWinner?().address?.zipcode

Or fn? 10 if you will.

Whenever I write code in JavaScript instead of CoffeeScript, this is the number one feature I miss. :)

@tad-lispy
Copy link
Author

Thanks for your comment @carlmathisen. I fully agree with you that conditional function call is a very good feature.

I'm not saying it should be removed, but rather that it's implementation should be different. Example you have provided works just as well in both current and proposed implementation, unless you expect that drawWinner can be defined and not to be a function at the same time and your intention is not to call it then. I doubt this is the case. My guess is that you want to call it if it exists. Correct me if I'm wrong :)

Consider how existential family of operators in CoffeeScript is consistent, except for the function invocation:

operator meaning
a? does a exist?
a ? b if a exists then a else b
a ?= b set a to b if a does not exist
a?.b take b of a if a exists
a? b call a if a is a function

What I suggest is to change the meaning of a? b to mean call a if a exists, which IMO is more consistent (and thus intuitive) and also prevents kind of bugs I described above.

@tad-lispy tad-lispy changed the title Conditional function call (e.g. fn? x ) is counter intuitive and bug-prone Different rules for conditional function call (e.g. fn? x ) Aug 2, 2016
@tad-lispy
Copy link
Author

Ok, I've just realised that original title for this issue wasn't the best I could have come up with :)

@connec
Copy link
Collaborator

connec commented Aug 2, 2016

This has come up before (e.g. #2315, and I'm sure there are more recent ones). There's been no consensus so far.

Personally I agree that the semantics should be the same for function calls as they are for other existence checks (e.g != null), both for consistency and to catch hard-to-debug cases such as these.

@tad-lispy
Copy link
Author

Thanks @connec. Closing in favour of #2315. I did my research, but missed this one.

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