I have a problem I don't understand how let
works in a cond
, with an if
I understand it but not with a cond
...
Here's my code with a let
:
(define add2
(lambda (l)
(cond ((null? l) l)
(let ((R (add2 (cdr l))))
((list? (car l)) (cons (add2 (car l)) R))
((number? (car l)) (cons (+ 2 (car l)) R))
(else (cons (car l) R))))))
When I try it on my list, it doesn't work.
Normally when I give my list:
(add2 '(2 b (10 a (56 3) 5) 4))
It should give me this :
(4 b (12 a (58 5) 7) 6))
It doesn't... It says: let: bad syntax
I think it might be this but I checked every parentheses and didn't see something missing...
But when I remove my let
and try without it, it works!
(define add2
(lambda (l)
(cond ((null? l) l)
((list? (car l)) (cons (add2 (car l)) (add2 (cdr l))))
((number? (car l)) (cons (+ 2 (car l)) (add2 (cdr l))))
(else (cons (car l) (add2 (cdr l)))))))
(add2 '(2 b (10 a (56 3) 5) 4))
into (4 b (12 a (58 5) 7) 6))
Therefore I don't understand why it doesn't work and I would appreciate any help!
You cannot make your own syntax - but you have to follow the cond
syntax
which says:
(cond ((condition-1 consequent-1)
(condition-2 consequent-2)
...
(else final-consequent)))
So there is no room for a let
which you can place into it.
You want to add 2 to only the numeric elements in a nested.
Such recursive functions dealing with nested lists (trees) traditionally have a *
at their end of their name.
And let this function be tail-recursive.
We would define it first without let
:
(define (add2* l (acc '()))
(cond ((null? l) (reverse acc))
((list? (car l)) (cons (add2* (car l)) (add2* (cdr l))))
((number? (car l)) (cons (+ 2 (car l)) (add2* (cdr l))))
(else (cons (car l) (add2* (cdr l))))))
Using let
, you want to save some typing. Do it by nesting two cond expressions:
(define (add2* l (acc '()))
(cond ((null? l) (reverse acc))
(else (let ((R (add2* (cdr l))))
(cond ((list? (car l)) (cons (add2* (car l)) R))
((number? (car l)) (cons (+ 2 (car l)) R))
(else (cons (car l) R)))))))
You could use if
for the outer cond
:
(define add2
(lambda (l)
(if (null? l)
l
(let ((R (add2 (cdr l))))
(cond ((list? (car l)) (cons (add2 (car l)) R))
((number? (car l)) (cons (+ 2 (car l)) R))
(else (cons (car l) R)))))))
Whish is the same like:
(define (add2 l)
(if (null? l)
l
(let ((R (add2 (cdr l))))
(cond ((list? (car l)) (cons (add2 (car l)) R))
((number? (car l)) (cons (+ 2 (car l)) R))
(else (cons (car l) R))))))
map-tree
This thing is actually a map-tree:
(define (map-tree func tree (acc '()))
(cond ((null? tree) (reverse acc))
((list? (car tree)) (cons (map-tree func (car tree)) (map-tree func (cdr tree))))
(else (cons (func (car tree)) (map-tree func (cdr tree))))))
And using this more general function, you define your add2*
by:
(define (add2 x)
(if (number? x)
(+ 2 x)
x))
(define (add2* tree)
(map-tree add2 tree))
And test it:
(add2* '(2 b (10 a (56 3) 5) 4))
;; => '(4 b (12 a (58 5) 7) 6)
Generalization by map-tree
makes it possible for you to define
other kind of such similar functions - since it decouples the
actual function applied to each element of the tree
from the traversal and application of the function on the tree.
e.g. you could define a add5*
easily:
(define (add5 x)
(if (number? x)
(+ 5 x)
x))
(define (add5* tree)
(map-tree add5 tree))
addN
and addN*
Since this also follows some pattern, you can let a function
return the corresponding add7
and add7*
:
(define (generate-addN n)
(lambda (x)
(if (number? x)
(+ n x)
x)))
(define (generate-addN* n)
(lambda (tree)
(map-tree (generate-addN n) tree)))
These functions generate you the functions for addN
and addN*
:
(define add7 (generate-addN 7))
(define add7* (generate-addN* 7))
addN*
functionOr you directly define and use a generalized addN*
function which takes n
and the tree
as its arguments:
(define (addN* n tree)
(map-tree (generate-addN n) tree))
or write-out the generate-addN
as a lambda expression:
(define (addN* n tree)
(map-tree (lambda (x)
(if (number? x)
(+ n x)
x))
tree))
And use it
(addN* 7 '(2 b (10 a (56 3) 5) 4))
;; => '(9 b (17 a (63 10) 12) 11)
You could also define a function which recursively adds at the and of a string element the suffix: "_s".
(define (addS* s tree)
(map-tree (lambda (x)
(if (string? x)
(~a x s)
x))
tree))
(addS* "_s" '(2 b (10 a ("abc" 3) "def") 4))
;; => '(2 b (10 a ("abc_s" 3) "def_s") 4)