scheme(或 lisp)的诀窍是在将每组括号构建成更复杂的形式时理解每组括号之间的每一点。
让我们从条件句开始。 if 接受 3 个参数。它计算第一个参数,如果为真,则返回第二个,如果第一个参数为假,则返回第三个。
(if #t "some value" "some other value") ; => "some value"
(if #f "some value" "some other value") ; => "some other value"
(if (<= 1 0) "done" "go again") ; => "go again"
cond 也可以——你可以在这里阅读条件句的球拍介绍:http://docs.racket-lang.org/guide/syntax-overview.html#%28part._.Conditionals_with_if__and__or__and_cond%29
您可以用两种不同的方式定义函数。您正在使用匿名函数方法,这很好,但在这种情况下您不需要 lambda,因此更简单的语法是:
(define (function-name arguments) result)
例如:
(define (previous-number n)
(- n 1))
(previous-number 3) ; => 2
使用像你一样的 lambda 实现同样的事情,使用不同的语法(现在不要担心任何其他差异):
(define previous-number* (lambda (n) (- n 1)))
(previous-number* 3) ; => 2
顺便说一句 - '*' 只是该名称中的另一个字符,没什么特别的(请参阅http://docs.racket-lang.org/guide/syntax-overview.html#%28part._.Identifiers%29)。一种 '!'在函数名的末尾通常意味着该函数有副作用,但是 n!在这种情况下,这是您的函数的好名称。
让我们回到你原来的问题,把函数定义和条件放在一起。我们将使用 wiki 定义中的“递归关系”,因为它提供了一个很好的递归函数:如果 n 小于 1,则阶乘为 1。否则,阶乘是 n 乘以小于 n 的阶乘。在代码中,它看起来像:
(define (n! n)
(if (<= n 1) ; If n is less than 1,
1 ; then the factorial is 1
(* n (n! (- n 1))))) ; Otherwise, the factorial is n times the factorial of one less than n.
最后一个子句比我想要的要密集一些,所以让我们在 n = 2 的情况下继续工作:
(定义 n 2)
(* n (n! (- n 1)))
; =>
(* 2 (n! (- 2 1)))
(* 2 (n!1))
(* 2 1)
2
另外,如果您使用的是 Racket,很容易确认它是否按我们预期的那样工作:
(check-expect (n! 0) 1)
(check-expect (n! 1) 1)
(check-expect (n! 20) 2432902008176640000)