【问题标题】:Differences between Expression vs Function表达式与函数之间的差异
【发布时间】:2021-12-08 14:38:49
【问题描述】:

表达式和函数在形式上的区别是什么?我通过查看它知道区别,但我正在寻找对它的彻底理解。例如,展示一些来自 Scheme 或 Python 的示例:

; scheme
(display "hello")                          # expression
((lambda () (display "hello")))            # unnamed lambda
(define hi (lambda () (display "hello")))  # named lambda

# python
>>> print ('hello')          
>>> lambda: print ('hello')
>>> hi = lambda: print ('hello')

在我的初步思考中,我认为不同之处在于:

  1. 函数具有名称并且可以被引用(尽管可以将表达式分配给变量?)
  2. 函数可以带参数(表达式可以带参数吗?)
  3. 一个函数可以有一个作用域/封装并包含多个语句。

【问题讨论】:

  • Python 中的函数可以通过语句 (def) 或表达式 (lambda) 来定义,它们并不是两个可比较的东西。
  • 虽然是不同的东西,但它们都有共同的属性:它们评估为一个值,是可组合的和一流的。语句没有这些。

标签: function functional-programming expression


【解决方案1】:

您可能在这里将苹果与橙子进行比较。 表达式是一种句法形式。它是您代码的一部分,描述了代码是如何解析的。 a + bprint(x) 是表达式,但 abx 也是。表达式通常由较小的表达式组成,通常有好几层。

另一方面,函数关注的是语义,而不是语法。这是一个运行时值。有人可能会说

lambda x: x + 1

一个函数。为了完全正确,我会说这些字母解析为一个表达式,当 Python 解释器 求值 时,它会产生一个函数。但这太罗嗦了,所以我们通常会跳过中间人,直接说 lambda is 是一个函数。

将表达式分配给变量是没有意义的。如果我写x = 1 + 1,我不会将表达式 1 + 1 分配给变量。我将计算一加一的结果分配给该变量。另一方面,如果我写x = lambda: 2,那么我实际上是在为变量x 分配一个函数。函数存在于运行时;表达式纯粹是一个解析结构。

【讨论】:

  • 感谢您。你是什​​么意思:Functions exist at runtime; expressions are purely a parsing construct.?例如,如果表达式是 now() + interval 1 day 怎么办?
  • 我不明白这个问题,恐怕。这不是有效的 Python 语法。虽然如果是now() + 1,那么我会说它是一个加法表达式,其中右侧是调用表达式,左侧是数字文字表达式。
  • 当然,我是用 SQL 编写的,但在 python 中会是:datetime.datetime.now() + datetime.timedelta(days=1)
  • 在许多语言中,您当然可以将表达式分配给变量,例如在 R 中:x <- quote(1+1)。这种“语言编程”或“非标准评估”在许多情况下都很有用
  • @HongOoi 确实如此。一旦你进入反射和宏扩展,事情就会变得真的有趣。
【解决方案2】:

如果您在纯 FP 的上下文中考虑它,它不允许副作用(因此不需要语句),那么函数只是具有特定类型的值(A ->乙)。表达式是归约为一个值的符号组合。

考虑以下示例:

a = 1 + (2 * 3);
b = a * 10;

add1 = x -> x + 1;

applyTwice = f -> x -> f(f(x))

add2 = applyTwice(add1)

a、b、add1、applyTwice 和 add2 都是已定义的名称以保存由特定表达式计算的值。前两个表达式分别缩减为 7 和 70,后三个是函数值。最后一个 add2 是通过一个简化为函数值的表达式来定义的。

关于你提出的观点:

  • 函数具有名称并且可以被引用(尽管可以将表达式分配给变量?)

大多数语言都允许您将任何表达式分配给名称。

  • 函数可以带参数(表达式可以带参数吗?)

函数有参数,不像非函数。如上所述,表达式可以简化为函数值。

  • 一个函数可以有一个作用域/封装并包含多个语句。

函数体本质上只是一个表达式,尽管它包含引用函数参数的未绑定变量。语句会分散注意力 - 某些语言还允许您将一系列语句的结果分配给非函数变量,例如:

result = {
    a = f();
    b = g(a);
    h(b);
}

(即h(b)的返回值赋值给result)

【讨论】:

    【解决方案3】:

    首先回答你的问题:

    1. 一个函数有一个名字并且可以被引用(虽然是一个表达式
      可以分配给变量吗?) --- 是的,可以将表达式分配给变量,但与函数不同,您不能使用参数调用表达式。
    2. 函数可以带参数(表达式可以吗?) --- 不,表达式不能带参数。
    3. 一个函数可以有一个作用域/封装并包含多个语句。 -- 是的

    函数式编程 (FP) 都是关于表达式的,因为在 FP 中,一切都简化为表达式。 函数在 FP 中用作对象。也就是说,它们通常在程序中以与其他变量大致相同的方式传递。 例如 - Python 提供了几个函数,这些函数支持函数式编程方法,比如函数 map(aFunction, aSequence)

    此函数将 Python 函数 aFunction 应用于 aSequence 的每个成员。表达式:

    L = map(eggs, spam)
    print L
    

    导致在 L 中返回一个新列表(在这种情况下与垃圾邮件相同)。

    【讨论】:

      【解决方案4】:

      表达是一个模糊的概念。如果你要求正式的定义,它在不同的语言中会有所不同。

      1。形式语法定义

      正式的语法定义通常以巴科斯-瑙尔形式编写。它是一种描述另一种语言的语言。 您可以查看LispPythonHaskell 的正式定义。

      2。编译器/解释器是如何实现的

      一些编程语言提供正式的语义定义。 但是,这种承诺的语义如何工作取决于编译器的实现。

      3。教程或文档怎么说

      TBH,我不确定教程或文档中对表达式和函数的定义是否可靠。它可能与正式定义不同。猜猜你被它弄糊涂了?

      题外话:以正确的方式学习新的编程语言:阅读它们的语法和语义正式定义:P。

      【讨论】:

        猜你喜欢
        • 2014-06-29
        • 1970-01-01
        • 2013-04-12
        • 2017-12-24
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多