I know you can write a simple factorial function by doing this:
(define fact
(lambda (n)
(if (= n 0) 1
(* n (fact (- n 1)))))
However, that will only work if you send in a number; it will error if you send in a list or symbol. So what I want to do is make it work for everything and, if a list, do the factorial of each individual element in the list. Here is what I have:
(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)))))))
I'm not too great at Scheme, but I need to be able to know the basics. Every input works properly except for a list.
> (listFact '())
1
(listFact 'a)
'a
(listFact 4)
24
(listFact '(1 2 3))
cons: second argument must be a list, but received 6 and 1
What I want that last one to do is return:
(list 1 2 6)
I have no idea why it won't work. If anyone could help me figure this one out without changing the entire structure of the code (i.e. don't use apply/map or multiple functions), it would be much appreciated. I'd assume the only line messed up is the one with cons.
Thanks.
Just replace
(cond
((null? n) 1)
with
(cond
((null? n) n)
for cons
to work properly, because of the trailing nil
: a list (1 2 3)
is actually (1 . (2 . (3 . ())))
, so you eventually get to the sentinel nil
in the end of the list. To reconstruct the list back, you need it to remain an empty list, or nil
, so that (cons 6 nil)
creates a new list (6)
; (cons 6 1)
would create a pair (6 . 1)
but apparently it doesn't work in your implementation for some reason.
If you want your ()
elements in a list to be transformed into 1
s, you will have to distinguish the two cases.