JavaScript以外の他の言語では、中括弧の開始位置に違いがありますか(同じ行と次の行)?


91

今日、O'ReillyのJavaScriptパターンをランダムに読んでいるときに、興味深いことが1つ見つかりました(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デモ

他の言語にそのような振る舞いはありますか?もしそうなら、私は確かに私の習慣を変更する必要があります.. :)

私は主にPHP、C、C ++、Java、およびルビーについて心配しています。


1
ChromeとIE9で再現、良いキャッチ:P
ギデオン

4
ホワイトスペースの感度は動作するように作成できます--- Pythonまたはラインモードfortranを見てください---しかし、微妙なホワイトスペースの感度は悪魔の働きです。ガ!これはmakeと同じくらい悪いです!
dmckee ---元モデレーターの子猫2012

これは印象的です!いい発見!
CheckRaise、

ここで、JavaScriptがこのように動作する理由を知りたいと思います。
CheckRaise、

4
@CheckRaise:私はここのルールをまとめる:blogs.msdn.com/b/ericlippert/archive/2004/02/02/...
エリックリペット

回答:


53

任意の範囲を定めるステートメントにセミコロン(代わりに改行上)に依存しない言語では、潜在的にこれを可能にします。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は、改行を空白として破棄し、ステートメントを区切るためにセミコロンを必要とするだけではありません。

RubyのPythonの例からの同等のコードを次に示します。

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

2
行継続シーケンス「_」を使用しない限り、VB ステートメントが複数行にまたがることを決して許可しないため、VBの例はまったく意味をなさない。
phoog

2
VB.NETが暗黙の行継続をサポートするいくつかのコンテキストがあるので、仕様を確認しただけなので、前のコメントを取り消します。私はそれがあることはかなり明白だから、しかし、経験豊富なVBプログラマが「落とし穴」この例を考えることはないだろうThrowし、ex.GetBaseException()別々の論理行です。より具体的には、Basicは歴史的にステートメントを区切るために行を使用するので、「落とし穴」は、プログラマーが新しい論理行に新しいステートメントを作成したと考えているがそうしていない状況である可能性が高くなります。
phoog

@phoog確かに、それは絶対に問題ではありません。
Konrad Rudolph

40

JavaScriptインタープリターは、;行が見つからない場合、自動的に各行の終わりにa を追加します(ただし、いくつかの例外はありますが、ここでは取得しません)。

したがって、基本的に問題は中括弧の場所(ここではオブジェクトリテラルを表し、ほとんどの言語のコードブロックではありません)ではなく、最初の例をreturn ;=>に強制するこの小さな「機能」ですundefinedreturn ES5の仕様での動作を確認できます。

同様の動作をする他の言語については、Konradの回答をご覧ください。


5
非常に賛成の回答ですが、実際には間違っています。説明はいいですが、間違いを訂正してください。
Konrad Rudolph

JavaScriptに関する部分に問題はありません。JavaScriptの動作は、セミコロンの挿入によって強制的undefinedに返されるためです。私はafaik始まる他の言語について少し書いたので、それを一粒の塩でとってください:)。
Alex Ciminian、2012

5
しかし、JSが「いくつかの例外を除いて」「各行の終わりに」セミコロンを挿入することは事実ではありません。むしろ、それは通常はありませんセミコロンを挿入し、それはほんの数例があるんでは。そのため、多くの問題が発生します。
ruakh

26

確かに。Googleの goプログラミング言語は、非常によく似た動作を示します(効果は異なります)。そこで説明したように:

実際、CやJavaのように、正式な言語ではセミコロンが使用されますが、ステートメントの終わりのように見えるすべての行の終わりにセミコロンが自動的に挿入されます。自分で入力する必要はありません。

..をちょきちょきと切る...

このアプローチにより、見た目がきれいでセミコロンのないコードになります。1つの驚きは、ifステートメントなどの構造の開始中括弧をifと同じ行に置くことが重要であることです。そうしないと、コンパイルできない場合や、間違った結果が生じる場合があります。言語はブレーススタイルをある程度強制します。

ひそかに、私はロブ・パイクがOne True Braceスタイルを要求する言い訳がちょうど欲しかったと思います。


10
クール、これについては知りませんでした:)。個人的には、自動セミコロン挿入は良い考えではないと思います。言語に不慣れな人が理解するのが難しい微妙なバグが発生する可能性があります。セミコロンなしのコードを記述したい場合は、Pythonの方法をお勧めします。
Alex Ciminian、2012

@Alex セミコロン(VB)のない言語にこのプロパティがあります。また、PythonもJavaScriptと同じように処理されますが、Pythonもそうです。
コンラートルドルフ

私は賛成票を投じますが、2番目の文が完全に間違っているため、反対票を投じたくなります。彼らはキャンセルすることを推測します。;-)
ruakh

1
@ruakh「これは正確にこれを行う」という意味ですか、それともロブパイクに関するジョークのことですか?前者の場合、「同じ行動をとる」と言い換えることができます。後者の場合、私の下品なユーモアのセンスに問題があるとすみません;)
Dave

1
「Goはまさにこれを行う」という意味です。Goのセミコロン挿入の元の提案は、JavaScriptの提案と明確に対照的であり、「この提案は、JavaScriptのオプションのセミコロンルールを思い出させるかもしれません。これにより、解析エラーを修正するためにセミコロンが追加されます。Goの提案は大きく異なります。」すべてのレベルで非常に真実です。動作が異なり、効果も異なり、問題点もほとんどありません。(OTBS-enforcementは、迷惑ですが、すべてのGoコードで一貫した要件であるため、問題ではありません。)
ruakh

14

その質問への答えはかなり簡単です。「セミコロンの自動挿入」がある言語は、その行で問題が発生する可能性があります。これの問題

return
{
     name: 'rajat'
};

..これは、jsエンジンがreturn;ステートメントの後にセミコロンを挿入することを意味します(したがってreturn undefined)。この例は、中かっこを常に右側で開き、左側でも開かないようにするための適切な理由です。あなたはすでに正しく気づいたので、同じ行に中括弧がある場合、通訳者はそれに気づきセミコロンを挿入することができません。


6

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

私がこれに出会った最初の言語はawkでした(これにも構文の「奇数」、オプションのセミコロン、空白のみを使用した文字列連結などの共有があります)。D構文に緩く基づいているDTraceデザイナーawkでは、これらの機能をコピーしないように十分な意味がありましたが、頭の上から覚えていません。簡単な例(私のMacから、DTD内のENTITYタグの数を数える):

$ 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
$ 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.