【问题标题】:Simplistic way to think of the apply function考虑应用函数的简单方法
【发布时间】:2021-06-21 21:17:59
【问题描述】:

在尝试“减少”apply 函数时,正确的理解是否正确?

例如(apply func args)

  1. 删除(apply 和匹配的)
  2. 插入func 作为args 的第一个元素,如有必要,将外部引号移至一级。

这是一个应用程序:

; (add-pairs '((1 2)(3 4))) --> (3 7)
(define (add-pairs ps)
  (if (null? ps) nil
     (cons (+ (car (car ps)) (cadr (car ps))) (add-pairs (cdr ps)))))
(apply add-pairs '(((1 2) (3 4))))
xxxxxxx                          x
; Remove the "(apply " and matching ")"
add-pairs '(((1 2) (3 4)))
------------^
; Insert the function into the args, moving the quote in one level if required.
(add-pairs '((1 2) (3 4)))

以上是显示apply 如何添加的准确方法,还是我遗漏了什么?

【问题讨论】:

  • apply 通常用于动态计算参数时,因此无需删除括号,也无需移动引号。
  • 例如(apply + list-of-numbers)
  • @Barmar 怎么样:(apply + '(1 2)) --> (+ 1 2) 那里去掉了一层括号,不是吗?
  • 不要从语法上考虑它,了解它做什么
  • 它只是将一个列表传播到函数的参数列表中。

标签: scheme lisp racket apply sicp


【解决方案1】:

这个例子很不幸,因为它只在“括号的开头”之后留下 一个 参数。但是,是的,我也是这么想的。越简单越好,:)只要是正确的。

除了列表中的值当然首先被评估,所以这不是一个简单的句法过程。但作为一个基本的例子,

(apply + (list 1 2 3)) 
== 
(      +       1 2 3 )

arguments 周围的括号会消失。

有关重要示例,请参阅

【讨论】:

  • 那个链接的答案太酷了,真的很让人费解,感谢分享。
  • 顺便说一句,它还表明 apply 不止于此:(apply list 1 2 3 '(4)) 也有效并返回 '(1 2 3 4)
【解决方案2】:

您似乎了解 Python。我个人认为Scheme中的apply和Python中的星号*很像。

假设您想要压缩几个列表,这些列表本身就被打包在一个列表中。试图打电话

list_of_lists = [[1, 2],[3, 4]]
zip(list_of_lists)

不会给你[(1, 3), (2, 4)],所以你写

zip(*list_of_lists)
# here it's the same as
zip(list_of_lists[0], list_of_lists[1])

使用可迭代解包运算符*。 Racket/Scheme 中的一个(相当完整的)替代方案是使用应用函数:

(define list-of-lists '((1 2) (3 4)))
(apply zip list-of-lists)
;; here it's the same as
(zip (car list-of-lists) (cadr list-of-lists))

(当然,如果 Scheme 中的 zip 的定义方式与 Python 中相同,需要任意数量的参数)

但是你绝对可以在这里看到区别,语法上的区别。在apply 的Python 版本中,我们将这个*“应用”到参数,然后将“返回”的内容传递给调用函数(zip)。 Scheme 就像一种函数式语言,将所有内容都从里到外颠倒过来(至少我是这么看的):您将apply“应用”到函数及其参数,然后它自己处理所有内容。

另一个显着的区别是,当然,Scheme中的apply是一个普通函数,所以我们可以写成e.g.

(define (apply-func-to-sum-and-args func args)
  (func + args))
(apply-func-to-sum-and-args apply (list 1 2 3))
;; returns 6

虽然我相信(如果我错了,请纠正我)这个函数不能用纯 Scheme 编写,并且它在后台调用了一些奇怪的 C 函数。

【讨论】:

  • Scheme 中有zip,可以使用任意数量的参数。它被称为map。 :) 更具体地说,(map list (list 1 2) (list 3 4) ...) == (list (list 1 3) (list 2 4) ...)
  • @WillNess,哦,确实!)我总是忘记 Scheme 中的 map 本身就是可变参数)
  • 我不确定解包运算符是否是考虑apply 的好方法,它接受任意数量的参数,其中只有最后一个参数必须是一个列表。所以(apply + 2 4 6 '(8 10 12)) --> 42。这允许zip 实现为:(define (zip . xss) (apply map list xss))(zip '(a b c) '(1 2 3) '(x y z)) --> ((a 1 x) (b 2 y) (c 3 z))。一般来说,我认为匹配来自(非常)不同语言的语言特征以试图理解其中一种语言是一种糟糕且具有误导性的策略。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-11
  • 1970-01-01
  • 2014-01-07
  • 1970-01-01
相关资源
最近更新 更多