割り当て演算子が左側に割り当てられるのはなぜですか?


47

私はちょうど友達プログラミングを教え始めました(Pythonを使用しています)。変数の作成と代入演算子について議論し始めたとき、彼女はなぜ右の値が左の名前に割り当てられているのかを尋ねました。 。

私にとってそれは自然に思えたので、あまり考えたことはありませんでしたが、彼女は左から右の方が自然であると言った、それが私たちのほとんどが自然言語を読む方法だからです。

私はそれについて考えて、割り当てられた名前(プログラマが再利用する必要がある)が簡単に表示され、左に揃えられているため、コードがはるかに読みやすくなると結論付けました。

aligned = 2
on = 'foo' + 'bar' + 'foobar'
the = 5.0 / 2
left = 2 + 5

とは対照的に:

2 = aligned 
'foo' + 'bar' + 'foobar' = on
5.0 / 2 = the 
2 + 5 = right 

# What were the names again...?

さて、この基準には他の理由もあるのだろうか。その背後に歴史はありますか?または、これが良いオプションである技術的な理由があります(コンパイラについてあまり知りません)?そして、右側に割り当てるプログラミング言語はありますか?


15
Rは右側(value -> variable)に割り当てることができます。
あなたは

おそらくこれは悪い変数名が原因ですか?「numAligned is 2」と「chickensLeft is 2 + 5」はどうですか?
仕事

18
友達の名前は…ヨーダ?
エイドリアン

1
彼女がこれについて気を配り始めたら、彼女がC ++&coを見たとき、彼女は何をするのだろうか。
ブラックベア

3
ちょっとした注意:カーンアカデミーには初心者プログラマ向けのPythonに関するいくつかのレッスンがあります:khanacademy.org/#computer-scienceとGoogleにはさらに高度なものがある:code.google.com/edu/languages/google-python-class/set- up.html
リンドンキツネ

回答:


56

同じ@paxdiablo。初期のプログラミング言語は数学者によって書かれましたが、実際にはすべてがそうでした。数学では、彼女自身の原則(左から右に読む)によって、それが機能する方法に意味があります。

x = 2y-4。

数学では、これを言うでしょう:xを2y -4と等しくします。

また、代数でもこれを行います。変数の方程式を解くとき、解く変数を左側に分離します。すなわち、y = mx + b;

さらに、Cファミリなどの言語ファミリ全体が特定の構文を持つと、変更するのにコストがかかります。


19
@FarmBoy:数学では、割り当てと平等は同じものです。式にはコンピューターにあるような順序はないためです。(aはbに等しいと同時にbはaに等しい)
ペトルザ

1
@FB(Erlangなどの単一の割り当て機能言語を除く)。平等を代入し、レート保証数学のように同じです
ピアStritzinger

18
@Petruzaいいえ、数学では割り当てと平等は同じものではありません。「Let x = 2y-3」と言うと、「Thus x = 2y-3」とは異なります。私は数学で、通常は文脈によってそれらを区別します。私に異議を唱えるコメントは非常に広く称賛されていたので、私は博士号を持っていることに言及します。数学では、これについてはかなり確信しています。
エリックウィルソン

2
私は博士号の近くのどこでも数学を知りません、私が述べることは、連続性がないので、割り当ての両側ができるプログラミングとは異なり、割り当てまたは平等の両方で数学の実行の順序がないことですある時点で異なっており、他のある時点で等しくなることになります。しかし、数学では、同様の割り当てにlet a be...割り当てが実際に平等、不思議であるので、時間がないとして、割り当ての両側には、同様に等しい理由を両方使用同じ符号:=
Petruza

5
@Petruzza -しかし、そこにある連続性。数学文書は、他の文書と同じように、最初から最後まで書かれています。私x = 1が第1章で主張するがx = 2、第2 章で主張する場合、それはひどい矛盾ではありません-各主張は特定のコンテキスト内でのみ適用されます。命令型プログラミングの違いは、一部は障壁の除去(コンテキストの変更は不要)、一部は実装と有用性に関するものです。
Steve314

