List Scheme-映射函数,用于将函数应用于嵌套列表中的元素

List Scheme-映射函数,用于将函数应用于嵌套列表中的元素,list,nested,scheme,map-function,List,Nested,Scheme,Map Function,我试图在scheme中编写一个映射函数,将函数应用于嵌套列表中的每个值 例如,(地图编号?'(3(2 A)2 Z)应该返回(#t(#t#f)#t#f) 以下是我目前掌握的情况: (define (map fun lst) (if (null? lst) '() (if (list? (car lst)) (cons (map fun (car lst)) (map fun (cdr lst))) (cons (f

我试图在scheme中编写一个映射函数,将函数应用于嵌套列表中的每个值

例如,
(地图编号?'(3(2 A)2 Z)
应该返回
(#t(#t#f)#t#f)

以下是我目前掌握的情况:

(define (map fun lst)
    (if (null? lst) '()
        (if (list? (car lst)) 
            (cons (map fun (car lst)) (map fun (cdr lst)))
                 (cons (fun (car lst)) (map fun (cdr lst))))))
如果嵌套列表位于列表的前面,则它可以工作。例如
(地图编号?'((3 A)2 Z))
正确返回
((#t#f)#t#f)

当嵌套列表出现在原始列表中的另一个元素之后时,就会出现问题。 例如
(地图编号?)
错误地返回
(#t#f#f)
[结果应该是
(#t#f(#t#f))
]


如何更改我的算法来更正此问题?

您的代码是正确的,只是过于冗长。提示:您只需要担心两种情况:
lst
是否为
对?
仅此而已。换句话说,您的代码假定输入始终是一个列表,但可以简化为accep当它是一对时,做特殊的递归操作

至于你看到的问题——我猜你在用球拍,因此你遇到了一个奇怪的情况。如果不是这样,你可以停止阅读这里

问题是,在Racket中,函数本身将在绑定到
map
之前编译,因此
map
调用不是真正的递归调用,而是对内置
map
的调用绑定到结果函数,但递归调用已被编译。如果您输入相同的定义两次,您将看到它再次开始工作。解决此问题的方法是不在REPL上工作,而是始终在以一些
#lang
开头的文件中编写定义。这是我的解决方案,它非常重要便宜的是,它使用(我知道,使用设计模式的Scheme程序?:-O)重用内置的
map

通过使用命名的
let
,可以进一步“简化”:

(define (deep-map f l)
  (let deep ((x l))
    (cond ((null? x) x)
          ((pair? x) (map deep x))
          (else (f x)))))
(这两段代码并不完全相同,但对于这个问题,如果给定一个列表作为输入,这两段代码的工作原理是相同的。)


使用
null?
pair?
检查(均为O(1))以避免使用
list?
(即O(n)).

我正在使用Chicken。谢谢你的提示,我会尝试修复它。我不知道Chicken会这样做,但如果是同一个问题,我也不会感到惊讶……对不起,但你能澄清scheme中的配对是什么吗?我还是个新手。@user247679:scheme中的列表由零个或多个conse(配对)组成。例如,
(列表1)
(cons1'())
(列表由一对组成),
(列表123)
(cons1(cons2'()))
(列表由三对组成)。在方案中,您可以使用
对?
“非常便宜”来测试对这是不正确的……例如,我希望许多实现为直接调用自身的更简单版本生成更好的代码,因为
map
通常足够重,不能内联。因此,虽然在某些情况下它可能更便宜,但声称它总是更便宜是错误的。@Eli:“便宜”在这种情况下,不是指性能,而是指我用作弊者的方法解决了这个问题。-)CKY:就重用代码而言,它甚至不便宜——您节省了
(cons(map…)(map…)
,这是一个很小的优势,但从教学角度来看,结果更清楚。。。(在这个过程中,你会得到一些更一般的东西,尽管这当然与问题无关。)@Eli:我在IRC上回答。(我认为这是让每个人都在同一页上的最直接的方法。):-)注意,
配对?
并不意味着列表-对于
(a(b.c)d)
with“(b.c)这将失败不是一个合适的列表”。你不能避免在
list?
上支付O(n),因为这是
map
所需要的
(define (deep-map f l)
  (let deep ((x l))
    (cond ((null? x) x)
          ((pair? x) (map deep x))
          (else (f x)))))