Петля в схеме - PullRequest
       8

Петля в схеме

1 голос
/ 06 октября 2011

Я хочу определить функцию for-n в схеме, которая принимает 3 параметра, start и stop - целые числа, а fn - функция. Я хочу, чтобы функция for-n вызывала fn с start, затем start + 1 ... и, наконец, с остановкой.
Также я хочу сохранить все значения, которые 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))) 
       )
     )

Ответы [ 3 ]

5 голосов
/ 06 октября 2011

Вы редко хотите использовать list для рекурсивного построения списков. Списки построены с cons и null (он же '()); list - это просто удобная функция для создания списка фиксированного размера .

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

В предложении cond должно быть только два случая: либо вы закончили, либо нет.

Примеры помощи. В частности, выберите примеры, связанные с вашими рекурсивными вызовами. Вы включили пример (for-n 3 5 fn). А как насчет (for-n 4 5 fn); что должно вернуться? Теперь, учитывая start = 3, stop = 5 и (for-n 4 5 fn) = все, что, по вашему мнению, должно произойти, как вы можете построить ответ, который, по вашему мнению, должен дать (for-n 3 5 fn)?

Я настоятельно рекомендую Как разрабатывать программы (текст доступен онлайн) как введение в функциональное программирование.

2 голосов
/ 06 октября 2011

Вот решение, которое использует 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 самостоятельно.


Надеемся, что из приведенных выше двух примеров решений у вас достаточно идей для создания собственного решения с нуля. : -)

1 голос
/ 27 июня 2012

Я тоже новичок в схеме, но вот что я придумал для общего цикла 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)

... и вы можете понять, почему парадигма плохо переводится, хотя вы можете заменить эти лямбды именованными функциями, чтобы сделать их более читабельными.

-

Самостоятельное редактирование 2015:

Это ужасный и неправильный способ заниматься функциональным программированием. Подход на основе «карты» или «сгиба» гораздо лучше.

...