当前位置:  开发笔记 > 编程语言 > 正文

表达与陈述

如何解决《表达与陈述》经验,为你挑选了7个好方法。

我问的是关于c#,但我认为它在大多数其他语言中都是一样的.

有没有人对表达式语句有一个很好的定义,有什么区别?



1> Joel Spolsky..:

表达式:评估值的东西.示例:1 + 2/x
语句:执行某些操作的代码行.示例:GOTO 100

在最早的通用编程语言中,如FORTRAN,区别非常清晰.在FORTRAN中,声明是一个执行单元,你做了一件事.它不被称为"线"的唯一原因是因为有时它跨越多条线.表达式本身无法做任何事情......你必须将它分配给变量.

1 + 2 / X

是FORTRAN中的错误,因为它不执行任何操作.你必须对那个表达做一些事情:

X = 1 + 2 / X

FORTRAN没有我们今天所知的语法 - 这个想法与Backus-Naur Form(BNF)一起被发明,作为Algol-60定义的一部分.在那一点上,语义上的区别("有一个值"与"做某事")在语法中得到了体现:一种短语是表达式,另一种是语句,解析器可以区分它们.

后来语言的设计者模糊了这种区别:他们允许语法表达式做事,并且他们允许具有值的句法语句.仍然存在的最早的流行语言示例是C.C的设计者意识到,如果允许您评估表达式并丢弃结果,则不会造成任何伤害.在C语言中,每个语法表达式都可以通过在末尾添加分号来形成语句:

1 + 2 / x;

虽然绝对不会发生任何事情,但这是完全合法的陈述.类似地,在C中,表达式可能有副作用 - 它可以改变某些东西.

1 + 2 / callfunc(12);

因为callfunc可能只是做一些有用的事情

一旦允许任何表达式成为语句,您也可以在表达式中允许赋值运算符(=).这就是为什么C让你做的事情

callfunc(x = 2);

这将计算表达式x = 2(将值2赋值给x),然后将该值(2)传递给函数callfunc.

表达式和语句的这种模糊发生在所有C衍生物(C,C++,C#和Java)中,它们仍然有一些语句(如while),但几乎允许任何表达式用作语句(仅在C#中赋值,调用,递增和递减表达式可用作语句;请参阅Scott Wisniewski的答案).

有两个"语法类别"(这是事物语句和表达式的技术名称)可能导致重复工作.例如,C有两种形式的条件,即语句形式

if (E) S1; else S2;

和表达形式

E ? E1 : E2

有时人们想要不存在的重复:例如,在标准C中,只有一个语句可以声明一个新的局部变量 - 但这种能力足够有用,GNU C编译器提供了一个GNU扩展,使表达式能够声明一个局部变量也是如此.

其他语言的设计者不喜欢这种重复,他们很早就看到如果表达式既有副作用也有值,那么语句和表达式之间的句法区别并不是那么有用 - 所以他们摆脱了它.Haskell,Icon,Lisp和ML都是没有语法语句的语言 - 它们只有表达式.即使是类结构化循环和条件形式也被认为是表达式,它们具有值 - 但不是非常有趣的.


如果我在这里没有误解你,你似乎声称"(setf(第三个foo)'goose)"是一个表达式,而不是一个声明,因为它是Lisp,"没有语句",因为Lisp比C语言早了十多年,这是"在表达和语句之间模糊界限的最早流行语言." 可以向我解释一下这个细节吗?
如果我没有弄错,`callfunc(x = 2);`将`x`传递给`callfunc`,而不是`2`.如果`x`是一个浮点数,则调用`callfunc(float)`,而不是`callfunc(int)`.在C++中,如果将`x = y`传递给`func`,并且`func`接受引用并更改它,它会改变`x`,而不是`y`.
@Curt Sampson,你有没有问过这个单独的问题?

2> Mark Harriso..:

表达式是任何产生值的东西:2 + 2

语句是程序执行的基本"块"之一.

请注意,在C中,"="实际上是一个运算符,它执行两项操作:

返回右手子表达式的值.

将右侧子表达式的值复制到左侧的变量中.

这是ANSI C语法的摘录.您可以看到C没有很多不同类型的语句......程序中的大多数语句都是表达式语句,即最后带分号的表达式.

statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;

expression_statement
    : ';'
    | expression ';'
    ;

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html


关于语句是什么的错误逻辑.声明性程序也可以执行,但声明性程序没有语句.声明是并且确实["副作用"](http://stackoverflow.com/a/8357604/615784),即必要.比照 [我的回答](http://stackoverflow.com/a/8450398/615784).

3> Patrick..:

表达式是返回值的东西,而语句则不是.

举些例子:

1 + 2 * 4 * foo.bar()     //Expression
foo.voidFunc(1);          //Statement

两者之间的大问题是你可以将表达式链接在一起,而语句不能被链接.


肯定的陈述可以链接.{stmt1; stmt2; stmt3;}是一个链,它本身也是一个(复合)语句.
`foo.voidFunc(1);`是一个带有void值的表达式.`while`和`if`是陈述.

4> Mike Stone..:

你可以在维基百科上找到它,但是表达式被评估为某个值,而语句没有评估值.

因此,表达式可以用在语句中,但不能用于其他方式.

请注意,某些语言(例如Lisp,我相信Ruby和许多其他语言)不区分语句与表达式......在这些语言中,一切都是表达式,可以与其他表达式链接.



5> Conal..:

为了解释表达式与语句的可组合性(可链接性)的重要差异,我最喜欢的参考是John Backus的图灵奖论文,可以从冯·诺依曼风格中解放出编程吗?.

命令式语言(Fortran,C,Java,...)强调结构化程序的语句,并将表达式作为一种后思.功能语言强调表达. 函数式语言具有如此强大的表达式,而语句可以完全消除.



6> Mark Cidade..:

可以计算表达式以获取值,而语句不返回值(它们的类型为void).

函数调用表达式当然也可以被认为是语句,但除非执行环境有一个特殊的内置变量来保存返回的值,否则无法检索它.

面向语句的语言要求所有过程都是语句列表.面向表达式的语言,可能是所有函数式语言,是表达式列表,或者在LISP的情况下,是表示表达式列表的一个长S表达式.

尽管两种类型都可以组合,但只要类型匹配,大多数表达式都可以任意组合.每种类型的语句都有自己的组合其他语句的方式,如果他们可以做到这一切.Foreach和if语句要求单个语句或所有从属语句一个接一个地进入语句块,除非子语句允许其自己的子语句.

语句还可以包含表达式,其中表达式实际上不包含任何语句.但是,一个例外是lambda表达式,它表示一个函数,因此可以包含函数可以包含的任何内容,除非该语言仅允许有限的lambdas,如Python的单表达式lambda.

在基于表达式的语言中,您只需要一个函数的单个表达式,因为所有控制结构都返回一个值(其中很多都返回NIL).由于函数中最后一次计算的表达式是返回值,因此不需要return语句.



7> Matthew Schi..:

简单地说:表达式求值为值,语句则不求值.

推荐阅读
保佑欣疼你的芯疼
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有