Имеет ли какой-либо другой язык, кроме JavaScript, разницу между местоположениями начала скобок (такая же строка и следующая строка)?

Сегодня, когда я случайно читал книгу JavaScript O'Reilly, я нашел одну интересную вещь (стр. 27 для справки).

В Javascript в некоторых случаях существует разница, если местоположение начала скобки отличается.

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

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

Пока

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

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

JSfiddle Demo

Есть ли у любого другого языка такое поведение? Если да, то мне пришлось бы изменить свою привычку наверняка..:)

Меня в основном интересуют PHP, C, С++, Java и ruby.

Ответ 1

Любой язык, который не полагается на точки с запятой (но вместо этого на новые строки), чтобы разграничить заявления, потенциально позволяет это. Рассмотрим Python:

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

Возможно, вы сможете построить аналогичный случай в Visual Basic, но не в верхней части моей головы. Я не могу понять, как из-за того, что VB довольно ограничительный, где могут быть размещены значения. Но следующее должно работать, если статический анализатор не жалуется на недостижимый код:

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

Из упомянутых вами языков Ruby имеет то же свойство. PHP, C, С++ и Java не просто потому, что они отбрасывают новую строку как пробел и требуют, чтобы точки с запятой ограничивали выражения.

Вот эквивалентный код из примера Python в Ruby:

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

Ответ 2

Переводчик JavaScript автоматически добавляет ; в конце каждой строки, если он не находит его (за некоторыми исключениями, не попадая сюда:).

Таким образом, в основном проблема заключается не в местоположении скобок (которое здесь представляет собой литерал объекта, а не блок кода, как на большинстве языков), но эта небольшая "функция", которая заставляет ваш первый пример return ; = > undefined. Вы можете проверить поведение return в спецификации ES5.

Для других языков с аналогичным поведением проверьте ответ Konrad.

Ответ 3

Конечно. Язык i0 > демонстрирует очень похожее поведение (хотя и с разными эффектами). Как объясняется там:

Фактически, происходит то, что на официальном языке используются точки с запятой, как и на C или Java, но они автоматически вставлены в конце каждой строки, которая похожа на конец инструкции. Вам не нужно вводить их самостоятельно.

.. чик...

Этот подход обеспечивает чистоту, без кода с запятой. Одно удивление состоит в том, что важно разместить открытую фигуру конструкции, такую ​​как оператор if в той же строке, что и if; если вы этого не сделаете, есть ситуации, которые не могут компилироваться или могут дать неправильный результат. Язык в некоторой степени заставляет стиль фигурной скобки.

Втайне, я думаю, что Роб Пайк просто хотел оправдания, чтобы потребовать One True Brace Style.

Ответ 4

Ответ на этот вопрос довольно прост. Любой язык, который имеет "автоматическую точку с запятой", может оказаться в затруднительном положении на этой линии. Проблема с этим

return
{
     name: 'rajat'
};

.. является то, что движок js вставляет точку с запятой после оператора return; (и, следовательно, возвращает undefined). Этот пример является хорошей причиной для открытия фигурных скобок всегда с правой стороны и никогда не с левой стороны. Поскольку вы уже правильно заметили, если в одной строке есть фигурная скобка, интерпретатор заметит это и не может вставить точку с запятой.

Ответ 5

FWIW, JSLint сообщает о нескольких предупреждениях с этим синтаксисом:

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

Ответ 6

Первым языком, на котором я столкнулся, был awk (который также имеет свою долю синтаксиса "странности", необязательные полуколоны, конкатенацию строк с использованием только пробелов и т.д.) Я думаю, что дизайнеры DTrace, основанные на синтаксисе D свободно на awk, имели достаточный смысл НЕ копировать эти функции, но я не могу вспомнить с головы. Простой пример (подсчет количества тегов ENTITY в DTD с моего 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

Если этот маленький script был написан с помощью скобки на отдельной строке, это произойдет:

$ 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
$