【问题标题】:Are 'combinations whose operators are themselves compound expressions' synonymous with Variable Functions?“运算符本身就是复合表达式的组合”是变量函数的同义词吗?
【发布时间】:2019-07-18 09:32:11
【问题描述】:

对于此处缺少一些词汇,我提前道歉。通过Structure and Interpretation of Computer Programs,早期提到了“运算符本身就是复合表达式的组合”,例如:

(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

其中(if (> b 0) + -) 组合被评估为+-,然后评估为例如(+ a b) 如果 b 大于零。

我的问题是:这与变量函数(例如in PHP)有什么不同,又有何不同?另外,变量函数和这个函数与使用Javascript-style object references有什么不同吗?

【问题讨论】:

    标签: function scheme evaluation function-call


    【解决方案1】:

    从 Lisp 的角度来看,这里的重要概念是一种语言是“lisp-1”还是“lisp-2”。这两者的区别在于:在一个看起来像函数应用程序的表达式中,代表要应用的函数的事物是如何求值的?

    所以,在 Lisps 中,看起来像函数应用程序的东西看起来像一个列表:

    (f a b ...)
    

    在考虑这样的事情时,系统必须做三件事:

    1. 确定它一个函数应用程序(例如,(if ...) 不是,也不是一个作为宏的表单);
    2. 如果是,请评估函数及其参数;
    3. 调用函数,将评估其参数的结果传递给它。

    (注意:我在这里假设了所谓的 applicative-order 评估:normal-order 语言做不同的事情。)

    问题是 (2) 是如何发生的。

    • lisp-1 以与所有其他位置完全相同的方式以这种形式评估函数位置(第一个位置)。因此函数位置可以包含一个完全任意的表达式。所以((if add + -) 1 2) 非常好,例如(let ((op ...)) (op ...))
    • lisp-2 对函数位置使用了一些特殊规则,特别是对于 lisp-2,符号的“函数值”与普通值位于不同的命名空间中。这意味着允许的内容不是通用表达式,而是规则允许的任何内容。因此,例如,在 lisp-2 中,这样的事情不起作用:(let ((op (lambda ...))) (op ...)),但这样的事情确实起作用:(let ((car ...)) (car car))

    众所周知,Scheme 是 lisp-1,Common Lisp 是 lisp-2。

    那么,我认为,回答你的问题的方法是认识到这个概念可以很好地应用于其他语言。

    • JavaScript 是一个 lisp-1,所以看起来像函数应用程序的东西的函数位置只是正常地完美评估。
    • Python 是一个 lisp-1。
    • 我不知道 PHP 是什么。

    请注意,在这些语言中,您知道某物是函数应用程序的方式与在 Lisp 中完全不同,但重要的问题是,一旦您知道这一点,您如何评估函数位置?

    【讨论】:

    • 我们不需要funcalllet-defined car吗?
    • @WillNess:如果我们想调用它,我们会这样做,但我想调用普通的car 函数。显然这在实践中会是很糟糕的代码:我承认像 (destructuring-bind (first . rest) ... ...) 这样的事情,但我会尽量避免在正文中说 (first first),因为它只是无缘无故地令人困惑。
    • 啊,所以你的意思是 let-defined car 是一些数据,而不是一个函数......
    【解决方案2】:

    在Scheme(SICP使用)中,可以在函数位置使用变量。

    首先我们尝试使用符号+ 作为函数:

    尝试将符号用作函数

    > (define foo '+)
    > foo
    +
    > (foo 1 2)
    Exception: attempt to apply non-procedure +
    

    不幸的是,这不起作用:foo 计算为符号 +,这本身不是函数

    使用函数对象

    但这有效:

    > (define foo +)
    > (foo 1 2)
    3
    

    这里foo被设置为+的值,这是一个函数对象。 foo 也将评估为该对象。因此(foo 1 2) 的计算结果为3

    【讨论】:

      【解决方案3】:

      JavaScript 中的所有函数都是变量,它允许在运算符位置使用表达式:

      function plus (a, b) {
        return a + b;
      }
      
      plus; // => [Function: plus]
      
      function minus (a, b) {
        return a - b
      }
      
      minus; // => [Function: minus]
      
      function plusAbs (a, b) {
        return (b > 0 ? plus : minus)(a, b);
      }
      
      plusAbs(3, -3); // => 6
      plusAbs(3, 3);  // => 6
      
      var plus = 4;
      plus; // => 4 (no longer a function)
      plusAbs(3, 3);  // ERROR! 4 is not a function
      

      正如 Scheme 它评估为 plusminus 而是 plusminus 评估的结果。例如。 [function minus]not 变量。

      PHP 中的函数不能通过名称来实现,而是绑定到函数的变量:

      function plusAbs ($a, $b) { 
        $add = function($a, $b) { return $a+$b; }; 
        $sub = function($a, $b) { return $a-$b; }; 
        return ($b < 0 ? $sub : $add)($a, $b); 
      }
      plusAbs(3, -3); // => 6
      

      与命名函数最接近:

      function add($a, $b) { return $a+$b; }
      function sub($a, $b) { return $a-$b; }
      
      function plusAbs ($a, $b) { 
        return call_user_func($b < 0 ? 'sub' : 'add', $a, $b); 
      }
      plusAbs(3, -3); // => 6
      

      请注意,这在操作符位置不再有表达式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-13
        • 2017-06-09
        • 2017-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-17
        • 2017-01-09
        相关资源
        最近更新 更多