26

BASIC、最も初期のコンピューター言語の1つには、次の「適切な」形式がありました。

10 LET AREA = HEIGHT * WIDTH

これは、「Hをオブジェクトの高さとする」などの変数を指定する数学的な考え方に一致します。

COBOLCOMPUTE声明も似ていました。物事を行う多くの方法と同様に、それは単に多くの言語で繰り越されたarbitrary意的な決定であったかもしれません。


7
プログラム行が「操作」ではなく「ステートメント」と見なされる場合、この形式がより自然であると思います。のように、I declare that X must equal THISより線形ではなくEvaluate THIS and store it in X
-voithos

待ってください、BASICは「初期の」コンピューター言語でしたか?
アレックスファインマン

2
@Alex 1960年代から生じていると考えると、それはかなり早いと思います。
ベンリチャーズ

1
一方、COBOLではを書くことができるためMULTIPLY HEIGHT BY WIDTH GIVING AREA、結果を取得する変数はステートメントの非常に右側にあります。
user281377

25

実際、右側に割り当てるプログラミング言語TI-BASICがあります!それだけでなく、代入演算子として「=」を使用せず、「STO」演算子として知られる矢印を使用します。

例:

5→A
(A + 3)→B
(A - B)→C

上記の例では、3つの変数が宣言され、値が与えられています。Aは5、Bは8、Cは-3です。最初の宣言/割り当ては「store 5 as A」と読むことができます。

TI-BASICがこのようなシステムを割り当てに使用する理由については、それが計算機のプログラミング言語であるため、私はそれが存在すると考えています。TI計算機の「STO」演算子は、数値が計算さ、通常の計算機操作で最も頻繁に使用されていました。ユーザーが覚えておきたい数字である場合、「STO」ボタンを押すと、計算機は名前の入力を促します(キーストロークが数字ではなく文字を生成するように自動的にアルファロックを有効にします)。

Sin(7 + Cos(3))
                    -.26979276
Ans→{variable name}
                    -.26979276

また、ユーザーは選択した変数に名前を付けることができます。アルファロックをオンにし、名前を入力してから「STO」を押し、「Ans」キーを押すことは、通常の操作では面倒です。すべての計算機機能はTI-BASICで利用できるため、他のほとんどの言語と比較すると後方ではありますが、「STO」が同じタスクを実行するため、他の割り当て演算子は追加されません。

(補遺:TI-BASICは私が学んだ最初の言語の1つだったので、大学で最初にJavaを学んだとき、LEFTへの割り当ては珍しくて「後方」であるように感じました!)


+1それを完全に忘れてしまった!TI Basicも私の最初の言語でしたが、この詳細は覚えていません。
バルジャック

実際、STOオペレーターは、マシンの動作方法、および任意の言語が実際に動作する方法に近くなっています。値は最初に計算され、メモリに保存されます。
クラッツ

15

ヒューリスティック1: 言語の設計中に何かを行うための複数の可能な方法に直面した場合、最も一般的で最も直感的な方法を選択しないと、Perl +になってしまいます。

さて、それは(少なくとも英語を話す人にとっては)もっと自然なのでしょうか?英語で物事を書く/言う方法を見てみましょう:

スティーブンは現在10歳です(10歳のスティーブンとは対照的に)。私の体重は190ポンドを超えています(190ポンドを超える体重とは対照的です)。

コード内:

steven = 10
i > 190

以下は、より自然に聞こえます:

「メアリーが18歳の場合、キャンディを食べることができます」。「私が21歳未満の場合、弟にテキーラをお願いします」

if (mary == 18) { ... }
if (i < 21) { ... }

より:

「18歳のメアリーが...」「21歳が私の年齢よりも大きい場合...」

今のコード:

