Giter Club home page Giter Club logo

Comments (90)

sethvargo avatar sethvargo commented on July 23, 2024 4

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):

The golden rule of CoffeeScript is: "It's just JavaScript". The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. You can use any existing JavaScript library seamlessly from CoffeeScript (and vice-versa).

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.

from coffeescript.

SuperPaintman avatar SuperPaintman commented on July 23, 2024 3

@penne12

       |=._
       |    \
       |     |
  >>>--|-----(-(arg)>
       |     |
       |    /
       |=*''

sorry :D

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024 2

Let's be pleasant, folks.

from coffeescript.

rlidwka avatar rlidwka commented on July 23, 2024 1

@michaelficarra

If you really care, add a displayName property to your functions after defining them.

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... :)

from coffeescript.

rlidwka avatar rlidwka commented on July 23, 2024 1

@em:
Node.js and Chrome are using Function.name to build stack trace (see here and here).

Sometimes, it will print my function name instead of unknown source saving me some seconds of searching... reason enough for me.

For production enviroment with some buggy browsers we can always turn off this feature, of course.

from coffeescript.

connec avatar connec commented on July 23, 2024 1

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()

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Reference for named functions in JS:
http://yura.thinkweb2.com/named-function-expressions/

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

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.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

There's a problem with functions with the same name as variable
E.g.

x:1
y: {}
y.x: => 3

should either

  1. throw a compiler error,
  2. make the function anonymous in this instance
  3. name the something else

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

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 true.

x: 1
y: {}
y.x: => 3

print(x is 1)
print(typeof(y.x) is 'function')
print(y.x() is 3)
print(y.x.name is 'x')

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Let me know if you're hitting any errors or unexpected behavior, with a test case, and I'll reopen this ticket.

from coffeescript.

TrevorBurnham avatar TrevorBurnham commented on July 23, 2024

One year later...

I'm wondering why this behavior was changed, so that square = (x) -> x * x no longer gives the resulting function the name square (which would be useful for stack traces).

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?

from coffeescript.

TrevorBurnham avatar TrevorBurnham commented on July 23, 2024

Ah, just found the full explanation in the FAQ here.

from coffeescript.

sethvargo avatar sethvargo commented on July 23, 2024

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 arguments.callee.caller.name... but that's impossible when everything is an anonymous function when compiled.

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 :'(

from coffeescript.

em avatar em commented on July 23, 2024

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.

from coffeescript.

sethvargo avatar sethvargo commented on July 23, 2024

When was this fixed? Can someone cite a commit?

from coffeescript.

michaelficarra avatar michaelficarra commented on July 23, 2024

@sethvargo: it hasn't been fixed and never will. There's no need for NFEs or FDs. Your example above is not convincing. arguments.callee is a poison pill in strict mode, and highly highly discouraged outside of strict mode. Like eval, it doesn't allow the interpreter to do almost all of its optimisations. If you really care, add a displayName property to your functions after defining them.

from coffeescript.

em avatar em commented on July 23, 2024

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 = {
foo: function() { /.../ }
, bar: function() { /... }
};

function patch(functionToPatch) {
module[functionToPatch.name] = functionToPatch;
}

