Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scheme 一个球拍内有多个程序?_Scheme_Conditional_Racket - Fatal编程技术网

Scheme 一个球拍内有多个程序?

Scheme 一个球拍内有多个程序?,scheme,conditional,racket,Scheme,Conditional,Racket,我正在研究racket中的Project Euler问题3,不知道如何将多个过程用作条件句中的一个过程。通常在使用过程语言时,我会使用“while”循环并进行一些变量更新,因此我使用“set!”在下面的代码中,如果有更好的方法——正如我从相关问题/答案中读到的,在racket中变异变量不是一个好的做法,那么请提供一个替代方案,如果条件为真,请提供几个过程。通过将多条指令封装在一个输出语句中来将其作为一个输出语句似乎不起作用,但我确信有某种方法可以实现这一点 我考虑过将其分解成小函数,然后生成两个

我正在研究racket中的Project Euler问题3,不知道如何将多个过程用作条件句中的一个过程。通常在使用过程语言时,我会使用“while”循环并进行一些变量更新,因此我使用“set!”在下面的代码中,如果有更好的方法——正如我从相关问题/答案中读到的,在racket中变异变量不是一个好的做法,那么请提供一个替代方案,如果条件为真,请提供几个过程。通过将多条指令封装在一个输出语句中来将其作为一个输出语句似乎不起作用,但我确信有某种方法可以实现这一点

我考虑过将其分解成小函数,然后生成两个较大的函数,一个用于“then”区域,一个用于“else”区域,但这似乎不是正确的解决方案,或者至少不是传统的方法

如果有帮助的话,我还包含了这个特定代码的错误消息

; 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”区域,如果没有用粗体标出,那么它将被****示例:example包围。希望它不会破坏可读性


谢谢。

要将多条指令组合到一条语句中,可以使用begin

请注意,最后一条指令的返回值将是begin….的结果

但是,运行带有这些更改的代码将产生'。 这是因为append pL list DEVISOR将返回一个新列表。因此,此指令是无用的,因为您无法捕获结果

我想你想做一套!pL追加pL列表除数。现在它将不再返回空列表

您还希望pL变量的定义如下所示。现在,结果的第一个元素不再是由第一个附加引起的空列表


我测试了修改后的代码,它应该可以工作:

@HyperZ的答案是正确的。但是,广泛使用set!这并不是通常认为的惯用方案,所以我想展示一种不同的方法。我将使用相同的算法,只是在惯用的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,则返回空列表。 否则,请寻找合适的除数,从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))))))

谢谢,现在我可以试着把递归代码转换成线性迭代了我唯一不完全理解的是list null和'.@Byte list null返回一个元素的列表的确切区别。list返回零元素的列表。list null返回与list list相同的内容。已设置!在拍子中不是惯用的,因为它的性能比尾部递归/线性迭代差?对于for循环,同样的问题。顺便说一下,谢谢你的回答!展示了另一种思考问题的方式。这不是惯用的方式,因为Racket和Scheme的人倾向于以函数式风格编写代码,尽可能少的变异。当然,有些数据结构,如向量,可能需要变异才能有效,但只有在有限的情况下,如随机访问,向量才有用。大多数情况下,您可以使用标准列表,对于这些列表,您可以是100%不可变/功能性的。这也适用于for解决方案?我的意思是,它不是功能范式和惯用的敲打。for实际上是一种理解,与C-style for循环无关,也不涉及任何变异。所以它完全是功能性的,而且是惯用的。
(define (factors dividend)
  (if (= dividend 1)
      '()
      (for/first ((divisor (in-naturals 2))
                  #:when (zero? (remainder dividend divisor)))
        (cons divisor (factors (quotient dividend divisor))))))