On Jan 1, 2011, at 5:00 AM, Dmitry A. Soshnikov wrote:

> On 01.01.2011 2:43, fernando trasvina wrote:
>> Hi. very nice explanation but what i don't fully understand is why the 
>> grouping operator makes the parenthesis following the function declaration 
>> work as call.
>> 
>> (function(x){alert(x)}(1));
>> 
>> why this is not treated the same way as:
>> 
>> function(x){}(1);
>> 
> 
> Because inside the grouping operator () there can be only an _expression_. No 
> matter in which way you place a function there (with a call or without it) -- 
> it's treated as FE (function expression). I.e. everything that is placed 
> inside the grouping operator is an expression.
> 
> (1); // grouping operator with expression 1
> ("test"); // with expression "test"
> (function () {}); // with a functional expression
> 
> So in case when you have the following construction:
> 
> (function (x) {alert(x)})(1);
> 
> We have:
> 
> 1. A grouping operator with a function(al) expression inside. It's exactly 
> the sign to the interpreter that this _something inside the grouping 
> operator_ should be _evaluated_ during the _execution_. I.e. we have a 
> function definition there. And this function definition is provided during 
> the runtime.
> 
> 2. Applying (1) on the result of which is returned by the grouping operator 
> (i.e. our just created function). And notice, this is already exactly the 
> _call_ -- (1), but not a grouping operator as it was with a function 
> declaration (FD).
> 
> Since FDs are created on entering the context stage (i.e. before the runtime 
> execution), obviously the following (1) _cannot_ be treated as a _call_. 
> Therefore, the parser considers theses as two constructions: FD and a the 
> following grouping operator:
> 
> function foo(x){alert(x)}(1); // not a call, but syntactically correct
> 
> 
> Backing to FEs. When you have the following construction:
> 
> (function (x) {alert(x)}(1));
> 
> Again it's the sign to the interpreter that _something_ inside the grouping 
> operator should happen (evaluated) at runtime. And what is inside it doesn't 
> matter much at the stage of the parsing. When at runtime the interpreter 
> reaches this line, it just eval(uate)s the expression -- were the expression 
> is again -- creating the function and calling it.

Nice. thx. i read a lil bit after reading this and i think the explanation 
could be improved by including the following areas (not in this particular form 
but this helped me on clearing doubts):

Program:
        Statement
        FunctionDeclaration

Statement:
        Block
        VariableStatement 
        EmptyStatement 
        ExpressionStatement 
        IfStatement 
        IterationStatement 
        ContinueStatement 
        BreakStatement 
        ReturnStatement 
        WithStatement 
        LabelledStatement 
        SwitchStatement 
        ThrowStatement 
        TryStatement 
        DebuggerStatement

FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody } 

FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }

notice the optional clause on Identifier for the FunctionExpression, 
FunctionDeclaration requires Identifier

ExpressionStatement : 
        [lookahead ∉ {{, function}] Expression ;

Expression: (there are too many but you can see them in appendix 3 of ECMA-262, 
FunctionExpression is not directly listed but you can see it on Appendix 5 of 
ECMA-262)

Note: This excludes Block and FunctionExpression

So with this rules at the program level and every place where StatementList is 
used you will always get a FunctionDeclaration.

FunctionDeclarations are never callable, this is the rule for a CallExpression

CallExpression : 
        MemberExpression Arguments 
        CallExpression Arguments 
        CallExpression [ Expression ] 
        CallExpression . IdentifierName

A FunctionDeclaration is not a MemberExpression neither a CallExpression. 
Statement is a not returning construct in the language, it does not "return" 
anything so no CallExpression can be formed.

note that GroupingOperator is a PrimaryExpression not a Statement so it does 
"returns" something.

you say this already but maybe give it more importance.

GroupingOperator
PrimaryExpression:
...
(Expression)

This means that everything inside () is treated as an expression and when you 
put function x(){} inside its parsed as FunctionExpression never as 
FunctionDeclaration

hope it helps, it helped me to understand it better.


Also i would like to give credit and recommend the way Jose Antonio Perez wrote 
the explanation


Happy new year ;)
 
Remember, a A FunctionDeclaration's function is added to the
VariableEnvironment in Variable Instantiation. It is not and cannot be an 
ExpressionStatement.

An FunctionExpression is an ExpressionStatement; it is not bound to the VE 
(VariableEnvironment) on entering an execution context. A FunctionExpression is 
disabiguated from a FunctionDeclaration by the fact that an ExpressionStatement 
can't start with the `function` keyword. 
 
