球拍条件内的多个程序?
Multiple procedures within a racket conditional?
我正在研究 Project Euler problem #3 in racket,我不确定如何在条件语句中将多个过程作为一个过程使用。通常在使用过程语言时,我会使用 'while' 循环并进行一些变量更新(因此我在以下代码中使用 'set!' 的原因(如果有更好的方法 - 正如我所读来自相关的 questions/answers,在 racket 中改变变量不是好的做法,那么请提供一个替代方案)并且如果条件为真则有多个过程。将多个指令作为一个输出语句(通过将其包含在'()'中似乎行不通,但我相信有一些方法可以做到这一点。
我考虑过将其分解成小函数,然后制作 2 个较大的函数(1 个用于 'then' 区域,1 个用于“其他区域”),但它似乎不是正确的解决方案(或者至少不是传统的方法)。
如果有帮助,我还包含了此特定代码的错误消息。
; Project Euler # 3
; What is the largest prime factor of the number 600851475143?
(define pL (list null))
(define divisor 2)
(define (pF dividend)
(if (= dividend 1)
pL
(if (= (remainder dividend divisor) 0)
**(**(append pL (list divisor))
(set! dividend (/ dividend divisor))
(set! divisor 2)
(pF dividend)**)**
**(**(set! divisor (+ divisor 1))
(pF dividend)**)**)))
(pF 33)
application: not a procedure;
expected a procedure that can be applied to arguments
given: '(() 11)
arguments.:
我已经把'then'和'else'区域加粗了(如果没有加粗,那么它会被****包围(例如:示例)。希望它不会破坏可读性。
谢谢。
要将多个指令组合在一个语句中,您可以使用 begin
。
(if (= (remainder dividend divisor) 0)
(begin (append pL (list divisor)) // Then
(set! dividend (/ dividend divisor))
(set! divisor 2)
(pF dividend))
(begin (set! divisor (+ divisor 1)) // Else
(pF dividend)))
请注意,最后一条指令的return值将是(begin ...)
的结果。
但是 运行 具有这些更改的代码将生成 '(())
。
这是因为 (append pL (list divisor))
将 return 一个 new 列表。因此这条指令是无用的,因为你没有捕捉到结果。
我想你想做 (set! pL (append pL (list divisor)))
。现在它不再是 return 空列表。
您还希望 pL
变量像这样定义 (define pL '())
。现在结果的第一个元素将不再是一个空列表(这是由第一次追加引起的)。
我测试了修改后的代码,它应该可以工作:)
@HyperZ 的回答是正确的。但是,set!
的广泛使用通常不被认为是惯用的 Scheme,因此我想展示一种不同的方式来处理它。我将使用相同的算法,只是在惯用的 Racket 中重新表述:
(define (factors dividend)
(if (= dividend 1)
'()
(let loop ((divisor 2))
(define-values (q r) (quotient/remainder dividend divisor))
(if (zero? r)
(cons divisor (factors q))
(loop (add1 divisor))))))
这应该很容易阅读:
- 如果被除数为 1,return 一个空列表。
- 否则,寻找一个合适的除数,从2开始:
- 被除数除以除数得到商和余数。
- 如果余数为零,结果就是除数加上商的因数。
- 否则,除数加1,重试
您实际上可以通过使用 for/first
理解而不是手动内部循环来使代码更具可读性:
(define (factors dividend)
(if (= dividend 1)
'()
(for/first ((divisor (in-naturals 2))
#:when (zero? (remainder dividend divisor)))
(cons divisor (factors (quotient dividend divisor))))))
我正在研究 Project Euler problem #3 in racket,我不确定如何在条件语句中将多个过程作为一个过程使用。通常在使用过程语言时,我会使用 'while' 循环并进行一些变量更新(因此我在以下代码中使用 'set!' 的原因(如果有更好的方法 - 正如我所读来自相关的 questions/answers,在 racket 中改变变量不是好的做法,那么请提供一个替代方案)并且如果条件为真则有多个过程。将多个指令作为一个输出语句(通过将其包含在'()'中似乎行不通,但我相信有一些方法可以做到这一点。
我考虑过将其分解成小函数,然后制作 2 个较大的函数(1 个用于 'then' 区域,1 个用于“其他区域”),但它似乎不是正确的解决方案(或者至少不是传统的方法)。
如果有帮助,我还包含了此特定代码的错误消息。
; Project Euler # 3
; What is the largest prime factor of the number 600851475143?
(define pL (list null))
(define divisor 2)
(define (pF dividend)
(if (= dividend 1)
pL
(if (= (remainder dividend divisor) 0)
**(**(append pL (list divisor))
(set! dividend (/ dividend divisor))
(set! divisor 2)
(pF dividend)**)**
**(**(set! divisor (+ divisor 1))
(pF dividend)**)**)))
(pF 33)
application: not a procedure;
expected a procedure that can be applied to arguments
given: '(() 11)
arguments.:
我已经把'then'和'else'区域加粗了(如果没有加粗,那么它会被****包围(例如:示例)。希望它不会破坏可读性。
谢谢。
要将多个指令组合在一个语句中,您可以使用 begin
。
(if (= (remainder dividend divisor) 0)
(begin (append pL (list divisor)) // Then
(set! dividend (/ dividend divisor))
(set! divisor 2)
(pF dividend))
(begin (set! divisor (+ divisor 1)) // Else
(pF dividend)))
请注意,最后一条指令的return值将是(begin ...)
的结果。
但是 运行 具有这些更改的代码将生成 '(())
。
这是因为 (append pL (list divisor))
将 return 一个 new 列表。因此这条指令是无用的,因为你没有捕捉到结果。
我想你想做 (set! pL (append pL (list divisor)))
。现在它不再是 return 空列表。
您还希望 pL
变量像这样定义 (define pL '())
。现在结果的第一个元素将不再是一个空列表(这是由第一次追加引起的)。
我测试了修改后的代码,它应该可以工作:)
@HyperZ 的回答是正确的。但是,set!
的广泛使用通常不被认为是惯用的 Scheme,因此我想展示一种不同的方式来处理它。我将使用相同的算法,只是在惯用的 Racket 中重新表述:
(define (factors dividend)
(if (= dividend 1)
'()
(let loop ((divisor 2))
(define-values (q r) (quotient/remainder dividend divisor))
(if (zero? r)
(cons divisor (factors q))
(loop (add1 divisor))))))
这应该很容易阅读:
- 如果被除数为 1,return 一个空列表。
- 否则,寻找一个合适的除数,从2开始:
- 被除数除以除数得到商和余数。
- 如果余数为零,结果就是除数加上商的因数。
- 否则,除数加1,重试
您实际上可以通过使用 for/first
理解而不是手动内部循环来使代码更具可读性:
(define (factors dividend)
(if (= dividend 1)
'()
(for/first ((divisor (in-naturals 2))
#:when (zero? (remainder dividend divisor)))
(cons divisor (factors (quotient dividend divisor))))))