-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Named Functions #15
Comments
Reference for named functions in JS: |
Since we're always going to name the function with the same name as the variable, I think we can avoid most of the pitfalls of the above article. It is going to leak memory in Internet Explorer, if you create 100000 named function objects, but that's an affordable price. This is on master now, closing the ticket. |
There's a problem with functions with the same name as variable x:1 should either
|
I'm not so sure that this is a problem. It seems to behave correctly when I try it. This is now a test case in test/fixtures/execution, that prints all
|
Let me know if you're hitting any errors or unexpected behavior, with a test case, and I'll reopen this ticket. |
One year later... I'm wondering why this behavior was changed, so that Searching through later issues doesn't give me much. I can't make heads or tails of issue 758 from October; it begins "Now that we have a format for allowing named functions without breaking IE..." What was that referring to? |
Ah, just found the full explanation in the FAQ here. |
I'm going to chime back in on this one... I've read and fully understand the IE issues with named functions. However, I think it's asinine that CoffeeScript explicitly disallows the use of named functions just to support IE. By default, CoffeeScript should not allow for named functions, however, why can't we have an alternative syntax or optional compile-time flag that let's the user determine if they want named functions, not that language. CoffeeScript has become increasingly popular among NodeJS developers - developers who don't need to support IE - they are writing server-side language. They could leverage so much more if they could name functions... I cite the example of express. If they could access the named function in a routes file, they could "guess" the name of the view (like rails) using Bottom line - I understand why it was taken out. It needs to be put back in as a non-default compile option or alternative syntax. You've taken away one of the best features of Javascript :'( |
I really need this. I didn't realize coffeescript with OK with removing javascript features. I thought it was supposed to be nothing fancy, and I think attempting to remove the responsibility of cross-platform programming is pretty much as fancy as you could get. |
When was this fixed? Can someone cite a commit? |
@sethvargo: it hasn't been fixed and never will. There's no need for NFEs or FDs. Your example above is not convincing. |
Well, aside from debugging and profiling where function names are essential. I use the .name property that v8 puts on all functions for a kind of monkey patching. The problem is not that I can't design an API which uses strings and a hashmap (object), but aside from it looking ugly, the entire codebase at hand is written in js which has named functions, so I now need two alternate interface for patching methods one using strings so coffeescript can work, and another using function names, because coffeescript is not compatible with javascript. Alternatively I can't use coffeescript in the app. You are making the assumption that a library will never use function.name, but if anything does (like my lib) then it cannot be used by coffeescript, unless it repurposes itself for coffeescript's sake. : \ e.g. var module = { function patch(functionToPatch) { patch(function foo() { Again, "patch" could be repurposed for coffeescript, the problem is that coffeescript probably shouldn't be requiring js to change for its sake. Also... the real problem creating the IE issue is the assumption that "a = ->" generates "function a()", instead of an additional syntax for named functions. The idea that a named function is the same as a named variable holding a function, is a false premise of how javascript works. |
@em: edit: regarding debugging, most debuggers actually look at the |
The IE bug is not standard either, so what's your point? The .name property is one example of how different environments can do different things for named-functions and anonymous-functions. They're different things. The other example bodes the same, debugging and profiling use function.name to build call stacks. Honestly, I bet if you asked Brendan Eich why he gave javascript named functions at all and didn't make everything anonymous he'd cite the same point. Sheesh. |
Let's be pleasant, folks. |
IIRC, Pinging @jdalton; he clarified this point for me some time ago. |
@em:
They're really not different things. NFEs and anonymous FEs are identical except NFEs add their name to their body's scope. Other than that, they're supposed to behave exactly the same. FDs are different because they respect odd hoisting rules and they add their names to the containing scope.
That's just a reason for not using the extraneous feature that we're not providing for you. We're not providing it because it's not necessary and, as the IE bug points out, can even be harmful. We also don't provide
As I said above, they use note: in case you aren't familiar with the common acronyms, NFE = named function expression, FE = function expression, FD = function declaration |
@kitcambridge: you are correct. The IE bug treats NFEs similarly to FDs in that it adds the name to the containing scope instead of just the function body's scope. |
I was summoned by @kitcambridge to confirm that |
Obviously there's some hostility here. Frankly I think it's ridiculous. I don't understand why you won't add the functionality back in. Since there's such hostility, it should be an option, not a default. However, you are violating this very description of coffeescript (via CoffeeScript.org):
Well, it's not "just JavaScript". There's something I can do in plain JS (NFE) that I can't do with coffeescript because its creators are too strongly opinionated against it. Either implement it as a non-standard option, or change the description on coffeescript.org. |
Furthermore, labeling this as "fixed" was quite misleading... I suggested "blatantly ignored due to overzealous opinions"... |
@sethvargo At the time the issue was closed, named functions existed on master. They were later removed for the reasons detailed above. |
Well, someone should remove the label... Without reading the entire thread, it's very easy to think this issue has been resolved... |
@sethvargo: CoffeeScript's golden rule doesn't apply to constructs, but functionality. As I said above, there's no way to put an unqualified reference to the Also, I'm not sure what hostility people are talking about. I don't see any. If it was directed at me, I didn't mean to come off as hostile. |
Yeah, I don't see any hostility either. My "Sheesh"? Sorry, it resonated as light-hearted in my head. |
Do you really think that manually adding displayName property to all functions is a very good idea? Really, I'm working with server-side javascript, so, I cant imagine any reason why some old microsoft's garbage is poisoning it for me now... :) |
Well... fortunately, it is one-line fix. I've just replaced code = 'function';
/*if (this.ctor)*/ if (this.name !== undefined) code += ' ' + this.name;
code += '(' + vars.join(', ') + ') {'; and now it works just fine. |
Chiming in to say I tested every major browser, safari, ff, and chrome. None of them use 'name' or 'displayName' for profiling or console display of function names. |
@em: Sometimes, it will print my function name instead of For production enviroment with some buggy browsers we can always turn off this feature, of course. |
@GeoffreyBooth @lydell @vendethiel — Now that IE8 and below aren't relevant anymore, is there a good reason why CoffeeScript 2.0 shouldn't bring back our old-school named-by-default functions everywhere? edit: To be clear — I'm not talking about function declarations. I'm talking about all functions being named in addition to assigned, like we used to have, briefly. |
I'd be concerned about users expecting the same behaviour from bound functions, for which there is no named syntax. With the rules of the ES spec named functions are basically redundant in CS (where an assignment is needed for the name anyway). |
Huh? That's not true. We can put names on bound functions in exactly the same way as unbound ones: hello = -> hello = function hello() {}; hello = => hello = (function(_this) {
return function hello() {};
})(this); |
Fair point. I was thinking of the hello = => hello = () => {}; |
Oh, of course -- sorry. I forgot about those. |
@jashkenas what about function hoisting? let's also support that! @penne12 thanks for ``function test(){ |
@jashkenas We were discussing named classes here in the CS2 reimplementation of classes. Basically the CS2 version of classes will output code like So yes, I think function declarations like |
* fix: add missing `Base#locationData` property * fix: `Literal#value` is a string, not another node * fix: add missing `Block#expressions` property * fix: `Parens#body` is a block
@avalanche1 It was clearly pointed out that function declaration (or hoisting) is not a part of this thread. Please create a separate issue where we could have a focused discussion about its necessity and implementation. |
well, function hoisting without named functions doesnt make sense to me - so I'll wait if named functions are set upon as an agreed solution - then I'll make a sep. request if needs be. |
VoidWHOA! Super duper kool!
The following works for objects:
Finally we can drop all the backtick voodoo and other magic. Hurray! 😺 I think this can be closed. |
@avalanche1 That's not coffee script - it's the browser doing it for you, and it has limited support (and is undocumented behavior). This issue still should be worked on to make it work in all browsers. |
@penne12 , huh?
R u talking about |
Oops... sorry bout that 😨 Anyways, basically, a named function looks like this: function namedFunction(){
// this is a namedFunction
} But, with your example, CoffeeScript generates: var f, foo;
foo();
foo = f = function() {
return log(arguments.callee.name);
}; Which means that the function isn't named - but some browsers will assume the name based on what they're assigned too, but not always. In terms of hoisting, CoffeeScript is smart and declares variables the first time they're used, and many browsers will do a "first past" while parsing Javascript to define variables before running the rest of the code (as far as I understand it, maybe someone more familiar with the inner workings of the language could explain better). |
I see. |
@avalanche1 It’s not a feature with a name like you would find in an ES6 compatibility table. I would refer to it as debugging tools inferring anonymous function names from their assigned references. See https://www.bennadel.com/blog/2836-anonymous-functions-assigned-to-references-show-up-well-in-javascript-stack-traces.htm |
Ahem, after further investigating, it turns out that what I've posted above is actually void. Anyway: |
Here's a simple little script if you want to force names onto functions, but this uses runtime evaluation, and might not be the best choice except in some very specific scenarios. DO NOT LET THE USER PICK THE FUNCTION'S NAME, OR THEY WILL BE ABLE TO EXECUTE ARBITRARY JAVASCRIPT CODE nameFunc = (n, func) ->
new Function("func",
"return function #{n}(){return func.invoke(this, Array.prototype.slice.call(arguments))}"
)(func) Then just: nameFunc 'namedFunc', (a) -> console.log a might be somewhat broken, also shouldn't be used for user input. |
@penne12 , thanks mate! |
Per #4531, it was decided that CoffeeScript will not be supporting function declarations (outputting |
@GeoffreyBooth I was cleaning up an old coffeescript project and came across if obj instanceof baseStream && !obj._readableState.ended
obj.on('end', next)
obj.on('data', ->
obj.removeListener('end', next)
obj.removeListener('data', arguments.callee)
next()
)
else
next() In es5 you would do: if (obj instanceof baseStream && !obj._readableState.ended) {
obj.on('end', next)
obj.on('data', function data() {
obj.removeListener('end', next)
obj.removeListener('data', data)
next()
})
} else
next() If coffeescript had support for named functions, you could do: if obj instanceof baseStream && !obj._readableState.ended
obj.on('end', next)
obj.on('data', \data ->
obj.removeListener('end', next)
obj.removeListener('data', data)
next()
)
else
next() Which is a nicer than: if obj instanceof baseStream && !obj._readableState.ended
# don't inline event handlers in coffeescript (no support for named functions)
# arguments.callee is deprecated so don't use it to remove event handler
data = ->
obj.removeListener('end', next)
obj.removeListener('data', data)
next()
obj.on('end', next)
obj.on('data', data)
else
next() The |
What's wrong with if obj instanceof baseStream && !obj._readableState.ended
obj.on 'end', next
obj.on 'data', data = ->
obj.removeListener('end', next)
obj.removeListener('data', data)
next()
else
next() |
…s-helpers AST helpers revisions
For debugging purposes, it would be better if CoffeeScript generated only named functions, ie:
Compiles into:
Questions:
Are there any namespace problems with this, if function names in different scopes collide? If so, what are the consequences (debuggers getting confused, perhaps)? Is it safe to take the final portion of the id as the function name when defining a function on a nested object?
The text was updated successfully, but these errors were encountered: