指定敘述:修订间差异
小 →top 标签:加入不存在模板 |
小 →標記法 |
||
(未显示5个用户的19个中间版本) | |||
第6行: | 第6行: | ||
在[[程序設計]]中,'''指定敘述'''({{lang-en|assignment statement}})-{zh-cn:,;zh-tw:,又譯'''指定指述''',}-會將一個特定的[[值 (電腦科學)|值]]設定到某個特定的[[記憶體位址|儲存位址]]去,這個位置被標記成一個特定的[[变量 (程序设计)|變數]]名稱。換句話說,這個敘述會複製一個值到某個特定變數中。在多數的[[指令式編程|指令式]][[程式語言]]中,這種敘述是其中最基礎的結構。 |
在[[程序設計]]中,'''指定敘述'''({{lang-en|assignment statement}})-{zh-cn:,;zh-tw:,又譯'''指定指述''',}-會將一個特定的[[值 (電腦科學)|值]]設定到某個特定的[[記憶體位址|儲存位址]]去,這個位置被標記成一個特定的[[变量 (程序设计)|變數]]名稱。換句話說,這個敘述會複製一個值到某個特定變數中。在多數的[[指令式編程|指令式]][[程式語言]]中,這種敘述是其中最基礎的結構。 |
||
指定敘述的通用表示方法通常是 <code>x = expr</code>(這種表示法最早源自1949年–1951年时的{{ |
指定敘述的通用表示方法通常是 <code>x = expr</code>(這種表示法最早源自1949年–1951年时的{{en-link|Superplan|}},因為1957年首版的[[Fortran]]與[[C語言]]而廣為人知),另一種形式則為 <code>x := expr</code>(這種形式最早來自[[ALGOL 58]],因為[[Pascal (程式語言)|Pascal]]而盛行)。在這兩種表示法之外,仍然存在許多其他的形式。 |
||
對多數的指令式程式語言來說,指定敘述允許某個特定變數,在其生命週期與作用域之中,可以被指定為不同的值,或是重複被-{指定}-值。 |
對多數的指令式程式語言來說,指定敘述允許某個特定變數,在其生命週期與作用域之中,可以被指定為不同的值,或是重複被-{指定}-值。 |
||
第25行: | 第25行: | ||
==单赋值== |
==单赋值== |
||
{{See also |
{{See also|静态单赋值形式}} |
||
任何改变现存值的赋值(比如<code>x := x + 1</code>),在[[纯函数式语言]]中都是不允许的<ref name="Bruce Tate">[http://www.ibm.com/developerworks/java/library/j-cb07186.html Crossing borders: Explore functional programming with Haskell] {{webarchive |url=https://web.archive.org/web/20101119190821/http://www.ibm.com/developerworks/java/library/j-cb07186.html |date=November 19, 2010 }}, by Bruce Tate</ref>。在[[函数式编程]]中,赋值是被劝阻的,用以支持也叫做“初始化”的单赋值。单赋值是[[名字绑定]]的用例,不同于本文其他部分描述的赋值之处在于,它只能做一次,通常是在变量被创建的时候,不允许后续的重新赋值。 |
任何改变现存值的赋值(比如<code>x := x + 1</code>),在[[纯函数式语言]]中都是不允许的<ref name="Bruce Tate">[http://www.ibm.com/developerworks/java/library/j-cb07186.html Crossing borders: Explore functional programming with Haskell] {{webarchive |url=https://web.archive.org/web/20101119190821/http://www.ibm.com/developerworks/java/library/j-cb07186.html |date=November 19, 2010 }}, by Bruce Tate</ref>。在现今的[[函数式编程]]中,赋值是被劝阻的,用以支持也叫做“初始化”的单赋值。单赋值是[[名字绑定]]的用例,不同于本文其他部分描述的赋值之处在于,它只能做一次,通常是在变量被创建的时候,不允许后续的重新赋值。 |
||
表达式的求值,如果不改变机器的可察见状态<ref name="Mitchell2003">{{cite book |last=Mitchell |first=John C. |authorlink=John C. Mitchell |title=Concepts in programming languages |url=https://books.google.com/books?id=7Uh8XGfJbEIC&pg=PA23|accessdate=3 January 2011 |year=2003 |publisher=Cambridge University Press |isbn=978-0-521-78098-8 |page=23}}</ref>,并且对相同的输入产生相同的值<ref name="Bruce Tate"/>,就没有[[副作用 (计算机科学)|副作用]]。指令式赋值,在销毁旧值并使之不可获得时,在将旧值替代为新值时,就可能介入了副作用<ref name="csci210">{{cite web|url=http://www.seas.gwu.edu/~bell/csci210/lectures/imperative_languages.pdf|title=Imperative Programming Languages (IPL)|author=|date=|website=gwu.edu|accessdate=20 April 2018}}</ref>;为此在[[LISP]]和[[函数式编程]]中,这被称为“破坏性”(destructive)赋值,类似于“破坏性更新”。 |
表达式的求值,如果不改变机器的可察见状态<ref name="Mitchell2003">{{cite book |last=Mitchell |first=John C. |authorlink=John C. Mitchell |title=Concepts in programming languages |url=https://books.google.com/books?id=7Uh8XGfJbEIC&pg=PA23|accessdate=3 January 2011 |year=2003 |publisher=Cambridge University Press |isbn=978-0-521-78098-8 |page=23}}</ref>,并且对相同的输入产生相同的值<ref name="Bruce Tate"/>,就没有[[副作用 (计算机科学)|副作用]]。指令式赋值,在销毁旧值并使之不可获得时,在将旧值替代为新值时,就可能介入了副作用<ref name="csci210">{{cite web|url=http://www.seas.gwu.edu/~bell/csci210/lectures/imperative_languages.pdf|title=Imperative Programming Languages (IPL)|author=|date=|website=gwu.edu|accessdate=20 April 2018|archive-date=2021-01-18|archive-url=https://web.archive.org/web/20210118171507/https://www2.seas.gwu.edu/~bell/csci210/lectures/imperative_languages.pdf|dead-url=no}}</ref>;为此在[[LISP]]和[[函数式编程]]中,这被称为“破坏性”(destructive)赋值,类似于“破坏性更新”。 |
||
在纯函数式语言比如[[Haskell]]中,单赋值是赋值的唯一形式,这里没有在指令式语言意义上的变量<ref name="Bruce Tate"/>,而是命名的常量值,并具有可能的合成(compoud)本性,即它们的元素"[[惰性求值|在需要时]]"被逐步的定义。纯函数式 |
在纯函数式语言比如[[Haskell]]中,单赋值是赋值的唯一形式,这里没有在指令式语言意义上的变量<ref name="Bruce Tate"/>,而是命名的常量值,并具有可能的合成(compoud)本性,即它们的元素"[[惰性求值|在需要时]]"被逐步的定义。[[纯函数式编程]]和与之于此共通的[[数据流程编程]],由于值之间相互独立,可以提供在[[并行计算]]上的优势,它避免了顺序的一时一步执行的[[冯·诺伊曼瓶颈]]<ref name="Mitchell2003.1">{{cite book |author=John C. Mitchell |title=Concepts in programming languages |url=https://books.google.com/books?id=7Uh8XGfJbEIC&pg=PA81|accessdate=3 January 2011 |year=2003 |publisher=Cambridge University Press |isbn=978-0-521-78098-8 |pages=81–82}}</ref>。 |
||
非纯函数式语言,同时提供了单赋值和真赋值(尽管相比指令式编程语言而言真赋值典型的较少使用)。例如,在[[Scheme]]中,单赋值(通过<code>let</code>),和真赋值(通过<code>set!</code>),二者都可以用于所有变量上,并提供专门的原语(primitive)用于在列表、向量、字符串等之内做破坏性更新。在[[OCaml]]中,只有单赋值,通过<code>let ''name'' = ''value''</code>语法,被允许用于变量;而破坏性更新,可通过单独的<code><-</code>算符,用于数组的元素和字符串,还可用于已经被编程者显式声明为[[不可变对象|可变]](意味着能够在其初始化声明之后被变更)的记录字段和对象。 |
非纯函数式语言,同时提供了单赋值和真赋值(尽管相比指令式编程语言而言真赋值典型的较少使用)。例如,在[[Scheme]]中,单赋值(通过<code>let</code>),和真赋值(通过<code>set!</code>),二者都可以用于所有变量上,并提供专门的原语(primitive)用于在列表、向量、字符串等之内做破坏性更新。在[[OCaml]]中,只有单赋值,通过<code>let ''name'' = ''value''</code>语法,被允许用于变量;而破坏性更新,可通过单独的<code><-</code>算符,用于数组的元素和字符串,还可用于已经被编程者显式声明为[[不可变对象|可变]](意味着能够在其初始化声明之后被变更)的记录字段和对象。 |
||
使用单赋值的[[函数式编程]]语言,包括[[Clojure]](针对数据结构,而非变量)、[[Erlang]](相比Haskell,它接受多次赋值,如果值相等的话)、[[F♯|F#]]、[[Haskell]]、 |
使用单赋值的[[函数式编程]]语言,包括[[Clojure]](针对数据结构,而非变量)、[[Erlang]](相比Haskell,它接受多次赋值,如果值相等的话)、[[F♯|F#]]、[[Haskell]]、{{en-link|Lava (编程语言)|Lava (programming language)|Lava}}、[[OCaml]]、[[Oz (编程语言)|Oz]](对用数据流变量,而非cell)、[[Racket]](对于一些数据结构如列表,而非符号)、[[SASL (编程语言)|SASL]]、[[Scala]](对于变量)、[[SISAL]]、[[Standard ML]]。非[[回溯法|回溯]]的[[Prolog]]代码可以被看作“明显的”单赋值,这里明显的含义为,它的(命名)变量可以显式的处在未赋值状态,或只能准确的被设置一次。相反的,在[[Haskell]]中,没有未赋值变量,而所有变量可以看作在创建时就被隐式的设定了它的值(更精确的说是设置了计算对象在“[[惰性求值|在需要时]]”产生它的值)。 |
||
== 指定語句的回傳值 == |
== 指定語句的回傳值 == |
||
第49行: | 第49行: | ||
===增广赋值=== |
===增广赋值=== |
||
{{main |
{{main|增广赋值}} |
||
所赋予的值依赖于先前的值是很常见的,很多指令式语言,尤其是[[C语言|C]]及其主要派生者,提供了叫做 |
所赋予的值依赖于先前的值是很常见的,很多指令式语言,尤其是[[C语言|C]]及其主要派生者,提供了叫做[[增广赋值]]的特殊算符,比如<code>*=</code>,则<code>a = 2*a</code>可以转而写为<code>a *= 2</code><ref name="Flaig2008">{{cite book |author=Ruediger-Marcus Flaig |title=Bioinformatics programming in Python: a practical course for beginners |url=https://books.google.com/books?id=kS7Dye-dv54C&pg=PA98 |access-date=25 December 2010 |year=2008 |publisher=Wiley-VCH |isbn=978-3-527-32094-3 |pages=98–99 |archive-date=2017-04-19 |archive-url=https://web.archive.org/web/20170419014237/https://books.google.com/books?id=kS7Dye-dv54C&pg=PA98 |dead-url=no }}</ref>。 |
||
===链式赋值=== |
===链式赋值=== |
||
第56行: | 第56行: | ||
===并行赋值=== |
===并行赋值=== |
||
一些编程语言,比如[[APL语言|APL]]、[[Common Lisp]]<ref>{{cite web |title=CLHS: Macro SETF, PSETF |url=http://www.lispworks.com/documentation/HyperSpec/Body/m_setf_.htm#psetf |website=Common Lisp Hyperspec |publisher=LispWorks |accessdate=23 April 2019}}</ref>、[[Go]]<ref>The Go Programming Language Specification: [http://golang.org/ref/spec#Assignments Assignments]</ref>、[[JavaScript]](自从1.7)、[[Lua]]、[[Maple]]、[[occam#occam 2|occam 2]]<ref name="occam">{{cite book |last= |first= |editor=INMOS Limited |authorlink= |year=1988 |title=Occam 2 Reference Manual |location=New Jersey |publisher=Prentice Hall |isbn=0-13-629312-3}}</ref>、[[Perl]]<ref name="perl">{{cite book |last=Wall |first=Larry |authorlink=Larry Wall |author2=Christiansen, Tom |author3=Schwartz, Randal C. |year=1996 |edition=2 |title=Perl Programming Language |location=Cambridge |publisher=O´Reilly |isbn=1-56592-149-6 |url=https://archive.org/details/programmingperl00wall }}</ref>、[[PHP]]、[[Python]]<ref name="python">{{cite book |last=Lutz |first=Mark |authorlink= |year=2001 |edition=2 |title=Python Programming Language |location=Sebastopol |publisher=O´Reilly |isbn=0-596-00085-5 |url=https://archive.org/details/programmingpytho00lutz }}</ref>、[[REBOL]]、[[Ruby]]<ref name="ruby">{{cite book |last=Thomas |first=David |authorlink= |author2=Hunt, Andrew |year=2001 |title=Programming Ruby: The Pragmatic Programmer's Guide |location=Upper Saddle River |publisher=Addison Wesley |isbn=0-201-71089-7 |url=https://archive.org/details/programmingruby000thom }}</ref>、[[Windows PowerShell]],允许多个变量被并行的赋值,语法如下: |
一些编程语言,比如[[APL语言|APL]]、[[Common Lisp]]<ref>{{cite web |title=CLHS: Macro SETF, PSETF |url=http://www.lispworks.com/documentation/HyperSpec/Body/m_setf_.htm#psetf |website=Common Lisp Hyperspec |publisher=LispWorks |accessdate=23 April 2019 |archive-date=2020-11-30 |archive-url=https://web.archive.org/web/20201130224608/http://www.lispworks.com/documentation/HyperSpec/Body/m_setf_.htm#psetf |dead-url=no }}</ref>、[[Go]]<ref>The Go Programming Language Specification: [http://golang.org/ref/spec#Assignments Assignments] {{Wayback|url=http://golang.org/ref/spec#Assignments |date=20210318133416 }}</ref>、[[JavaScript]](自从1.7)、[[Lua]]、[[Maple]]、[[occam#occam 2|occam 2]]<ref name="occam">{{cite book |last= |first= |editor=INMOS Limited |authorlink= |year=1988 |title=Occam 2 Reference Manual |url=https://archive.org/details/occam2referencem0000unse|location=New Jersey |publisher=Prentice Hall |isbn=0-13-629312-3}}</ref>、[[Perl]]<ref name="perl">{{cite book |last=Wall |first=Larry |authorlink=Larry Wall |author2=Christiansen, Tom |author3=Schwartz, Randal C. |year=1996 |edition=2 |title=Perl Programming Language |location=Cambridge |publisher=O´Reilly |isbn=1-56592-149-6 |url=https://archive.org/details/programmingperl00wall }}</ref>、[[PHP]]、[[Python]]<ref name="python">{{cite book |last=Lutz |first=Mark |authorlink= |year=2001 |edition=2 |title=Python Programming Language |location=Sebastopol |publisher=O´Reilly |isbn=0-596-00085-5 |url=https://archive.org/details/programmingpytho00lutz }}</ref>、[[REBOL]]、[[Ruby]]<ref name="ruby">{{cite book |last=Thomas |first=David |authorlink= |author2=Hunt, Andrew |year=2001 |title=Programming Ruby: The Pragmatic Programmer's Guide |location=Upper Saddle River |publisher=Addison Wesley |isbn=0-201-71089-7 |url=https://archive.org/details/programmingruby000thom }}</ref>、[[Windows PowerShell]],允许多个变量被并行的赋值,语法如下: |
||
a, b := 0, 1 |
a, b := 0, 1 |
||
它同时赋值<code>0</code>到<code>a</code>和<code>1</code>到<code>b</code>。这经常叫做'''并行'''(parallel)赋值;它是[[CPL (程式语言)|CPL]]语言于1963年介入的,当时名字叫做'''同时'''(simultaneous)赋值<ref>D.W. Barron ''et al.'', "The main features of CPL", ''Computer Journal'' '''6''':2:140 (1963). [http://comjnl.oxfordjournals.org/cgi/reprint/6/2/134 full text (subscription)]</ref>,有时也叫做'''多'''(multiple)赋值,但这在与'''单'''(single)赋值一起用时会产生混淆,因为它们不是对比的。如果赋值的右手侧是一个单一变量(比如一个数组或结构),这个特征就叫做'''解包'''(unpacking)<ref>{{cite web|url=http://legacy.python.org/dev/peps/pep-3132/|title=PEP 3132 -- Extended Iterable Unpacking|author=|date=|website=legacy.python.org|accessdate=20 April 2018}}</ref>或'''解构'''(destructuring)赋值<ref>{{cite web|url=https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment|title=Destructuring assignment|author=|date=|website=MDN Web Docs|accessdate=20 April 2018}}</ref>: |
它同时赋值<code>0</code>到<code>a</code>和<code>1</code>到<code>b</code>。这经常叫做'''并行'''(parallel)赋值;它是[[CPL (程式语言)|CPL]]语言于1963年介入的,当时名字叫做'''同时'''(simultaneous)赋值<ref>D.W. Barron ''et al.'', "The main features of CPL", ''Computer Journal'' '''6''':2:140 (1963). [http://comjnl.oxfordjournals.org/cgi/reprint/6/2/134 full text (subscription)] {{Webarchive|url=https://archive.today/20120707200431/http://comjnl.oxfordjournals.org/cgi/reprint/6/2/134 |date=2012-07-07 }}</ref>,有时也叫做'''多'''(multiple)赋值,但这在与'''单'''(single)赋值一起用时会产生混淆,因为它们不是对比的。如果赋值的右手侧是一个单一变量(比如一个数组或结构),这个特征就叫做'''解包'''(unpacking)<ref>{{cite web|url=http://legacy.python.org/dev/peps/pep-3132/|title=PEP 3132 -- Extended Iterable Unpacking|author=|date=|website=legacy.python.org|accessdate=20 April 2018|archive-date=2016-05-13|archive-url=https://web.archive.org/web/20160513235219/http://legacy.python.org/dev/peps/pep-3132/|dead-url=no}}</ref>或'''解构'''(destructuring)赋值<ref>{{cite web|url=https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment|title=Destructuring assignment|author=|date=|website=MDN Web Docs|accessdate=20 April 2018|archive-date=2021-02-10|archive-url=https://web.archive.org/web/20210210170654/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment|dead-url=no}}</ref>: |
||
'''var''' list := {0, 1} |
'''var''' list := {0, 1} |
||
第94行: | 第94行: | ||
这提供了从一个函数返回多个值要使用[[输出参数]]的一种替代方式。这最早见于[[CLU]]语言(1974年),而CLU推动了一般的并行赋值变得流行。 |
这提供了从一个函数返回多个值要使用[[输出参数]]的一种替代方式。这最早见于[[CLU]]语言(1974年),而CLU推动了一般的并行赋值变得流行。 |
||
在C和C++中,[[逗号运算符]],在允许多个赋值出现在一个单一语句上类似于并行赋值,写<code>a = 1, b = 2</code>替代<code>a, b = 1, 2</code>。这主要用在for循环中,在其他语言比如Go中,被替代为并行赋值<ref>[http://golang.org/doc/effective_go.html Effective Go]: [http://golang.org/doc/effective_go.html#for for], |
在C和C++中,[[逗号运算符]],在允许多个赋值出现在一个单一语句上类似于并行赋值,写<code>a = 1, b = 2</code>替代<code>a, b = 1, 2</code>。这主要用在for循环中,在其他语言比如Go中,被替代为并行赋值<ref>[http://golang.org/doc/effective_go.html Effective Go] {{Wayback|url=http://golang.org/doc/effective_go.html |date=20210209204944 }}: [http://golang.org/doc/effective_go.html#for for] {{Wayback|url=http://golang.org/doc/effective_go.html#for |date=20210209204944 }}, |
||
"Finally, Go has no comma operator and ++ and -- are statements not expressions. Thus if you want to run multiple variables in a for you should use parallel assignment (although that precludes ++ and --)."</ref>。但是上述C++代码不确保完全的同时性,因为代码<code>a = b, b = a+1</code>的右侧项是在左侧项之后运算的。在语言如Python中,<code>a, b = b, a+1</code>将并发的赋值两个变量,使用最初的<code>a</code>的值来计算新<code>b</code>的值. |
"Finally, Go has no comma operator and ++ and -- are statements not expressions. Thus if you want to run multiple variables in a for you should use parallel assignment (although that precludes ++ and --)."</ref>。但是上述C++代码不确保完全的同时性,因为代码<code>a = b, b = a+1</code>的右侧项是在左侧项之后运算的。在语言如Python中,<code>a, b = b, a+1</code>将并发的赋值两个变量,使用最初的<code>a</code>的值来计算新<code>b</code>的值. |
||
第108行: | 第108行: | ||
| <code>''variable'' = ''expression''</code> || [[Fortran]], [[PL/I]], [[C语言|C]] (和[[:Category:C語言家族|派生者]]比如[[C++]], [[Java]]等), [[Bourne shell]], [[Python]], [[Go]] (赋值预先声明的变量), [[R语言|R]], [[Windows PowerShell]]等。 |
| <code>''variable'' = ''expression''</code> || [[Fortran]], [[PL/I]], [[C语言|C]] (和[[:Category:C語言家族|派生者]]比如[[C++]], [[Java]]等), [[Bourne shell]], [[Python]], [[Go]] (赋值预先声明的变量), [[R语言|R]], [[Windows PowerShell]]等。 |
||
|- |
|- |
||
| <code>''variable'' := ''expression''</code> || [[ALGOL]] (和派生者), [[Simula]], [[CPL]], [[BCPL]], [[Pascal |
| <code>''variable'' := ''expression''</code> || [[ALGOL]] (和派生者), [[Simula]], [[CPL]], [[BCPL]], [[Pascal语言|Pascal]]<ref name=pascal>{{cite book |last=Moore |first=Lawrie |authorlink= |year=1980 |title=Foundations of Programming with Pascal |url=https://archive.org/details/foundationsofpro0000moor |location=New York |publisher=John Wiley & Sons |isbn=0-470-26939-1}}</ref> (和派生者比如[[Modula]]), {{en-link|Mary (编程语言)|Mary (programming language)|Mary}}, {{en-link|PL/M}}, [[Ada]], [[Smalltalk]], [[Eiffel]]<ref name=eiffel1>{{cite book |last=Meyer |first=Bertrand |authorlink=Bertrand Meyer |year=1992 |title=Eiffel the Language |url=https://archive.org/details/eiffellanguage0000meye |location=Hemel Hempstead |publisher=Prentice Hall International(UK) |isbn=0-13-247925-7}}</ref><ref name=eiffel2>{{cite book |last=Wiener |first=Richard |authorlink= |year=1996 |title=An Object-Oriented Introduction to Computer Science Using Eiffel |location=Upper Saddle River, New Jersey |publisher=Prentice Hall |isbn=0-13-183872-5}}</ref>, [[Oberon]], [[Dylan语言|Dylan]]<ref name=dylan>{{cite book |last=Feinberg |first=Neal |authorlink= |author2=Keene, Sonya E.|author3= Mathews, Robert O.|author4= Withington, P. Tucker |year=1997 |title=Dylan Programming |url=https://archive.org/details/dylanprogramming0000unse |location=Massachusetts |publisher=Addison Wesley |isbn=0-201-47976-1}}</ref>, {{en-link|Seed7}}, [[Go]] (声明和定义变量的快捷方式)<ref>{{cite web|url=http://golang.org/ref/spec#Short_variable_declarations|title=The Go Programming Language Specification - The Go Programming Language|author=|date=|website=golang.org|accessdate=20 April 2018|archive-date=2021-03-18|archive-url=https://web.archive.org/web/20210318133416/https://golang.org/ref/spec#Short_variable_declarations|dead-url=no}}</ref>, [[Io (编程语言)|Io]], [[AMPL]], [[ML语言|ML]]<ref name="ml">{{cite book |last=Ullman |first=Jeffrey D. |authorlink= |year=1998 |title=Elements of ML Programming: ML97 Edition |url=https://archive.org/details/elementsofmlprog0000ullm |location=Englewood Cliffs, New Jersey |publisher=Prentice Hall |isbn=0-13-790387-1}}</ref>, [[AutoHotkey]]等。 |
||
|- |
|- |
||
|} |
|} |
||
第116行: | 第116行: | ||
:{| class="wikitable" |
:{| class="wikitable" |
||
|- |
|- |
||
| <code>''variable'' << ''expression''</code> || |
| <code>''variable'' << ''expression''</code> || {{en-link|Magik (编程语言)|Magik (programming language)|Magik}} |
||
|- |
|- |
||
| <code>''variable'' <- ''expression''</code> || [[F Sharp|F#]], [[OCaml]], [[R语言|R]], [[S语言|S]] |
| <code>''variable'' <- ''expression''</code> || [[F Sharp|F#]], [[OCaml]], [[R语言|R]], [[S语言|S]] |
||
第124行: | 第124行: | ||
| <code> assign("''variable''", ''expression'')</code> || [[R语言|R]] |
| <code> assign("''variable''", ''expression'')</code> || [[R语言|R]] |
||
|- |
|- |
||
| <code>''variable'' ← ''expression''</code> || [[APL]]<ref name="aplbook">{{cite book |last=Iverson |first=Kenneth E. |authorlink=Kenneth E. Iverson |title=A Programming Language |publisher=John Wiley and Sons |year=1962 |isbn=0-471-43014-5 |url=http://www.softwarepreservation.org/projects/apl/book/APROGRAMMING%20LANGUAGE/view |deadurl=yes |archiveurl=https://web.archive.org/web/20090604091725/http://www.softwarepreservation.org/projects/apl/book/APROGRAMMING%20LANGUAGE/view |archivedate=2009年6月4日 |df= }}</ref>, [[Smalltalk]] |
| <code>''variable'' ← ''expression''</code> || [[APL語言|APL]]<ref name="aplbook">{{cite book |last=Iverson |first=Kenneth E. |authorlink=Kenneth E. Iverson |title=A Programming Language |publisher=John Wiley and Sons |year=1962 |isbn=0-471-43014-5 |url=http://www.softwarepreservation.org/projects/apl/book/APROGRAMMING%20LANGUAGE/view |deadurl=yes |archiveurl=https://web.archive.org/web/20090604091725/http://www.softwarepreservation.org/projects/apl/book/APROGRAMMING%20LANGUAGE/view |archivedate=2009年6月4日 |df= }}</ref>, [[Smalltalk]] |
||
|- |
|- |
||
| <code>''variable'' =: ''expression''</code> || [[J语言|J]] |
| <code>''variable'' =: ''expression''</code> || [[J语言|J]] |
||
第130行: | 第130行: | ||
| <code>LET ''variable'' = ''expression''</code> || [[BASIC]] |
| <code>LET ''variable'' = ''expression''</code> || [[BASIC]] |
||
|- |
|- |
||
| <code>let ''variable'' := ''expression''</code> || |
| <code>let ''variable'' := ''expression''</code> || {{en-link|XQuery}} |
||
|- |
|- |
||
| <code>set ''variable'' to ''expression''</code> || [[AppleScript]] |
| <code>set ''variable'' to ''expression''</code> || [[AppleScript]] |
||
第138行: | 第138行: | ||
| <code>Set-Variable ''variable'' ''(expression)''</code> || [[Windows PowerShell]] |
| <code>Set-Variable ''variable'' ''(expression)''</code> || [[Windows PowerShell]] |
||
|- |
|- |
||
| <code>''variable'' : ''expression''</code> || |
| <code>''variable'' : ''expression''</code> || {{en-link|Macsyma}}, [[Maxima]], [[Rebol]] |
||
|- |
|- |
||
| <code>var ''variable'' ''expression''</code> || |
| <code>var ''variable'' ''expression''</code> || {{en-link|mIRC脚本语言|mIRC scripting language}} |
||
|- |
|- |
||
| <code>''reference-variable'' :- ''reference-expression''</code> || [[Simula]] |
| <code>''reference-variable'' :- ''reference-expression''</code> || [[Simula]] |
||
第155行: | 第155行: | ||
| style="padding-right: 1em" | <code>''expression'' -> ''variable''</code> || [[BETA (编程语言)|BETA]], [[R语言|R]] |
| style="padding-right: 1em" | <code>''expression'' -> ''variable''</code> || [[BETA (编程语言)|BETA]], [[R语言|R]] |
||
|- |
|- |
||
| style="padding-right: 1em" | <code>put ''expression'' into ''variable''</code> || |
| style="padding-right: 1em" | <code>put ''expression'' into ''variable''</code> || {{en-link|LiveCode}} |
||
|} |
|} |
||
第164行: | 第164行: | ||
| style="padding-right: 1em" | <code>(setf ''variable'' ''expression'')</code> || [[Common Lisp]] |
| style="padding-right: 1em" | <code>(setf ''variable'' ''expression'')</code> || [[Common Lisp]] |
||
|- |
|- |
||
| <code>(set! ''variable'' ''expression'')</code> || [[Scheme]]<ref name="scheme">{{cite book |last=Dybvig |first=R. Kent |authorlink= |year=1996 |title=The Scheme Programming Language: ANSI Scheme |location=New Jersey |publisher=Prentice Hall |isbn=0-13-454646-6}}</ref><ref name="schemeint">{{cite book |last=Smith |first=Jerry D. |authorlink= |year=1988 |title=Introduction to Scheme |location=New Jersey |publisher=Prentice Hall |isbn=0-13-496712-7}}</ref><ref name="sussman">{{cite book |last=Abelson |first=Harold |authorlink= |author2=Sussman, Gerald Jay|author3= Sussman, Julie |year=1996 |title=Structure and Interpretation of Computer Programs |location=New Jersey |publisher=McGraw-Hill |isbn=0-07-000484-6}}</ref> |
| <code>(set! ''variable'' ''expression'')</code> || [[Scheme]]<ref name="scheme">{{cite book |last=Dybvig |first=R. Kent |authorlink= |year=1996 |title=The Scheme Programming Language: ANSI Scheme |url=https://archive.org/details/schemeprogrammin0000dybv_r2k2 |location=New Jersey |publisher=Prentice Hall |isbn=0-13-454646-6}}</ref><ref name="schemeint">{{cite book |last=Smith |first=Jerry D. |authorlink= |year=1988 |title=Introduction to Scheme |url=https://archive.org/details/introductiontosc0000smit |location=New Jersey |publisher=Prentice Hall |isbn=0-13-496712-7}}</ref><ref name="sussman">{{cite book |last=Abelson |first=Harold |authorlink= |author2=Sussman, Gerald Jay|author3= Sussman, Julie |year=1996 |title=Structure and Interpretation of Computer Programs |url=https://archive.org/details/pdfy-x0q2Q4K6h-gsWbes |location=New Jersey |publisher=McGraw-Hill |isbn=0-07-000484-6}}</ref> |
||
|- |
|- |
||
| <code>set ''variable'' ''expression''</code> || [[Tcl]] |
| <code>set ''variable'' ''expression''</code> || [[Tcl]] |
||
第184行: | 第184行: | ||
[[Category:程序架构]] |
[[Category:程序架构]] |
||
[[Category:编程语言概念]] |
[[Category:编程语言概念]] |
||
[[Category:运算符_(编程)]] |
2024年9月14日 (六) 21:01的最新版本
在程序設計中,指定敘述(英語:assignment statement),會將一個特定的值設定到某個特定的儲存位址去,這個位置被標記成一個特定的變數名稱。換句話說,這個敘述會複製一個值到某個特定變數中。在多數的指令式程式語言中,這種敘述是其中最基礎的結構。
指定敘述的通用表示方法通常是 x = expr
(這種表示法最早源自1949年–1951年时的Superplan,因為1957年首版的Fortran與C語言而廣為人知),另一種形式則為 x := expr
(這種形式最早來自ALGOL 58,因為Pascal而盛行)。在這兩種表示法之外,仍然存在許多其他的形式。
對多數的指令式程式語言來說,指定敘述允許某個特定變數,在其生命週期與作用域之中,可以被指定為不同的值,或是重複被指定值。
语义
[编辑]在指令式編程中,隨著時間改變,不同的值被關聯到某個特定的變數名稱上。變數是數值的容器。可以先指派變數為某個值,在之後再用另一個值來加以取代。在這種模型中,程式的運作,是透過每次成功的指定敘述,來改變其狀態。指令式程式語言,倚靠指定敘述來進行迭代。在最低的層級中,指定敘述是以組合語言指令,如 MOVE
或 STORE
來實作。
以C語言為例,下列的程式碼段落可以作為指定敘述的例子:
int x = 10;
float y;
x = 23;
y = 32.4f;
在第一行程式碼中,變數x
先被宣告為int型別,之後將數值10指定給它。在第二行,變數y
被宣告為float型別,但沒有指定值。在第三行,變數x
被重新指定為數值23。在第四行中,變數y
被指定為浮點數值32.4f。
单赋值
[编辑]任何改变现存值的赋值(比如x := x + 1
),在纯函数式语言中都是不允许的[1]。在现今的函数式编程中,赋值是被劝阻的,用以支持也叫做“初始化”的单赋值。单赋值是名字绑定的用例,不同于本文其他部分描述的赋值之处在于,它只能做一次,通常是在变量被创建的时候,不允许后续的重新赋值。
表达式的求值,如果不改变机器的可察见状态[2],并且对相同的输入产生相同的值[1],就没有副作用。指令式赋值,在销毁旧值并使之不可获得时,在将旧值替代为新值时,就可能介入了副作用[3];为此在LISP和函数式编程中,这被称为“破坏性”(destructive)赋值,类似于“破坏性更新”。
在纯函数式语言比如Haskell中,单赋值是赋值的唯一形式,这里没有在指令式语言意义上的变量[1],而是命名的常量值,并具有可能的合成(compoud)本性,即它们的元素"在需要时"被逐步的定义。纯函数式编程和与之于此共通的数据流程编程,由于值之间相互独立,可以提供在并行计算上的优势,它避免了顺序的一时一步执行的冯·诺伊曼瓶颈[4]。
非纯函数式语言,同时提供了单赋值和真赋值(尽管相比指令式编程语言而言真赋值典型的较少使用)。例如,在Scheme中,单赋值(通过let
),和真赋值(通过set!
),二者都可以用于所有变量上,并提供专门的原语(primitive)用于在列表、向量、字符串等之内做破坏性更新。在OCaml中,只有单赋值,通过let name = value
语法,被允许用于变量;而破坏性更新,可通过单独的<-
算符,用于数组的元素和字符串,还可用于已经被编程者显式声明为可变(意味着能够在其初始化声明之后被变更)的记录字段和对象。
使用单赋值的函数式编程语言,包括Clojure(针对数据结构,而非变量)、Erlang(相比Haskell,它接受多次赋值,如果值相等的话)、F#、Haskell、Lava、OCaml、Oz(对用数据流变量,而非cell)、Racket(对于一些数据结构如列表,而非符号)、SASL、Scala(对于变量)、SISAL、Standard ML。非回溯的Prolog代码可以被看作“明显的”单赋值,这里明显的含义为,它的(命名)变量可以显式的处在未赋值状态,或只能准确的被设置一次。相反的,在Haskell中,没有未赋值变量,而所有变量可以看作在创建时就被隐式的设定了它的值(更精确的说是设置了计算对象在“在需要时”产生它的值)。
指定語句的回傳值
[编辑]在一些編程語言中,指定敘述的整個語句可能會傳回某種型別的一個值,而在其它語言中則不會。
在 C 編程語言中指定語句只會單純返回指定值,而允許這樣子的片語 x = y = a
,其中指定語句 y = a
返回值 a
,然後將值指定到 x
。在諸如 while ((ch = getchar()) != EOF) {…}
的語句中,函數的返回值可用於控制迴圈,同時將相同的值指定給變量 ch
。
在其它編程語言中例如 Scheme,指定語句的返回值是未定義的,而且這些片語無效。
在 Haskell 中沒有變量指定;但類似於指定的操作(如分配給數組的字段或可變數據結構的字段)通常以 unit
型別為單位進行求值,unit
型別以 ()
表示。這種型別只有一個可能的值,因此不包含任何信息。它通常是純粹為了副作用而評估的表達型別。
赋值的变体形式
[编辑]特定使用模式也非常常见,因此经常有支持它们的特殊语法。这些主要是减少源代码冗长的语法糖,但也能辅助代码读者理解编程者的意图,并提供给编译器进行可能的优化的线索。
增广赋值
[编辑]所赋予的值依赖于先前的值是很常见的,很多指令式语言,尤其是C及其主要派生者,提供了叫做增广赋值的特殊算符,比如*=
,则a = 2*a
可以转而写为a *= 2
[5]。
链式赋值
[编辑]语句如w = x = y = z
叫做“链式赋值”,其中z
的被赋给多个变量w
、x
和y
。链式赋值经常用来初始化多个变量,比如a = b = c = d = f = 0
。
并行赋值
[编辑]一些编程语言,比如APL、Common Lisp[6]、Go[7]、JavaScript(自从1.7)、Lua、Maple、occam 2[8]、Perl[9]、PHP、Python[10]、REBOL、Ruby[11]、Windows PowerShell,允许多个变量被并行的赋值,语法如下:
a, b := 0, 1
它同时赋值0
到a
和1
到b
。这经常叫做并行(parallel)赋值;它是CPL语言于1963年介入的,当时名字叫做同时(simultaneous)赋值[12],有时也叫做多(multiple)赋值,但这在与单(single)赋值一起用时会产生混淆,因为它们不是对比的。如果赋值的右手侧是一个单一变量(比如一个数组或结构),这个特征就叫做解包(unpacking)[13]或解构(destructuring)赋值[14]:
var list := {0, 1} a, b := list
这个列表将被解包使得赋值0
至a
和1
至b
。进一步的:
a, b := b, a
对换a
和b
的值。在没有并行赋值的语言中,这必须通过临时变量来书写:
var t := a a := b b := t
因为a := b; b := a
将把a
和b
二者都赋值为b
最初的值。
一些语言,比如Go和Python,将并行赋值、元组和自动元组解包结合起来,允许从一个单一函数返回多个值,比如如下Python的例子:
def f():
return 1, 2
a, b = f()
而其他语言,比如C#,要求使用圆括号的显式元组构造和解构,如下面例子这样:
(a, b) = (b, a);
(string, int) f() => ("foo", 1);
var (a, b) = f();
这提供了从一个函数返回多个值要使用输出参数的一种替代方式。这最早见于CLU语言(1974年),而CLU推动了一般的并行赋值变得流行。
在C和C++中,逗号运算符,在允许多个赋值出现在一个单一语句上类似于并行赋值,写a = 1, b = 2
替代a, b = 1, 2
。这主要用在for循环中,在其他语言比如Go中,被替代为并行赋值[15]。但是上述C++代码不确保完全的同时性,因为代码a = b, b = a+1
的右侧项是在左侧项之后运算的。在语言如Python中,a, b = b, a+1
将并发的赋值两个变量,使用最初的a
的值来计算新b
的值.
指定與等式符號
[编辑]標記法
[编辑]複製分配的兩個最常見的表示形式是等號(=
)和冒號等於(:=
)。這兩種形式都可以在語義上表示賦值語句或賦值運算符(它也具有值),這取決於語言用法。
variable = expression
Fortran, PL/I, C (和派生者比如C++, Java等), Bourne shell, Python, Go (赋值预先声明的变量), R, Windows PowerShell等。 variable := expression
ALGOL (和派生者), Simula, CPL, BCPL, Pascal[16] (和派生者比如Modula), Mary, PL/M, Ada, Smalltalk, Eiffel[17][18], Oberon, Dylan[19], Seed7, Go (声明和定义变量的快捷方式)[20], Io, AMPL, ML[21], AutoHotkey等。
其他可能性包括左箭頭或關鍵字,但還有其他更罕見的變體:
variable << expression
Magik variable <- expression
F#, OCaml, R, S variable <<- expression
R assign("variable", expression)
R variable ← expression
APL[22], Smalltalk variable =: expression
J LET variable = expression
BASIC let variable := expression
XQuery set variable to expression
AppleScript set variable = expression
C shell Set-Variable variable (expression)
Windows PowerShell variable : expression
Macsyma, Maxima, Rebol var variable expression
mIRC脚本语言 reference-variable :- reference-expression
Simula
數學偽代碼分配通常用左箭頭表示。有些平台將表達式放在左側,變量放在右側:
MOVE expression TO variable
COBOL expression → variable
TI-BASIC, Casio BASIC expression -> variable
BETA, R put expression into variable
LiveCode
一些面向運算式的語言比如 Lisp 和 Tcl,對所有語句(包括賦值)統一使用前綴(或後綴)語法。
(setf variable expression)
Common Lisp (set! variable expression)
Scheme[23][24][25] set variable expression
Tcl expression variable !
Forth
另見
[编辑]註釋
[编辑]- ^ 1.0 1.1 1.2 Crossing borders: Explore functional programming with Haskell 互联网档案馆的存檔,存档日期November 19, 2010,., by Bruce Tate
- ^ Mitchell, John C. Concepts in programming languages. Cambridge University Press. 2003: 23 [3 January 2011]. ISBN 978-0-521-78098-8.
- ^ Imperative Programming Languages (IPL) (PDF). gwu.edu. [20 April 2018]. (原始内容存档 (PDF)于2021-01-18).
- ^ John C. Mitchell. Concepts in programming languages. Cambridge University Press. 2003: 81–82 [3 January 2011]. ISBN 978-0-521-78098-8.
- ^ Ruediger-Marcus Flaig. Bioinformatics programming in Python: a practical course for beginners. Wiley-VCH. 2008: 98–99 [25 December 2010]. ISBN 978-3-527-32094-3. (原始内容存档于2017-04-19).
- ^ CLHS: Macro SETF, PSETF. Common Lisp Hyperspec. LispWorks. [23 April 2019]. (原始内容存档于2020-11-30).
- ^ The Go Programming Language Specification: Assignments (页面存档备份,存于互联网档案馆)
- ^ INMOS Limited (编). Occam 2 Reference Manual. New Jersey: Prentice Hall. 1988. ISBN 0-13-629312-3.
- ^ Wall, Larry; Christiansen, Tom; Schwartz, Randal C. Perl Programming Language 2. Cambridge: O´Reilly. 1996. ISBN 1-56592-149-6.
- ^ Lutz, Mark. Python Programming Language 2. Sebastopol: O´Reilly. 2001. ISBN 0-596-00085-5.
- ^ Thomas, David; Hunt, Andrew. Programming Ruby: The Pragmatic Programmer's Guide. Upper Saddle River: Addison Wesley. 2001. ISBN 0-201-71089-7.
- ^ D.W. Barron et al., "The main features of CPL", Computer Journal 6:2:140 (1963). full text (subscription) Archive.is的存檔,存档日期2012-07-07
- ^ PEP 3132 -- Extended Iterable Unpacking. legacy.python.org. [20 April 2018]. (原始内容存档于2016-05-13).
- ^ Destructuring assignment. MDN Web Docs. [20 April 2018]. (原始内容存档于2021-02-10).
- ^ Effective Go (页面存档备份,存于互联网档案馆): for (页面存档备份,存于互联网档案馆), "Finally, Go has no comma operator and ++ and -- are statements not expressions. Thus if you want to run multiple variables in a for you should use parallel assignment (although that precludes ++ and --)."
- ^ Moore, Lawrie. Foundations of Programming with Pascal. New York: John Wiley & Sons. 1980. ISBN 0-470-26939-1.
- ^ Meyer, Bertrand. Eiffel the Language. Hemel Hempstead: Prentice Hall International(UK). 1992. ISBN 0-13-247925-7.
- ^ Wiener, Richard. An Object-Oriented Introduction to Computer Science Using Eiffel. Upper Saddle River, New Jersey: Prentice Hall. 1996. ISBN 0-13-183872-5.
- ^ Feinberg, Neal; Keene, Sonya E.; Mathews, Robert O.; Withington, P. Tucker. Dylan Programming. Massachusetts: Addison Wesley. 1997. ISBN 0-201-47976-1.
- ^ The Go Programming Language Specification - The Go Programming Language. golang.org. [20 April 2018]. (原始内容存档于2021-03-18).
- ^ Ullman, Jeffrey D. Elements of ML Programming: ML97 Edition. Englewood Cliffs, New Jersey: Prentice Hall. 1998. ISBN 0-13-790387-1.
- ^ Iverson, Kenneth E. A Programming Language. John Wiley and Sons. 1962. ISBN 0-471-43014-5. (原始内容存档于2009年6月4日).
- ^ Dybvig, R. Kent. The Scheme Programming Language: ANSI Scheme. New Jersey: Prentice Hall. 1996. ISBN 0-13-454646-6.
- ^ Smith, Jerry D. Introduction to Scheme. New Jersey: Prentice Hall. 1988. ISBN 0-13-496712-7.
- ^ Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie. Structure and Interpretation of Computer Programs. New Jersey: McGraw-Hill. 1996. ISBN 0-07-000484-6.