地图功能的输出?
output of map function?
您好,我正在尝试理解以下代码的输出
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
当我使用
(map (p q) (list 1 2 3))
结果是
(1 16 81)
答案不应该是
(1 4 9) ?
提供两个函数:
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
q
是一个函数,它接受一个数字并将其平方。
p
是一个接受函数 x
和 returns 的函数,其中 x
两次应用于 y
。请注意,在 p
中,x
位于窗体的功能位置,并已在清单中突出显示。
不幸的是,在这两个表达式中使用 x
令人困惑。您可以将 lambda 表达式中的任何变量替换为任何其他变量,例如 function
- 这称为 alpha 转换 - https://en.wikipedia.org/wiki/Lambda_calculus - 您可以将任何命名函数的名称更改为更合理的名称。因此,我已将平方函数 q
重命名为 square
,并将 p
重命名为 do-twice
。
(define do-twice (lambda (function) (lambda (y) (function (function y)))))
(define square (lambda (x) (* x x)))
当你评估 do-twice square
.
时发生的事情就变得很明显了
您正在 (p q)
映射列表,因此请先弄清楚那是什么。
使用替换法,你得到
(p q)
==> ((lambda (x) (lambda (y) (x (x y)))) q)
==> (lambda (y) (q (q y)))
==> (lambda (y) (q ((lambda (x) (* x x)) y)))
==> (lambda (y) (q (* y y)))
==> (lambda (y) ((lambda (x) (* x x)) (* y y)))
==> (lambda (y) (* (* y y) (* y y)))
所以 (p q)
是一个函数,它接受一个数字并对其平方进行平方。
Francis King 的 很清楚,
这只是受其启发的扩展脚注。
将标识符替换为助记符(将q
重写为square
)可以更容易理解代码[1]
Procedures as [first-class] values in Scheme [2] 经常通过例子介绍 lambda
:
> (define twelve 12)
> (define square (lambda (x) (* x x)))
> (square twelve)
144
>
正如上面代码中的字符12
是一个数字的表示,
字符 (lambda (x) (* x x))
是过程的表示:
(number? 12)
=> #t, (procedure? (lambda (x) (* x x)))
=> #t
另外两次代码重写可能会有帮助:
使用“短格式”define
作为过程,并注释定义
带有类型签名(参数和结果类型):
> (define (square x) (* x x)) ;; Number -> Number
> (square 3)
9
> (define (do-twice f x) ;; (X -> X) X -> X
(f (f x)))
> (do-twice square 3)
81
> (map (lambda (x) (do-twice square x))
'(1 2 3))
(1 16 81)
>
注意这个do-twice
还没有对应问题的p
:
这两次 map 的第一个参数需要:
(map do-twice (make-list 3 square) '(1 2 3))
映射一个列表需要一个参数的函数,所以必须产生两次
(define (do-twice x) (f (f x)))
作为其值:
> (define (do-twice-with f) ;; (X -> X) -> (X -> X)
(define (do-twice x) ;; X -> X
(f (f x)))
do-twice)
> ((do-twice-with square) 3)
81
> (map (do-twice-with square)
'(1 2 3))
(1 16 81)
>
所以do-twice-with
就是问题中的函数p
。
do-twice-with
需要函数参数 (X -> X),但 X 可以是任何类型,因此:
> (define (repeat s) ;; String -> String
(string-append s " " s))
> ((do-twice-with repeat) "buffalo")
"buffalo buffalo buffalo buffalo"
和 do-twice-with
本身具有类型 (X' -> X')(X' 代表 (X -> X)),所以可以
应用于自身:
> (((do-twice-with do-twice-with) square) 3)
43046721
> (((do-twice-with do-twice-with) repeat) "buffalo") [3]
"buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo"
((((do-twice-with do-twice-with) do-twice-with) square) 3)
留作
reader...
练习
[1]“Naming is perhaps the most powerful abstracting notion we have”[盖伊·斯蒂尔]
[2] https://walker.cs.grinnell.edu/courses/151.sp04/readings/procedures-as-values.xhtml
[3] https://en.wikipedia.org/wiki/Buffalo_buffalo_Buffalo_buffalo_buffalo_buffalo_Buffalo_buffalo
您好,我正在尝试理解以下代码的输出
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
当我使用
(map (p q) (list 1 2 3))
结果是
(1 16 81)
答案不应该是
(1 4 9) ?
提供两个函数:
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
q
是一个函数,它接受一个数字并将其平方。
p
是一个接受函数 x
和 returns 的函数,其中 x
两次应用于 y
。请注意,在 p
中,x
位于窗体的功能位置,并已在清单中突出显示。
不幸的是,在这两个表达式中使用 x
令人困惑。您可以将 lambda 表达式中的任何变量替换为任何其他变量,例如 function
- 这称为 alpha 转换 - https://en.wikipedia.org/wiki/Lambda_calculus - 您可以将任何命名函数的名称更改为更合理的名称。因此,我已将平方函数 q
重命名为 square
,并将 p
重命名为 do-twice
。
(define do-twice (lambda (function) (lambda (y) (function (function y)))))
(define square (lambda (x) (* x x)))
当你评估 do-twice square
.
您正在 (p q)
映射列表,因此请先弄清楚那是什么。
使用替换法,你得到
(p q)
==> ((lambda (x) (lambda (y) (x (x y)))) q)
==> (lambda (y) (q (q y)))
==> (lambda (y) (q ((lambda (x) (* x x)) y)))
==> (lambda (y) (q (* y y)))
==> (lambda (y) ((lambda (x) (* x x)) (* y y)))
==> (lambda (y) (* (* y y) (* y y)))
所以 (p q)
是一个函数,它接受一个数字并对其平方进行平方。
Francis King 的
将标识符替换为助记符(将q
重写为square
)可以更容易理解代码[1]
Procedures as [first-class] values in Scheme [2] 经常通过例子介绍 lambda
:
> (define twelve 12)
> (define square (lambda (x) (* x x)))
> (square twelve)
144
>
正如上面代码中的字符12
是一个数字的表示,
字符 (lambda (x) (* x x))
是过程的表示:
(number? 12)
=> #t, (procedure? (lambda (x) (* x x)))
=> #t
另外两次代码重写可能会有帮助:
使用“短格式”define
作为过程,并注释定义
带有类型签名(参数和结果类型):
> (define (square x) (* x x)) ;; Number -> Number
> (square 3)
9
> (define (do-twice f x) ;; (X -> X) X -> X
(f (f x)))
> (do-twice square 3)
81
> (map (lambda (x) (do-twice square x))
'(1 2 3))
(1 16 81)
>
注意这个do-twice
还没有对应问题的p
:
这两次 map 的第一个参数需要:
(map do-twice (make-list 3 square) '(1 2 3))
映射一个列表需要一个参数的函数,所以必须产生两次
(define (do-twice x) (f (f x)))
作为其值:
> (define (do-twice-with f) ;; (X -> X) -> (X -> X)
(define (do-twice x) ;; X -> X
(f (f x)))
do-twice)
> ((do-twice-with square) 3)
81
> (map (do-twice-with square)
'(1 2 3))
(1 16 81)
>
所以do-twice-with
就是问题中的函数p
。
do-twice-with
需要函数参数 (X -> X),但 X 可以是任何类型,因此:
> (define (repeat s) ;; String -> String
(string-append s " " s))
> ((do-twice-with repeat) "buffalo")
"buffalo buffalo buffalo buffalo"
和 do-twice-with
本身具有类型 (X' -> X')(X' 代表 (X -> X)),所以可以
应用于自身:
> (((do-twice-with do-twice-with) square) 3)
43046721
> (((do-twice-with do-twice-with) repeat) "buffalo") [3]
"buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo"
((((do-twice-with do-twice-with) do-twice-with) square) 3)
留作
reader...
[1]“Naming is perhaps the most powerful abstracting notion we have”[盖伊·斯蒂尔]
[2] https://walker.cs.grinnell.edu/courses/151.sp04/readings/procedures-as-values.xhtml
[3] https://en.wikipedia.org/wiki/Buffalo_buffalo_Buffalo_buffalo_buffalo_buffalo_Buffalo_buffalo