Does any other language other than JavaScript have a difference between brace start locations (same line and next line)?

JavascriptLanguage AgnosticProgramming LanguagesLanguage Design

Javascript Problem Overview


Today, while I was randomly reading the JavaScript patterns O'Reilly book, I found one interesting thing (page 27 for reference).

In Javascript, in some cases, there is a difference if the brace start location is different.

function test_function1() {
    return
    {
        name: 'rajat'
    };
}

var obj = test_function1();
alert(obj);  //Shows "undefined"

While

function test_function2() {
    return {
        name: 'rajat'
    };
}

var obj = test_function2();
alert(obj); //Shows object

JSfiddle Demo

Does any other language out there have such behavior? If so, then I would have to change my habit for sure..:)

I am mainly concerned about PHP, C, C++, Java, and ruby.

Javascript Solutions


Solution 1 - Javascript

Any language that doesn’t rely on semicolons (but instead on newlines) to delimit statements potentially allows this. Consider Python:

>>> def foo():
...   return
...   { 1: 2 }
... 
>>> def bar():
...   return { 1: 2 }
... 
>>> foo()
>>> bar()
{1: 2}

You might be able to construct a similar case in Visual Basic but off the top of my head I can’t figure out how because VB is pretty restrictive in where values may be placed. But the following should work, unless the static analyser complains about unreachable code:

Try
    Throw New Exception()
Catch ex As Exception
    Throw ex.GetBaseException()
End Try

' versus

Try
    Throw New Exception()
Catch ex As Exception
    Throw
    ex.GetBaseException()
End Try

From the languages you mentioned, Ruby has the same property. PHP, C, C++ and Java do not simply because they discard newline as whitespace, and require semicolons to delimit statements.

Here’s the equivalent code from the Python example in Ruby:

>> def foo
>>   return { 1 => 2 }
>> end
=> nil
>> def bar
>>   return
>>   { 1 => 2 }
>> end
=> nil
>> foo
=> {1=>2}
>> bar
=> nil

Solution 2 - Javascript

The JavaScript interpreter automatically adds a ; at the end of each line if it doesn't find one (with some exceptions, not getting into them here :).

So basically the issue is not the braces' location (which here represent an object literal, not a code block as in most languages), but this little "feature" that forces your first example to return ; => undefined. You can check out the behavior of return in the ES5 spec.

For other languages that have similar behavior, check out Konrad's answer.

Solution 3 - Javascript

Most certainly. Google's go programming language exhibits a very similar behavior (albeit with different effects). As explained there:

>In fact, what happens is that the formal language uses semicolons, much as in C or Java, but they are inserted automatically at the end of every line that looks like the end of a statement. You don't need to type them yourself. > > ..snip... > >This approach makes for clean-looking, semicolon-free code. The one surprise is that it's important to put the opening brace of a construct such as an if statement on the same line as the if; if you don't, there are situations that may not compile or may give the wrong result. The language forces the brace style to some extent.

Secretly, I think Rob Pike just wanted an excuse to require the One True Brace Style.

Solution 4 - Javascript

The answer to that question is fairly easy. Any language that has "automatic semicolon insertion" might be in trouble on that line. The problem with this

return
{
     name: 'rajat'
};

..is that the js engine will insert a semicolon after the return; statement (and therefore, return undefined). This example is a good reason to open curly brackets always on the right side and never on the left side also. Since you already correctly noticed, if there is a curly bracket in the same line, the interpretator will notice that and can't insert a semicolon.

Solution 5 - Javascript

FWIW, JSLint reports several warnings with that syntax:

$ jslint -stdin
function foo(){
  return
  { x: "y" };
}
^D
(3): lint warning: unexpected end of line; it is ambiguous whether these lines are part of the same statement
  return
........^

(3): lint warning: missing semicolon
  { x: "y" };
..^

(3): lint warning: unreachable code
  { x: "y" };
..^

(3): lint warning: meaningless block; curly braces have no impact
  { x: "y" };
..^

(3): lint warning: use of label
  { x: "y" };
.....^

(3): lint warning: missing semicolon
  { x: "y" };
...........^

(3): lint warning: empty statement or extra semicolon
  { x: "y" };
............^


0 error(s), 7 warning(s)

Solution 6 - Javascript

The first language where I came across this was awk (which also has its share of syntax "oddities"; optional semi colons, string concatenation using only whitespace and so on...) I think the DTrace designers, which based the D syntax loosely on awk, had enough sense to NOT copy these features, but I can't remember off the top of my head. A simple example (counting the number of ENTITY tags in a DTD, from my Mac):

$ cat printEntities.awk 
# This prints all lines where the string ENTITY occurs
/ENTITY/ {
  print $0
}
$ awk -f printEntities.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     119

If this little script instead were written with the brace on a line of its own, this is what would happen:

$ cat printAll.awk 
# Because of the brace placement, the print statement will be executed
# for all lines in the input file
# Lines containing the string ENTITY will be printed twice,
# because print is the default action, if no other action is specified
/ENTITY/
{ 
   print $0 
}
$ awk -f printAll.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     603
$ /bin/cat < /usr/share/texinfo/texinfo.dtd | wc -l
     484
$ 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRajat SinghalView Question on Stackoverflow
Solution 1 - JavascriptKonrad RudolphView Answer on Stackoverflow
Solution 2 - JavascriptAlex CiminianView Answer on Stackoverflow
Solution 3 - JavascriptDaveView Answer on Stackoverflow
Solution 4 - JavascriptjAndyView Answer on Stackoverflow
Solution 5 - JavascriptBrandanView Answer on Stackoverflow
Solution 6 - JavascriptAnders SView Answer on Stackoverflow