【问题标题】:For-loop in scheme方案中的for循环
【发布时间】:2011-10-06 03:17:05
【问题描述】:

我想在scheme中定义一个for-n函数,它有3个参数,start和stop是整数,fn是一个函数。我希望 for-n 函数先调用 fn,然后调用 start+1 ...,最后调用 stop。
我还想将 fn 返回的所有值存储在一个列表中。请帮助我开始。我是一位经验丰富的程序员,但刚刚开始学习计划。

这是我得到的函数定义:

[编辑]

    (define (fn a)
        a
     )

    (define (for-n start stop fn)
      (cond
        ((> start stop) (quote ()))
        ((= start stop) (list(fn start)))
        (else (list(for-n (+ start 1) stop fn))) 
       )
     )


    > (for-n 3 5 fn)
    (list (list (list 5)))

当 (for-n 3 5 fn) 被调用时,我希望它返回 (3 4 5),我做错了什么?

[编辑-2]
感谢大家的帮助。我的功能现在可以工作了。这是我得到的:

    (define (for-n start stop fn)
      (cond
        ((> start stop) (quote ()))
        ((= start stop) (list(fn start)))
        (else (cons (fn start) (for-n (+ start 1) stop fn))) 
       )
     )

【问题讨论】:

  • 尝试删除(= start stop) 大小写。你的测试还通过了吗?
  • 很高兴听到您成功了。您仍然应该删除 (= start stop) 行;它使您的功能比需要的丑陋约 5 倍。 (如果这是作业,并且我是标记,我会因为有那条线而扣掉你的分数,因为它表明你没有得到递归™。)
  • 这不是java。不要像 java 那样格式化你的代码。
  • 除了 Marcin 的评论:网上有一些不错的 Scheme/Common-Lisp 风格指南。参照。例如。 mumble.net/~campbell/scheme/style.txtgoogle-styleguide.googlecode.com/svn/trunk/lispguide.xml.

标签: functional-programming scheme


【解决方案1】:

您很少想使用list 递归地构造列表。列表使用consnull(又名'())构建; list 只是一个方便的函数来创建一个固定大小的列表。

(list 1 2 3) = (cons 1 (cons 2 (cons 3 null)))

cond 子句中应该只有两种情况:要么完成,要么没有。

示例帮助。特别是,选择与您的递归调用相关的示例。您包含了示例(for-n 3 5 fn)(for-n 4 5 fn) 呢?它应该返回什么?现在,给定start = 3stop = 5(for-n 4 5 fn) = 无论你认为它应该产生什么,你如何构建你认为(for-n 3 5 fn) 应该产生的答案?

我强烈推荐How to Design Programs(在线提供的文本)作为函数式编程的介绍。

【讨论】:

    【解决方案2】:

    这是一个使用SRFI 1的解决方案:

    (define (for-n start stop fn)
      (map fn (iota (- stop start) start)))
    

    如果这是用于家庭作业,那么由您来定义iota,或许还可以定义map。 :-D


    使用不同策略的另一种解决方案(也使用 SRFI 1):

    (define (for-n start stop fn)
      (unfold-right (lambda (x) (< x start))
                    fn sub1 (sub1 stop)))
    

    sub1 == (lambda (x) (- x 1))。当然,在这种情况下,您必须自己实现unfold-right


    希望从以上两个示例解决方案中,您有足够的想法来构建自己的从头开始的解决方案。 :-)

    【讨论】:

    • 我想从基本的内置函数构建函数。不想使用任何外部库。
    • @jamesio:我同意。自己编写这些函数。 :-) (对于大多数 SO 用户来说,这个问题太像家庭作业了,不想给你写一个直接的代码解决方案;这样的答案往往会被否决。)
    • @jamesio:提示:map(这是一个内置的 Scheme,顺便说一句)和iota真的易于编写。但是您应该自己编写它们;发现如何去做是一种非常有启发性的学习体验。
    • 请在编辑和评论中查看我的代码。非常感谢您的帮助。
    • @jamesio: 1.你知道cons怎么用吗?如果您使用cons,您将很快发现默认分支中的错误。 2. 您应该删除cond 的第二个分支。让(= start stop) case 掉到默认值,让第一个 case 在下一次迭代时触发。
    【解决方案3】:

    我也是 scheme 新手,但这是我想出的通用 for 循环,似乎对我有用:

    (define (for i end-cond end-fn fn var)
        (if (end-cond i)
          var
          (for (end-fn i) end-cond end-fn fn (fn var))
        )
    )
    

    所以规范:

    for (i=0; i > 5; i++) {
      print i;
    }
    return i;
    

    可以写成:

    (define i 0) (for i (lambda (x) (> 5 x)) (lambda (y) (+ 1 y)) display i)
    

    ...您可以看到为什么范式不能很好地翻译,尽管您可以用命名函数替换那些 lambda 以使其更具可读性。

    --

    2015 年自行编辑:

    这很糟糕,而且是错误的函数式编程方式。基于“地图”或“折叠”的方法要好得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-27
      • 2020-11-14
      相关资源
      最近更新 更多