patch(function foo() {
// my replacement 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.

from coffeescript.

michaelficarra avatar michaelficarra commented on July 23, 2024

@em: name is a non-standard property. That's what you get for relying on it being set by your interpreter. You should be assigning an identifying value of your own. Are you also going to rely on iteration order of keys in a for-in loop (another assumption people often make that's not guaranteed, in case you didn't know) and then complain about coffeescript?

edit: regarding debugging, most debuggers actually look at the displayName property, which you should be setting yourself.

from coffeescript.

em avatar em commented on July 23, 2024

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.

from coffeescript.

 avatar commented on July 23, 2024

IIRC, var square = function square(){ ... }; or square = function square() { ... }; should work...the leakage in IE occurs when the reference and the function name are different (var a = function b() { ... }). The square variable declaration is still overwritten with the square function declaration, but, because they are identical, the former should be garbage collected immediately.

Pinging @jdalton; he clarified this point for me some time ago.

from coffeescript.

michaelficarra avatar michaelficarra commented on July 23, 2024

@em:

named-functions and anonymous-functions. They're different things.

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.

The IE bug is not standard either, so what's your point?

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 with statements or unqualified access to the undefined global. Sure, some interpreters have errors related to those features, but those are only reasons not to use the features. We don't include the features because they're just not useful.

debugging and profiling use function.name to build call stack

As I said above, they use displayName first. You should be defining that value if you want better debugging support.

note: in case you aren't familiar with the common acronyms, NFE = named function expression, FE = function expression, FD = function declaration

from coffeescript.

michaelficarra avatar michaelficarra commented on July 23, 2024

@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.

from coffeescript.

jdalton avatar jdalton commented on July 23, 2024

I was summoned by @kitcambridge to confirm that var square = function square(){ ... }; takes care of the IE memory consumption problem. I used this in my code/projects to handle it.

from coffeescript.

sethvargo avatar sethvargo commented on July 23, 2024

Furthermore, labeling this as "fixed" was quite misleading... I suggested "blatantly ignored due to overzealous opinions"...

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

@sethvargo At the time the issue was closed, named functions existed on master. They were later removed for the reasons detailed above.

from coffeescript.

sethvargo avatar sethvargo commented on July 23, 2024

Well, someone should remove the label... Without reading the entire thread, it's very easy to think this issue has been resolved...

from coffeescript.

michaelficarra avatar michaelficarra commented on July 23, 2024

@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 undefined global or a with statement (without the god-awful backticks) in your output JS. But that doesn't prevent you from doing anything. It's still a one-to-one (injective) compilation, but it's not onto (surjective). I think you're confusing the injective relationship with a bijective relationship. Being injective but no surjective is not a problem in our case. The functionality of the JS constructs that don't have CS equivalents can be accomplished through combinations of CS constructs.

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.

from coffeescript.

em avatar em commented on July 23, 2024

Yeah, I don't see any hostility either. My "Sheesh"? Sorry, it resonated as light-hearted in my head.

from coffeescript.

rlidwka avatar rlidwka commented on July 23, 2024

Well... fortunately, it is one-line fix. I've just replaced if (this.ctor) condition with if (this.name !== undefined) in nodes.js:

code = 'function';
/*if (this.ctor)*/ if (this.name !== undefined) code += ' ' + this.name;
code += '(' + vars.join(', ') + ') {';

and now it works just fine.

from coffeescript.

em avatar em commented on July 23, 2024

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.

from coffeescript.

zot avatar zot commented on July 23, 2024

@rlidwka Thanks for the mod! I can see functions in my stack traces, now

from coffeescript.

pke avatar pke commented on July 23, 2024

Thanks @rlidwka ! Will implement this in our CS compiler

from coffeescript.

devinrhode2 avatar devinrhode2 commented on July 23, 2024

@pke what fork have you implemented this in?

from coffeescript.

pke avatar pke commented on July 23, 2024

@devinrhode2 unfort did not have time, but maybe @milgner can take another look.

from coffeescript.

truongsinh avatar truongsinh commented on July 23, 2024

Small note on this issue, as I understand, @jashkenas will never except FD. In my code, I need recursion, but argument.calle is deprecated https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee

For example, this syntax worked:

function factorial (n) {
    return !(n > 1) ? 1 : factorial(n - 1) * n;
}

but:

[1,2,3,4,5].map(function (n) {
    return !(n > 1) ? 1 : /* what goes here? */ (n - 1) * n;
});

did not. To get around this arguments.callee was added so you could do

[1,2,3,4,5].map(function (n) {
    return !(n > 1) ? 1 : arguments.callee(n - 1) * n;
});

and then for bla bla bla, it is deprecated. ECMAScript 3 resolved these issues by allowing named function expressions. For example:

[1,2,3,4,5].map(function factorial (n) {
    return !(n > 1) ? 1 : factorial(n-1)*n;
});
// typeof factorial === 'undefined'

Now, the tricky part:

[1,2,3,4,5].map factorial = (n)->
  unless n > 1 then 1 else factorial(n-1) * n

will be translated into:

var factorial;
[1,2,3,4,5].map(factorial = function(n) {
    return !(n > 1) ? 1 : factorial(n-1)*n;
});
// typeof factorial === 'function'

But hey, I don't want var leak. So, just do the closure

[1,2,3,4,5].map -> (factorial = (n)->
  unless n > 1 then 1 else factorial(n-1) * n
)()

will be:

[1,2,3,4,5].map(function() {
  var factorial;
  return factorial = function(n) {
    return !(n > 1) ? 1 : factorial(n-1)*n;
  };
}());
// typeof factorial === 'undefined'

Anyway, no comment on performance.

from coffeescript.

redexp avatar redexp commented on July 23, 2024

Hey guys. Maybe we can create some version of coffeescript for modern browsers? With named functions, without checks for indexOf in arrays and so on? I realy don't care about IE8 and I think there a lot of devs just like me. Maybe someone knows such fork of coffee? Maybe you know good book or article how I can write such coffee?
Many thanks.

from coffeescript.

xixixao avatar xixixao commented on July 23, 2024

This makes me cry (not really, but it's sad).

from coffeescript.

redexp avatar redexp commented on July 23, 2024

Created fork with named functions https://github.com/redexp/coffee-script
Syntax:

plus(a, b) -> a + b

result:

function plus(a, b) {
  return a + b;
};
[1..5].map factorial(n) -> 
    unless n > 1 then 1 else factorial(n - 1) * n

If named function in the end of code then it will not be returned

test ->
    asd() ->
test(function(){
  function asd() {};
});

because I want to do like this

test ->
    if valid() then save() 

    valid() ->
    save() ->

if save() will be after return then I will not be able to use it
But you can assign it

x = asd() ->

Very important last thing

asd() ->
asd () ->
function asd() {};
asd(function() {});

from coffeescript.

xixixao avatar xixixao commented on July 23, 2024

@redexp You don't need new syntax, you can use the current name = ->, this used to be part of CS.

from coffeescript.

redexp avatar redexp commented on July 23, 2024

@xixixao actually I need. With name = -> you first of all declare all functions then you using them. With name() -> you can use first and in the end of code declare. Also I really don't like when in debugger all functions in Call stack is anonymous.

from coffeescript.

davidchambers avatar davidchambers commented on July 23, 2024

@redexp, I think what @xixixao is saying is thatโ€ฆ

name = ->

could compile toโ€ฆ

function name() {}

orโ€ฆ

var name = function name() {};

depending on whether you want to support hoisting. It should be possible to have the compiler output your desired JavaScript without new CoffeeScript syntax.

from coffeescript.

redexp avatar redexp commented on July 23, 2024

@davidchambers sorry, can you show example when name = -> will be compiled to function name(){}

from coffeescript.

mklement0 avatar mklement0 commented on July 23, 2024

@redexp: I think the argument is that in your fork you could choose to retain the existing syntax on the CoffeeScript side (name = ->) and merely modify the compilation to translate name = -> into function name().

from coffeescript.

redexp avatar redexp commented on July 23, 2024

@mklement0 @xixixao it will looks weird. New syntax is like notice which shows that here is something unusual and regular compiler is not enough

One more thing. I need named function to make things like this https://leanpub.com/javascript-allonge/read#leanpub-auto-modules

from coffeescript.

xixixao avatar xixixao commented on July 23, 2024

@redexp This is how it used to compile before the IE bug was discovered (as jashkenas notes above). In CoffeeScript you cannot use stuff before defining it, so this would be valid:

DrawModule = do ->

  # public methods
  drawLine = (screen, leftPoint, rightPoint) -> ...

  # private helpers
  bitBlt = (screen, ...) -> ...

  drawLine: drawLine

But you can simply use static classes as modules and keep the desired order:

class DrawModule

  # public methods
  @drawLine = (screen, leftPoint, rightPoint) -> ...

  # private helpers
  bitBlt = (screen, ...) -> ...

I said before that not being able to define functions after using them is my biggest CS regret, but I tend to use classes much more these days because they make me think about splitting up my code (and if I was writing something purely functional, I'd use the above pattern).

from coffeescript.

jfelchner avatar jfelchner commented on July 23, 2024

Ok, so I hate to revive this extremely old thread, but after reading through all of the other threads listed in the FAQ under this issue, I wanted to get some things clear considering there are a lot of sources of information and these appears to be more or less the place people go to look for this issue.

And again, I apologize in advance @michaelficarra.

  1. Is this or is this not fixed in redux? michaelficarra/CoffeeScriptRedux#131 ended with a revert, but this issue is labeled as fixed-in-redux

  2. If the answer to number 1 is "yes", will it be merged into CS proper?

    If the answer to number 1 and number 2 was "yes", feel free to ignore the rest of these questions.

  3. Is the only reasoning behind not doing this because of the IE <= 8 bug?

  4. If the answer to number 3 is "yes" then, at what point can we safely add it back? IE <= 8 is less than 6.5% as of last month.

  5. If it isn't added back as a default, given that even @jashkenas said that it was a 2 line change is there a chance this will become a compiler option?

Thanks all.

from coffeescript.

michaelficarra avatar michaelficarra commented on July 23, 2024

@jfelchner: The PR for CoffeeScriptRedux was ready to be merged and safe for old IEs. But I closed it because there was a lot of fear-mongering and I didn't want to jeopardise the community's trust in my compiler. We can solve this by using the strategy in the linked PR, but we probably won't revisit this for a while. Also, for the foreseeable future, the officially-endorsed compiler will compile to IE6+ compatible JS. CSR was designed so that it may be extended to use additional compilation targets (e.g. ES6); see slides 42-43 of https://speakerdeck.com/michaelficarra/an-analysis-of-the-redesign-of-the-coffeescript-compiler for an example.

from coffeescript.

m1sta avatar m1sta commented on July 23, 2024

@michaelficarra Is there an easy way for me to grab the PR you mention? Lack of hoisted functions is the only genuine issue I have with coffeescript. No point in opening another issue about it from what I've read here so I figure I'll just have to maintain a patch for my own use.

from coffeescript.

michaelficarra avatar michaelficarra commented on July 23, 2024

That diff will not apply to this project. You can apply the same concepts from the linked PR to this project, though I can't guarantee it will be a simple 8-line diff as it was in CSR.

from coffeescript.

carlsmith avatar carlsmith commented on July 23, 2024

Named functions would be really helpful for constructor functions. The objects you construct can easily have their constructor bound to them, so you can do isType Constructor, instance, but there's no way to get a string of the name, so you can't implement a function that does isType "Constructor", instance. This is a fairly serious issue for me personally right now. A new assignment operator is an option.

square =: (x) -> x * x

from coffeescript.

devinrhode2 avatar devinrhode2 commented on July 23, 2024

ES6 now specifies that var func = function(){}; creates a named function, which should ultimately put this issue to rest. @carlsmith if you really need named functions, dig back through the commit log, @michaelficarra added the feature on some thread I was on but then reverted it, so iirc it is somewhere in the commit log of coffeescriptredux

from coffeescript.

carlsmith avatar carlsmith commented on July 23, 2024

@devinrhode2 - I didn't know that. Do you have a link? It'd be nice to know if this going to be applied to all JS code, or only the code in ES6 classes and modules. If JS engines are going to make lambda assignments name the function, that would solve the problem in some cases. Will a.b = -> name the function b?

Hacking the compiler isn't really an option for me. The app lets the user enter CoffeeScript, so a fork would need to be maintained with docs and everything. It just makes sense to stick to the de facto standard.

from coffeescript.

epidemian avatar epidemian commented on July 23, 2024

@devinrhode2 - I didn't know that. Do you have a link?

http://wiki.ecmascript.org/doku.php?id=harmony:function_name_property

As far as i understand, JS engines would apply the new function naming semantics to all JS code, not just ES6 classes/methods.

IDK if this proposal has been formalized in the ECMAScript spec though.

Will a.b = -> name the function b?

Yes! ๐Ÿ˜บ

from coffeescript.

carlsmith avatar carlsmith commented on July 23, 2024

@epidemian - Thanks man. Looks good.

from coffeescript.

objectkit avatar objectkit commented on July 23, 2024

I know this is closed, but just in case I missed anything in subsequent releases, the capability to transpile named functions by reference name would be great, esp in node contexts, and in many web browsers. Daft general example, already well understood. From this

methodLogger = 
    log: (method) ->
        console.log method.name

A = ->

methodLogger.log A # "A"

to this

var A, methodLogger;

methodLogger = {
  log: function(method) {
    return console.log(method.name);
  }
};

function A () {};

methodLogger.log(A); // "A"

from this at present

var A, methodLogger;

methodLogger = {
  log: function(method) {
    return console.log(method.name);
  }
};

A = function() {};

methodLogger.log(A); // "undefined"

really would be useful in many situations IMO e.g. custom error logging, bindings, application contexts, ... Perhaps a compiler option? Obviously not all deployment environments will support Function#name properties yet, but in certain deployment specific environments e.g. WebKit based apps outside of the browser context... Thats borderline everyday as far as I can see... my tuppence. Out of here!

from coffeescript.

benaubin avatar benaubin commented on July 23, 2024

This is an awful idea, on a already closed topic, but why not:

-(test)>
  # do something

from coffeescript.

pke avatar pke commented on July 23, 2024

Just got a notification that this is still being discussed and not available in CS.
Happily unsubscribing now because I have moved on to ES6 some time ago anyway.

from coffeescript.

youurayy avatar youurayy commented on July 23, 2024

pls at least change the label from fixed to wontfix

from coffeescript.

carlsmith avatar carlsmith commented on July 23, 2024

If ES6 will fix it for us, then it's essentially fixed. Just have to be patient.
http://wiki.ecmascript.org/doku.php?id=harmony:function_name_property

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

I really need named functions instead of anonymous functions assigned to variables!
When stupid-ass support for IE 6 will be dropped??

from coffeescript.

connec avatar connec commented on July 23, 2024

@avalanche1 what use-case do you have that demands named functions?

IE6 is being dropped in the 2 branch, though there is currently no plans to compile to named functions as modern environments can determine function names from the assigned variable.

var foo, bar
(foo = function () {}).name // 'foo'
(bar = () => {}).name       // 'bar'

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

I need this for:
1)'name' property of a function
According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name only latest Chrome supports names for anonymous functions:
image
2) function hoisting. I DO like to code like:

doStuff()
doOtherStuff()

doStuff = ->stuff
doOtherStuff = ->other stuff

(pls dont tell me it's 'bad', cause I like to have freedom of choice, you know - if I want to code in a 'bad' way - that's my choice)

from coffeescript.

epidemian avatar epidemian commented on July 23, 2024
  1. function hoisting. I DO like to code like:

The problem with that is that the assignment operator means two completely different things depending on whether the assigned value is a (literal) function or some other value. Personally, i dislike that sort of complexity on language constructs. If named functions where to be added, they should use some other syntactical form than the existing assignment.

from coffeescript.

connec avatar connec commented on July 23, 2024

@avalanche1 cool, thanks for the references. I didn't realised anonymous function names were only available in V8.

Even if we started using named functions, which we could feasibly do in 2, I don't think hoisting would change, since that would make a function assignment different from any other assignment, e.g. we would probably compile:

doStuff = ->

doStuffWithThis = =>

into

var doStuff, doStuffWithThis
doStuff = function doStuff () {}

// ruh roh, bound function syntax doesn't allow for a name
doStuffWithThis = () => {}

SO I'm not sure the status of this issue should change, carlsmith's comment above still stands - we can't reliable add names to all functions, so we just have to wait for JS engines to catch up with the spec.

Discussions of a "named function declaration" syntax have ranged back and forth over the years, but those discussions are independent of IE6.

from coffeescript.

benaubin avatar benaubin commented on July 23, 2024

Wait a second.... just noticed that CoffeeScript in fact does support named functions currently. It's just not pretty. But if you need it, it's there. The secret is how coffeescript implements classes:

class namedFunction then constructor: ->
    doSomething()

compiles to:

var namedFunction;

namedFunction = (function() {
  function namedFunction() {
    doSomething();
  }

  return namedFunction;

})();

making namedFunction a named function. Yay!

Or, you can just use Javascript interpolation

`function test(){`; do -> # the `do ->` part is optional, but it allows for indentation, making your code a bit clearer
  doSomething()
`}`

from coffeescript.

vendethiel avatar vendethiel commented on July 23, 2024

Sadly, that pollutes the global namespace.

huh? how so?

from coffeescript.

vendethiel avatar vendethiel commented on July 23, 2024

@vendethiel that better?

No. I don't see any difference.

which returns the named function & doesn't pollute the local namespace:

Sure, but you still need to assign it to something. Which will "pollute" the local namespace much the same way.

Or, you can just use Javascript interpolation

That also "pollutes" the local namespace the same way

from coffeescript.

benaubin avatar benaubin commented on July 23, 2024

@vendethiel

Sure - but in some cases, you could be passing a named function as an argument - idk. I guess I'll take out the whole part.

from coffeescript.

vendethiel avatar vendethiel commented on July 23, 2024

@jashkenas why reopen?

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

@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.

from coffeescript.

connec avatar connec commented on July 23, 2024

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).

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

I'd be concerned about users expecting the same behaviour from bound functions, for which there is no named syntax.

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);