When `f` is called, a VariableEnvironment (VE) is created. For each
FunctionDeclaration in the FunctionBody of `f` the Identifier of that
FD is added to the VE.

The point that Dmitry is trying to explain has nothing to do with the running, 
is a topic within the field of parsing. The grammar that you can see in 
specification is equivalent to 

SourceElements: ( Statement | FunctionDeclaration )+

Program: SourceElements?

FunctionBody: SourceElements?

FunctionDeclaration : function Identifier (FormalParameterList?){FunctionBody}

The source will be divided  into Statements and FunctionDeclarations, and a 
FunctionDeclaration ends in a  "}",  therefore the arguments of a hypothetical 
call haven't connection with "their function", the parser  will place they in 
the following SourceElement, an ExpressionStatement.

i just copied his post here.


Lastly.

I would like to call everyone to not give answers like because its a Syntax 
Error, or Because that is not allowed.
please explain as necessary so people interested on the topic get all the 
relevant information they want (need) if you don't want too well just don't say 
anything but misleading explanations or getting defensive over a mistake like a 
typo or focusing on irrelevant details will not lead us anywhere and people 
will not come to this list to read another fight.

This is of everyone, i got into a pointless discussion here too and i hope i 
never get into one again, please lets focus on improving the community.



> 
> Notice though, that there is one subtle case related with these two similar 
> forms.
> 
> // first function
> var foo = function () {
>  return true;
> }
> 
> // second function
> (function (x) {return x})(1);

Here the trick is just seeing this as the parser does.

var foo = FunctionExpression Arguments Arguments

var foo = CallExpression Arguments

var foo = CallExpression

so at the end you can rewrite the code as the following.

var foo = function () { return true }(function (x) {return x})(1);

Boolean is not callable.

same as: (true)(1);

> 
> The example above has an error (try to explain why). Thus, the following 
> example doesn't:
> 
> // first function
> var foo = function () {
>  return true;
> }
> 
> // second function
> (function (x) {return x}(1));

var foo = FunctionExpression Arguments

Arguments is an ArgumentsList with a single Argument, the result of 
(FunctionExpression Arguments)

FunctionExpression Arguments is a CallExpression

in this case returns 1;

so at the end you can rewrite the code as the following.

var foo = function () { return true }(1);

> 
> Also, try to explain why. Though, the topic of the answer isn't related with 
> the discussed topic. How the answer will change if the `foo` function will 
> return an object of the other kind?

return a Function instance because its the only callable object.

there is another way to "fix" it. just finish the statement after asigning foo.

// first function
var foo = function () {
 return true;
}; // <-- here

// second function
(function (x) {return x})(1);

Maybe this examples should also be included on your article as possible gotchas.

> 
> Dmitry.
> 
>> On Dec 31, 2010, at 7:46 AM, Dmitry A. Soshnikov wrote:
>> 
>>> Just for those who don't use Twitter. I've just edited my 
>>> "ES3.Ch5.Functions" article in respect of explanation the "surrounding 
>>> parentheses". The thing is, that almost _all_ explanations (in books, 
>>> articles, etc) were at least very incomplete (and even wrong).
>>> 
>>> So, why does this code produces a SyntaxError:
>>> 
>>> function () {
>>>  ...
>>> }()
>>> 
>>> // or with name
>>> 
>>> function foo() {
>>>  ...
>>> }();
>>> 
>>> Try to provide as much complete explanation as possible. Also try to answer 
>>> without cheating ;) The correct and full explanation is here: 
>>> http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#question-about-surrounding-parentheses
>>> 
>>> Dmitry.
>>> 
>>> P.S.: Happy New Year!
>>> 
>>> -- 
>>> To view archived discussions from the original JSMentors Mailman list: 
>>> http://www.mail-archive.com/[email protected]/
>>> 
>>> To search via a non-Google archive, visit here: 
>>> http://www.mail-archive.com/[email protected]/
>>> 
>>> To unsubscribe from this group, send email to
>>> [email protected]
> 
> -- 
> To view archived discussions from the original JSMentors Mailman list: 
> http://www.mail-archive.com/[email protected]/
> 
> To search via a non-Google archive, visit here: 
> http://www.mail-archive.com/[email protected]/
> 
> To unsubscribe from this group, send email to
> [email protected]

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/[email protected]/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/[email protected]/

To unsubscribe from this group, send email to
[email protected]

Reply via email to