-
Notifications
You must be signed in to change notification settings - Fork 2k
Default values for function arguments #2201
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
Comments
See #802, the issue that added default values for arguments. Please search next time. |
Sorry to be a pest, but I'm looking for the rationale for this too. I seem to remember some discussion about it on Twitter between @jashkenas and somebody (Eich?) but I can't find it now, and #802 doesn't seem to contain it. (Actually, it kind of reads like everybody coming to the consensus of using Thanks! |
The rationale is that the unfortunate distinction between null and undefined in JavaScript shouldn't be abused. CoffeeScript treats both as a way to say "no value". You can opt-in to a function's default value by explicitly passing |
Thanks @jashkenas. I completely agree about In any case, I appreciate that this is "settled law" in CS, and that, given that, these kinds of questions can be very tiresome. So thanks for taking the time to answer—and for doing it so quickly! It's much appreciated. |
Coffee's default arguments, being simply a sugar for a version of the JS idiom |
Yes, but the goal is clearly not to duplicate the behavior of the idiom exactly (or else other falsy values, like zero, would also be replaced by the default), but rather to provide the functionality that people are attempting to recreate when using the idiom. The idiom itself is a least-bad compromise we make to emulate default arguments—mostly because of its length in comparison to more unweildy solutions that would give us the exact behavior we desire (e.g. handle falsy values correctly). I understand that CoffeeScript's approach is fundamentally different than Ruby and Python's; my question was really about why the decision was made to make it so fundamentally different. Ultimately, I think, the answer boils down to which of the following you feel is more important:
Ruby and Python, at least, both take the position that 2 is more important and 1 is, in fact, not important at all (as only trailing arguments take the defaults). Philosophically, this seems like a sensible position as it seems important that a language (programming or otherwise) be able to convey both the idea of not having a favorite color (for example) and not specifying a favorite color, distinctly. The design of CoffeeScript, on the other hand, places more importance on 1. Of course, both 1 and 2 could be attained by using a sentinel value, but that's what Both 1 and 2 could also be (nearly) attained, I assume, by adding syntax to the language (which is why I include the caveat); something along the lines of Again, I do understand that this is an old decision too ingrained to be revisited this late in the game, and I want you to know that I'm not campaigning for a change or anything (which I realize this may sound like). I just wanted to understand the reasoning behind this design decision. I think I do now insofar as you guys felt that the ability to have default values for nullable arguments wasn't worth losing default arguments in non-tail positions or the cost of additional syntax. Thanks again @jashkenas and @satyr for jumping in on this thread. It's been really interesting, and I'm sure I won't be the only one curious about the subject! |
Ruby 1.9+ allows non-trailing defaults:
It's technically possible to implement positional default arguments (proposed at #1091), but the compilation would be more complex and non-idiomatic (non-goals for Coffee). |
Ah, cool. Regardless, I think it just underscores my point—both because of its late addition and because it's still impossible to opt in to an arbitrary default argument, e.g.
From my point of view, CS already has this ability—it's just implemented in a way that prohibits defaults for nullable arguments. If the goal were to allow both arbitrarily positioned defaults (including in non-beginning and non-trailing positions) and to honor explicitly passed f = (a = 0, b = 1, c = 2) ->
console.log [a, b, c]
f 9, -, 9 becomes var f;
f = function(a, b, c) {
if (a === undefined)
a = 0;
if (b === undefined)
b = 1;
if (c === undefined)
c = 2;
return console.log([a, b, c]);
};
f(9, undefined, 9); I'm not proposing a specific syntax here, just showing how both goals could be achieved by the addition of some new syntax. Of course this has its own drawbacks: using syntax instead of an identifier means that conditional omission would be difficult and, knowing the implementation, people would probably just resort to using undefined: f = (a = 0, b = 1, c = 2) ->
console.log [a, b, c]
if SOMETHING
f 9, 9, 9
else
f 9, -, 9
# Not as short as this:
f 9, (if SOMETHING then 9 else undefined), 9 This is @jashkenas's objection; that, because the underlying implmentation would recognize a difference between |
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Use NPM scripts to run coffeelint - Update coffeelint to 2.1.0 Also update Coffeescript and explictly depends on version 2, Use `undefined` as default argument instead of null, it's breaking changes on Coffescript 2. See: - https://coffeescript.org/#breaking-changes-default-values - jashkenas/coffeescript#2201 - Remove grunt and its plugins inlcude grunt-coffeelint, grunt-contrib-coffee and grunt-mocha-cov, Remove Gruntfile.coffee by using NPM scripts, and remove path of "npm bin" in scripts, Because the command of "npm run" adds node_modules/.bin to the PATH provided to scripts automatically. - Update vulnerable dependencies include socket.io, chokidar - Explictly depends on mocha Add --exit flag "By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior" mochajs/mocha#2879 https://mochajs.org/#-exit - Use c8 to output coverage instead of blanket - Add generate-examples scripts To replace 'gen-examples' task defined in Gruntfile
Why do you use
if (liquid == null) liquid = "coffee";
instead ofif (liquid === undefined) liquid = "coffee";
?Because in your case I can't pass the null argument for replace the dafault non-null argument.
The text was updated successfully, but these errors were encountered: