Есть ли какой-нибудь другой язык, кроме JavaScript, имеет разницу между начальными местоположениями фигурных скобок (та же строка и следующая строка)? - PullRequest
91 голосов
/ 08 февраля 2012

Сегодня, когда я случайно читал книгу о шаблонах JavaScript О'Рейли, я обнаружил одну интересную вещь (страница 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, C ++, Java и ruby.

Ответы [ 6 ]

53 голосов
/ 08 февраля 2012

Любой язык , который не использует точки с запятой (но вместо новой строки) для разграничения операторов, потенциально позволяет это сделать. Рассмотрим 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, C ++ и Java делают это не просто потому, что отбрасывают символ новой строки как пробел и требуют точки с запятой для разделения операторов.

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

>> def foo
>>   return { 1 => 2 }
>> end
=> nil
>> def bar
>>   return
>>   { 1 => 2 }
>> end
=> nil
>> foo
=> {1=>2}
>> bar
=> nil
40 голосов
/ 08 февраля 2012

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

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

Для других языков, имеющих подобное поведение, посмотрите ответ Конрада .

26 голосов
/ 08 февраля 2012

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

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

.. чик ...

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

Тайно, я думаю, что Роб Пайк просто хотел оправдания, чтобы требовать Единого Истинного Стиля.

14 голосов
/ 08 февраля 2012

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

return
{
     name: 'rajat'
};

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

6 голосов
/ 11 февраля 2012

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)
1 голос
/ 17 февраля 2012

Первым языком, с которым я столкнулся, был 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

Если бы этот маленький скрипт вместо этого был написан со скобкой в ​​отдельной строке, это то, что произошло бы:

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