from coffeescript.

connec avatar connec commented on July 23, 2024

Fair point. I was thinking of the 2 branch where bound functions are now compiled to ES6 arrow functions

hello = =>
hello = () => {};

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Oh, of course -- sorry. I forgot about those.

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

@jashkenas what about function hoisting? let's also support that!

@penne12 thanks for ``function test(){; do -> - didn't know about the `do ->` part ๐Ÿ‘

from coffeescript.

GeoffreyBooth avatar GeoffreyBooth commented on July 23, 2024

@jashkenas We were discussing named classes here in the CS2 reimplementation of classes. Basically the CS2 version of classes will output code like var Foo; Foo = class Foo {. I was suggesting that if weโ€™re doing this, we should be consistent and do the same for functions.

So yes, I think function declarations like var foo; foo = function foo () { would be great. Even if we canโ€™t do it in all circumstances, we might as well do it where we can to make debugging easier. Iโ€™m not worried about the increase in file size, because CS output wasnโ€™t meant to be minified in the first place, and a minifier would make short work of this duplication.

from coffeescript.

mauskin avatar mauskin commented on July 23, 2024

what about function hoisting?

@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.

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

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.

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

Void

WHOA! Super duper kool!
3a.m. and I've just found that named functions DO EXIST in Coffeescript. (Well, sort of named.. ๐Ÿ˜ƒ )
And they ARE hoisted to!! (When you declare in the following way:)

foo()
foo = f = ->log arguments.callee.name
// foo

The following works for objects:

obj=
  foo: foo = ->log arguments.callee.name

Finally we can drop all the backtick voodoo and other magic. Hurray! ๐Ÿ˜บ

I think this can be closed.
But I think the Functions section of the docs should be amended.

from coffeescript.

benaubin avatar benaubin commented on July 23, 2024

@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.

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

@penne12 , huh?

  1. Don't spoil all the happiness!
  2. Care to explain?

R u talking about argumetns.callee? Well, it doesnt matter if it's being deprecated - functions are hoisted and can be called before being declared - KOOL!
Pllus, I need arguments.callee.name exclusively for debugging & testing purposes.

from coffeescript.

benaubin avatar benaubin commented on July 23, 2024

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).

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

I see.
Does this feature have a name? I'd like to lookup JS engine compatibility.

from coffeescript.

GeoffreyBooth avatar GeoffreyBooth commented on July 23, 2024

@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

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

Ahem, after further investigating, it turns out that what I've posted above is actually void.
I was testing aforementionned techniques in Coffeescript Console extension for Chrome;
On the first run it throws en error, on the second, though - it works as described above.
Guess, that's the effect of working till 3AM.

Anyway:
still no function hoisting;
function name inferred from variable assignement works only if JS engine supports it.

from coffeescript.

benaubin avatar benaubin commented on July 23, 2024

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.

from coffeescript.

avalanche1 avatar avalanche1 commented on July 23, 2024

@penne12 , thanks mate!
Thankfully my dev environment supports named functions. And I'll make sure not to use them in production builds.

from coffeescript.

GeoffreyBooth avatar GeoffreyBooth commented on July 23, 2024

Per #4531, it was decided that CoffeeScript will not be supporting function declarations (outputting function foo() as opposed to foo = function ()) or outputting named functions as part of the currently output function expressions (so still foo = function(), not foo = function foo()).

from coffeescript.

dotnetCarpenter avatar dotnetCarpenter commented on July 23, 2024

@GeoffreyBooth I was cleaning up an old coffeescript project and came across arguments.callee, because coffeescript does not have support for named functions.

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 \name is the anti Lambda Abstractions hehe ;). Joke aside, I don't know how the syntax should be, but \ is an anonymous function in Haskell, so perhaps it could be a named function in coffee.

from coffeescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.