if (18 == mary) { ... }
if (21 > i) { ... }

これはプログラマにとっても英語を話す人にとっても自然ではないことに注意してください。文はyoda-speakのように聞こえ、コードはyoda-conditionsと呼ばれます。これらはC ++で役立つかもしれませんが、ほとんどの人が同意すると確信しています。コンパイラーが重い作業を行い、ヨーダ条件の必要性を軽減できれば、人生は少し楽になるでしょう。

もちろん、何にでも慣れることができます。たとえば、番号81は次のように記述されます。

Eighty One(英語)Eighty and one(スペイン語)One and Eighty(ドイツ語)。

最後に、4つあります!=ロシア語で「緑のリンゴはテーブルの上にある」と言う24の有効な方法-「オン」が「テーブル」と一緒にならなければならないことを除いて、順序は(ほとんど)関係ありません。したがって、あなたがロシア語のネイティブスピーカー(たとえば)である場合、一方が書いているのa = 1010 = a、両方が同じように自然に見えるのかは気にしないかもしれません。

言語学は魅力的なテーマですが、私は正式にそれを研究したことはなく、その多くの言語を知りません。うまくいけば、私は十分な反例を提供しました。


4
...そしてフランス語では、81は「4回21」と言われています... :)
マーティンソイカ

1
@マーティン、デンマーク語は非常に似ていると思います。
CVn

7
なぜなら、4回21は84で、本当に奇妙だ@Martin
ピーター・オルソン

6
@ピーター:括弧が間違っている、それは(four times twenty) one
-SingleNegationElimination

4
@ジョブ:「18歳のメアリーが...なら」を読んだとき、私は必然的にヨーダを思い出しました。ジェダイの帰還:-)
ジョリキ

11

1950年代にFORTRANで始まりました。FORTRANがFORmula TRANslationの略語である場合-問題の式は、慣例により常に左に割り当てられる単純な代数方程式です。

一方、そのほぼ現代的なCOBOLは、英語に似たものであり、右側に割り当てられていました(ほとんど!)。

MOVE 1 TO COUNTER.
ADD +1 TO LINE-CNT.
MULTIPLY QTY BY PRICE GIVING ITEM-PRICE.

これはここでの最良の例だと思います。なぜなら、それは一般的な英語話者には読めるが正しい割り当てがある言語の文脈を完全に示しているからです。多くの人が英語で言っているので、それは重要だと言っています。それは割り当てが意味をなすために左から右にしか読まないからです。
ジョシュアヘッジス

5

さて、@ diceguyd30が指摘したように、両方の表記があります。

  • <Identifier> = <Value>識別子値にする」という意味です。または、それを展開するには:変数IdentifierValueに定義(または再定義)します。
  • <Value> -> <Identifier>識別子にを保存」を意味します。または、それを展開するには:ValueIdentifierで指定された場所に配置します。

もちろん、一般的に言えば、識別子は実際には任意のL値です。

最初のアプローチは変数の抽象的な概念を尊重し、2番目のアプローチは実際のストレージに関するものです。

最初のアプローチは、割り当てのない言語でも一般的であることに注意してください。また、変数の定義と割当が比較的接近していることに、注意してください<Type> <Identifier> = <Value><Identifier> = <Value>


3

すでに述べたように、初期のすべてのコンピューター言語はそのように機能していました。例えば、BASICの何年も前に登場したFORTRAN。

割り当て式の左側に割り当てられた変数を持つことは、実際には非常に理にかなっています。一部の言語では、SAME NAMEを持ついくつかの異なるオーバーロードルーチンがあり、異なるタイプの結果を返す場合があります。コンパイラに割り当てられた変数の型を最初に見せることにより、どのオーバーロードされたルーチンを呼び出すか、または整数から浮動小数点に変換するときに生成する暗黙のキャストを知ることができます。それは少し単純な説明ですが、うまくいけばアイデアが得られます。


