【问题标题】:How to pass on a lambda that produces a list to a procedure that expects a list?如何将生成列表的 lambda 传递给需要列表的过程?
【发布时间】:2022-12-09 16:45:13
【问题描述】:
我有以下程序:
(define (remove-first f)
(rest f))
(define (sty f)
(remove-first (lambda (x) (map f x))))
(define (square x)
(* x x))
(define new-func (sty square))
(new-func (list 1 2 3))
在这里,我想创建一个函数sty,它接收一个函数,将其应用于列表,然后删除列表的第一个元素。但是,当我运行它时,出现以下错误:
rest: expects a non-empty list; given: (lambda (a1) ...)
我理解错误,但不确定如何将我的 lambda(将生成一个列表)传递给remove-first
【问题讨论】:
标签:
functional-programming
scheme
racket
【解决方案1】:
我假设 remove-first、square、new-func 和 (new-func (list 1 2 3)) 的定义是作业的一部分,您无法更改它们。
在这种情况下,函数sty 无法返回列表。它必须返回closure。闭包是一个 lambda 函数,它“记住”来自创建它的环境中的变量。因此,您的函数将“记住”f 的值,您只需使用列表调用它即可获得预期结果。
这是lambda的默认行为,因此您只需更改remove-first和lambda的顺序即可:
(define (remove-first f)
(rest f))
(define (sty f)
(lambda (x) (remove-first (map f x))))
(define (square x)
(* x x))
(define new-func (sty square))
(new-func (list 1 2 3))
【解决方案2】:
你在 sty 中尝试做的实际上是 compose 两个函数(链接它们) - remove-first 和你的 lambda:
(define (remove-first f)
(rest f))
(define (sty f)
(compose remove-first (lambda (x) (map f x)))))
(define (square x)
(* x x))
(define new-func (sty square))
(new-func (list 1 2 3)) ;;=> '(4 9)
【解决方案3】:
new-func 应该是一个函数。
所以,(sty square) 必须是一个函数。
这意味着 sty 必须具有以下形式
(define (sty f)
(lambda (x) ...))
添加“映射f到x并删除第一个元素”:
(define (sty f)
(lambda (x) (rest (map f x))))
请注意,除非 f 有任何副作用,否则将其应用于列表的头部并丢弃结果是浪费工作,并且首先丢弃头部更有意义:
(define (sty f)
(lambda (x) (map f (rest x))))