Схема Факториал (факт* l) Вопрос

Я новичок в Scheme, поэтому простите за вопрос: у меня есть функция, которая вычисляет факториалы списка чисел, но она дает мне точку перед последним числом в результатах. Где я ошибаюсь?

код:

#lang scheme

 (define fact
    (lambda (n)
      (cond
        ((= n 0) 1)
        ((= n 1) 1)
        (else (* n (fact (- n 1)))))))

 (define fact*
   (lambda (l)
     (cond
       ((null? (cdr l)) (fact (car l)))
       (else
        (cons (fact (car l)) (fact* (cdr l)))))))

выход:

> (fact* '(3 6 7 2 4 5))
(6 720 5040 2 24 . 120)

person Isaac    schedule 05.09.2009    source источник


Ответы (3)


Что вы сделали, так это создали неправильный список. Попробуй это:

(define fact*
   (lambda (l)
     (cond
       ((null? (cdr l)) (list (fact (car l))))
       (else
        (cons (fact (car l)) (fact* (cdr l)))))))

Добавление list в четвертой строке должно заставить это работать так, как вы ожидаете. Лучше может быть следующее:

(define fact*
   (lambda (l)
     (cond
       (null? l) '())
       (else
        (cons (fact (car l)) (fact* (cdr l)))))))

Это позволит вашей функции fact* работать с пустым списком, а также уменьшит количество мест, где вы делаете вызов fact.

person Greg Hewgill    schedule 05.09.2009
comment
Спасибо! Есть ли способ сделать это с помощью примитивов схемы? Является ли список примитивом? - person Isaac; 06.09.2009
comment
Я отредактировал, чтобы добавить вторую реализацию после вашего комментария выше. Это отвечает на ваш вопрос? - person Greg Hewgill; 06.09.2009
comment
Ах, превосходно! Мои знания Маленького Интригана были на мгновение забыты. Спасибо! - person Isaac; 06.09.2009
comment
Я не знаю, знаете ли вы (или даже важно ли это), но есть примитив схемы, называемый map. Что он делает, так это применяет данную функцию к каждому члену данного списка. Таким образом, вы можете определить fact* как (define fact* (lambda (l) (map fact l))), и это будет работать точно так же. Конечно, вы должны знать, как это сделать, не используя сначала map! - person configurator; 17.09.2010
comment
О! Только что заметил именно то, что я сказал в качестве более позднего ответа! - person configurator; 17.09.2010

другое ответы указали причину, по которой вы получаете неправильный список в результате вашей fact* функции. Я хотел бы только отметить, что вы можете использовать функцию высшего порядка map:

(define fact*
  (lambda (l)
    (map fact l))

(fact* '(3 6 7 2 4 5))

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

person Jonas    schedule 06.09.2009

Используйте append вместо cons. cons используется для создания пар, поэтому у вас есть "." который используется для разделения элементов пары. Вот пример:

(define (factorial n)
  (if (<= n 1)
      1
      (* n (factorial (- n 1)))))

(define (factorial-list l)
  (if (null? l)
      '()
      (append (list (factorial (car l))) 
              (factorial-list (cdr l)))))
person João Silva    schedule 05.09.2009
comment
Не могли бы вы рассказать об этом более детально? Почему именно . вставляться в мой список, когда я добавляю атом в список? - person Isaac; 06.09.2009
comment
Пара – это объект, состоящий из двух атомов. Список — это последовательность пар со свойством, состоящим в том, что cdr каждой пары является другим списком, за исключением того, что конец списка обозначается пустым атомом списка. Таким образом, (cons 'a (cons 'b (cons 'c '()))) является правильным списком, но (cons 'a (cons 'b 'c)) называется неправильным списком, потому что cdr второго минуса не является списком. - person Greg Hewgill; 06.09.2009
comment
Потому что на последнем шаге вы создаете пару, состоящую из списка и атома, например, (cons '(20 21) 120) => ((20 21) . 120). Чтобы заставить его работать правильно, вам нужно преобразовать 120 в список. - person João Silva; 06.09.2009