2
私はあなたの説明を理解していますが、文の終わりまでコンパイラが先を見ることができませんでしたか?
-voithos

これにより、今日の言語ではレクサーが簡単になりますが、この種の構文が新しいときに、メソッドのオーバーロードはもちろんのこと、名前付きメソッドをサポートしているプログラミング言語はいくつありますか?
CVn

2
こんにちは@voithos。はい-コンパイラーは先を見ることができますが、コンパイラー作成の初期の段階ではおそらく容認できないレベルの複雑さだったでしょう。割り当てられた変数を左側に置くことは実用的な選択だと思います。人間と機械の両方が解析しやすいです。
デイブジュエル

割り当てを右に割り当てるのは簡単なことだと思います。3 + 4 == 6 + 7のような式の場合、言語は再帰的に定義されるため、演算子の前に両側が評価されます。言語要素「変数=式」は、「式=変数」に簡単に変更できます。それがあいまいな状況を引き起こすかどうかは、言語の残りの部分に依存します。
クラッツ

@Kratz-これはコンパイラーには確かに当てはまりますが、トークン化されたソースで動作する非常に古いインタープリター言語には小さな問題があった可能性があります。OTOH、それは左の変数よりも右の変数を好むかもしれません。
Steve314

3

それは初期の解析アルゴリズムの名残かもしれません。LRパーシングは1965年に発明されただけであり、LLパーサーが(当時のマシンの時間とスペースの制限内で)問題を抱えていた可能性があることを忘れないでください。考慮してください:

identifier = function();
function();

2つは2番目のトークンから明確に区別されます。一方、

function() = identifier;
function();

楽しくない。これは、代入式のネストを開始すると悪化します。

function(prev_identifier = expression) = identifier;
function(prev_identifier = expression);

もちろん、機械の曖昧さを解消しやすいということは、人間の曖昧さを解消しやすいことも意味します。別の簡単な例は、特定の識別子の初期化を検索することです。

identifier1 = expressionOfAnArbitraryLength;
identifier2 = expressionOfAReallyReallyReallyArbitraryLength;
identifier3 = expression;
identifier4 = AlongLineExpressionWithAFunctionCallWithAssignment(
    identifier = expr);

簡単です、左側を見てください。一方、右側

expressionOfAnArbitraryLength = identifier1;
expressionOfAReallyReallyReallyArbitraryLength = identifier2;
expression = identifier3;
AlongLineExpressionWithAFunctionCallWithAssignment(expr = identifier
    ) = identifier4;

特に、grepカードをパンチできない場合、必要な識別子を見つけるのははるかに困難です。


まさに私が考えていたポイント、はい。
voithos

2

アセンブリ言語は、左側のオペコードの一部として宛先を持っています。高レベルの言語は、先行言語の規則に従う傾向がありました。

=(または:=パスカル語の方言)を見ると、それらをとして発音できますis assigned the value。そして、左から右の性質が理にかなっています(ほとんどの言語で左から右も読むため)。プログラミング言語は主に左から右に読む人々によって開発されたため、慣習は固執しました。

それは一種の経路依存です。コンピュータープログラミングがヘブライ語またはアラビア語(または他の右から左への言語)を話す人々によって発明されたとしたら、目的地を右に置くと思います。


はい。ただし、エディター内のテキストも右揃えになると
思い

8
アセンブリ言語についてそのように一般化することはできません。それらは、宛先オペランドがどこにあるかによって異なります。
すぐに

2
@quickly_now:正しい。実際、通常のアキュムレータは通常1つまたは2つしかなかったため、ほとんどのプリミティブマシン言語(今日の標準ではアセンブラーでもない)には宛先さえありませんでした。メモリストアアドレスのみを指定し、ソース(アキュムレータ)を指定しない「ストア」オペコードを除き、ほとんどの操作はアキュムレータを宛先として暗黙指定しました。ALGOLに似た言語の割り当て構文に影響を与えたとは本当に思わない。
ハビエル

