Схема Факториал

Я знаю, что вы можете написать простую факториальную функцию следующим образом:

(define fact
  (lambda (n)
    (if (= n 0) 1
        (* n (fact (- n 1)))))

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

(define listFact
 (lambda (n)
   (cond
     ((null? n) 1)
     ((symbol? n) n)
     ((number? n) (if (= n 0) 1 (* n (listFact (- n 1)))))
     ((cons? n) (cons (listFact(car n)) (listFact(cdr n)))))))

Я не слишком хорош в Scheme, но мне нужно знать основы. Каждый ввод работает правильно, кроме списка.

> (listFact '())

1

(список фактов)

'a

(список фактов 4)

24

(список фактов '(1 2 3))

минусы: второй аргумент должен быть списком, но получил 6 и 1

То, что я хочу, чтобы последний сделал, это return:

(список 1 2 6)

Я понятия не имею, почему это не сработает. Если бы кто-нибудь мог помочь мне разобраться в этом, не меняя всей структуры кода (т. е. не используя apply/map или несколько функций), я был бы очень признателен. Я бы предположил, что единственная перепутанная строка - это строка с минусами.

Спасибо.


person user2869231    schedule 17.11.2013    source источник
comment
какова ваша реализация схемы?   -  person Will Ness    schedule 18.11.2013


Ответы (2)


Просто замените

(cond
     ((null? n) 1)

с участием

(cond
     ((null? n) n)

для правильной работы cons из-за завершающего nil: список (1 2 3) на самом деле (1 . (2 . (3 . ()))), так что в конечном итоге вы доберетесь до часового nil в конце списка. Чтобы восстановить список обратно, вам нужно, чтобы он оставался пустым списком, или nil, чтобы (cons 6 nil) создавал новый список (6); (cons 6 1) создаст пару (6 . 1), но, видимо, по какой-то причине это не работает в вашей реализации.

Если вы хотите, чтобы ваши () элементы в списке были преобразованы в 1s, вам придется различать два случая.

person Will Ness    schedule 17.11.2013
comment
см. обновленный ответ. еще есть вопросы? спрашивай! :) - person Will Ness; 18.11.2013
comment
весь* пост. Но что делает так. Благодаря тонну! Стало довольно неприятно... - person user2869231; 18.11.2013

Вот ваша проблема:

((null? n) 1)

Итак, когда вы пытаетесь получить значение пустого списка, вы получаете целое число, которое не является списком. Когда вы вызываете свою функцию со списком, вы получаете что-то вроде этого:

(cons 1 (cons 2 (cons 6 1)))

Это не работает. Чтобы исправить вашу функцию, вы должны попробовать это:

((null? n) n)
person Simgate    schedule 17.11.2013
comment
Да, я не знал, что вам нужен пустой список в конце, учитывая, что он никогда не отображается - person user2869231; 18.11.2013