方案:我的代码出了什么问题?

时间:2014-02-21 01:49:50

标签: if-statement lambda scheme

这个问题可能很容易,但我花了一些时间在上面,我无法弄清问题是什么。我是Scheme的新手;) 好的,这是我的代码:

(define foo
        (lambda (x)
              ((if(equal? (car x) 4) "A" "B")
               (if(equal? (car (cdr x)) 3) "A" "B")
               (if(equal? (car(cdr (cdr x))) 5) "A" "B")
               )
               ))


(foo '(4 3 5))

运行代码时出现以下错误:

>  application: not a procedure;  expected a procedure that can be
> applied to arguments   given: "A"   arguments...:    "A"    "A"

3 个答案:

答案 0 :(得分:4)

要修复错误,只需执行以下操作:

(define foo
  (lambda (x)
    (if (equal? (car x) 4) "A" "B")
    (if (equal? (car (cdr x)) 3) "A" "B")
    (if (equal? (car (cdr (cdr x))) 5) "A" "B")))

问题?在你的代码中,()表达式周围有一对额外且错误的if对,因此Scheme认为if正在返回一个函数(不是)。请记住,在Scheme中:(f)表示:执行f作为没有参数的函数。

现在我们发现了语法错误,让我们看看代码还有什么问题。对于初学者来说,如果你在一个过程中编写了一系列表达式,那么只返回 last 的值,所以前两个if被完全忽略了!阅读完评论后,我了解您要为输入"AAA"返回'(4 3 5),或为输入"ABA"返回'(4 6 5)。这里的诀窍是我们必须使用string-append将所有字​​符串粘在一起:

(define foo
  (lambda (x)
    (string-append
     (if (equal? (car x) 4) "A" "B")
     (if (equal? (cadr x) 3) "A" "B")
     (if (equal? (caddr x) 5) "A" "B"))))

现在它按预期工作:

(foo '(4 3 5))
=> "AAA"
(foo '(4 6 5))
=> "ABA"

答案 1 :(得分:3)

首先我要说:“欢迎来到计划!”不要感到沮丧,不管你做什么,继续 试图理解功能性编程的做事方式。 你的毅力会得到回报,你将成为一名更好的程序员 为了努力,即使你回到使用Java。

Scheme是开始学习函数式编程的好地方。

我希望以下内容可以帮助您了解如何开始 改变你的想法,所以这里:

这里有一些关于你为什么会遇到你看到的奇怪错误的原因。如果你 有:

(define foo
        (lambda (x)
              ((if(equal? (car x) 4) "A" "B")
               (if(equal? (car (cdr x)) 3) "A" "B")
               (if(equal? (car(cdr (cdr x))) 5) "A" "B")
               )
               ))

然后:

(foo '(4 3 5))

等于:

((if (equal? (car '(4 3 5)) 4) "A" "B"))
 (if (equal? (car (cdr '(4 3 5))) 3) "A" "B")
 (if (equal? (car (cdr (cdr '(4 3 5)))) 5) "A" "B"))

因为这是您在更换每个事件时获得的结果 在您编写的lambda表达式的主体中x (4 3 5)。{/ p>

下一点推理是一个捷径,但请注意:
    (car '(4 3 5)) = 4
  和
    (car (cdr '(4 3 5))) = (car '(3 5)) = 3
  和
  (car (cdr (cdr '(4 3 5)))) = (car (cdr '(3 5))) = (car '(5)) = 5

所以,当我们在上面的表达式中用equals替换equals时, 我们得到:

((if (equal? 4 4) "A" "B")
 (if (equal? 3 3) "A" "B")
 (if (equal? 5 5) "A" "B"))

,这与:

相同
("A" "A" "A")

这是一个特殊的Scheme表达式,而Scheme抱怨的原因是 因为您正在尝试调用名为"A"的函数并将其应用于 两个参数"A""A"

从上面的讨论来看,很明显你正在尝试 根据输入推导出一个新结构。所以,你需要的是 基于检查得出新结构的函数 现有结构,并组装一个新结构。这是什么 由函数返回。

Scheme是一种函数式语言,这意味着它非常 表达为本。在Scheme中,计算机变成了一种 机械表达 - 评估者。这是非常不同的 我们在面向对象语言中习惯了什么(例如Java, C#)因为这些语言都是关于小心控制的 多变的状态。在函数式语言中,它就是全部 计算表达式的值。 (顺便说一句,深入 而且美丽的方式,就是你可以做到的一切 在“可变状态编程”的世界中可以做到 “机械评价表达”的世界。有个 两者之间的深刻和基本等同,信不信由你。)

如果您尝试根据个人的测试创建新列表 列表中的元素(4 3 5),那么你需要编写表达式 两件事:从较小的东西构建列表,并检查 列表的各种元素(在本例中为4,3和5)。

(define foo
  (lambda (x)
    (cons (if (equal? (car x) 4) "A" "B")
      (cons (if (equal? (car (cdr x)) 3) "A" "B")
        (cons (if (equal? (car (cdr (cdr x))) 5) "A" "B") '() )))))

因此,(foo '(4 3 5))会生成("A" "A" "A"),这是一个字符串列表。 你最终希望将它们全部附加到一个字符串中, 对?所以,已经提供了一个名为fold-right的函数 一种方法来做到这一点。 fold-right函数可以使用字符串追加 实现这一目标的功能:

(fold-right string-append "" (foo '(4 3 5)))

应提供“AAA”的答案。

(fold-right string-append "" (foo '(4 4 4)))

给出了"ABB"

的答案

使用foldfold-right等功能更具功能性 编程方式来做这些事情。

根据具体情况,您可能需要使用这些折叠功能 而不是根据foo函数编写string-append函数 奥斯卡·洛佩兹上面做了。

就像我之前说的那样,你必须以非常不同的方式思考问题 当使用函数式编程语言时,远离思考 程序作为改变内部状态的操作序列 计算机的内存。你必须开始考虑 计算机作为强大的表达评估机器而已。

我希望这会有所帮助,并鼓励你继续学习计划。

答案 2 :(得分:2)

因为你的lambda的主体被括在括号中,所以第一个if被视为一个过程,当它试图将其他if的结果应用于它时,你得到你得到的错误。

如果您尝试返回这3个if的值列表,则应使用list函数。