3
@Tangurena- 一部のアセンブラー言語には左側に推定値があります。ない(組み立てたオブジェクトコードです)オペコードのが、ニーモニック命令の引数リストの左側。しかし、他の人は目的地を右側に持っています。68000アセンブラーmov.b #255, d0d0は、たとえば、どこに割り当てるレジスターを書くでしょう。古いアセンブラには、命令ごとに1つの引数しかありません。6502 LDA #255(Load Accumulator)ではA、これは左側にあると主張できますが、STA wherever(Store Accumulator)の左側にもあります。
Steve314

2
また、Intel 4004(8008と8080を間に挟んだ8086ファミリの4ビットの究極の祖先)でさえ、高レベル言語での割り当てに開発さました。8086シリーズが、50年代以前にアセンブラーが行ったことを代表していると仮定している場合、それが本当かどうかは非常に疑わしいです。
Steve314

2

価値のあるものとして、COBOLのほとんどのステートメントは左から右に読み取るため、2つのオペランドには最初に名前が付けられ、宛先には次のように名前が付けられますmultiply salary by rate giving tax

しかし、私はあなたの学生がCOBOLを好むかもしれないと提案するつもりはありません。:-)


1

彼女は、左から右への方が自然に見えると言いました。それが私たちのほとんどが自然言語を読む方法だからです。

これは間違いだと思います。一方では、「10をxに割り当てる」または「10をxに移動する」と言うことができます。一方、「xを10に設定」または「xが10になる」と言うことができます。

つまり、動詞の選択に応じて、assigned-to変数が主語になる場合とそうでない場合があり、左にある場合とない場合があります。したがって、「自然なもの」は、割り当てを表す表現の習慣的な選択に完全に依存します。


0

擬似コードでは、割り当て演算子は非常に一般的に右側に記述されます。例えば

2*sqrt(x)/(3+y) -> z

Casioの計算機では、プログラム不可能なバリアントでも、割り当て変数も右側に表示されます

A+2B → C

Forthでは、変数も右側にあります

expression variable !

x86では、Intel構文の宛先は左側にありますが、GAS構文は順序を逆にし、特に減算や比較などのパラメーターの順序に関する指示に関して、多くの人々を混乱させます。これらの指示は2つの異なる方言で同じです

mov rax, rbx    ; Intel syntax
movq %rbx, %rax ; GAS syntax

どちらもrbxの値をraxに移動します。私が知っている他のアセンブリ言語は、GASのような右側に宛先を記述しません。

一部のプラットフォームでは、式を左側に、変数を右側に配置します。

MOVE expression TO variable      COBOL
expression → variable            TI-BASIC, Casio BASIC
expression -> variable           BETA, R
put expression into variable     LiveCode

https://en.wikipedia.org/wiki/Assignment_%28computer_science%29#Notation

ほとんどの言語は値を左に割り当てます。理由の1つは、演算子の位置合わせが容易で、変数の読み取りと認識が容易であるためです。 「変数を何らかの値にする」。

ただし、「値をxからyに移動する」と言い、変数を右側に書き込むことを好む人もいます。


-1

論理的な考え方に従っていると思います。
最初にボックス(変数)が必要です。次に、その中にオブジェクト(値)を配置します。
オブジェクトを空中に置いてから、その周りにボックスを配置しないでください。


2
そうです。ほとんどの言語では、右側が左側の前に評価されます。
ハビエル

3
その「道の右側で運転する」タイプのこと。それは論理的に思えますが、それはあなたがいつもそれをやった方法だからです。すべての優良国は左を走行します。
ジェームス・アンダーソン

1
@ジェームズアンダーソンの優れた国?:o
nawfal 14

あなたは正しいです、それはローマ字アルファベットとしての左から右への書記体系にとってのみ論理的です。
ペトルーザ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.