I'm debugging this code on DrRacket:
#lang racket
(define last-element-on-list
(lambda l
(cond ((null? l) '())
((null? (cdr l)) (car l))
(else (last-element-on-list (cdr l)))
)
)
)
(define lst '(
(n 25 f +)
(s 25 m +)
(ll 20 no -)))
(list-ref lst 0)
(last-element-on-list (list-ref lst 0))
The code (list-ref lst 0)
returns '(n 25 f +)
, but when I get into the procedure last-element-on-list
the parameter l
has the value ((n 25 f +))
.
Why l
is a list of list in procedure last-element-on-list
?
There's a difference between the (lambda (x) ...)
form and the (lambda x ...)
form.
Observe the difference between these two examples:
;; Example 1.
(define f
(lambda (x)
(if (list? x)
(display "x is a list!")
(display "x is not a list"))))
(f 1) ; Displays "x is not a list".
;; Example 2.
(define g
(lambda x
(if (list? x)
(display "x is a list!")
(display "x is not a list"))))
(g 1) ; Displays "x is a list!".
The (lambda x ...)
form allows the lambda to take any number of arguments, with all the arguments put into a list bound to x
in the lambda's body. i.e. x
is the list of arguments.
That's why when you give g
a list (e.g. (g '(1 2 3))
), x
will be '((1 2 3))
(a list of lists).
To fix your code:
(define last-element-on-list
(lambda (l) ; <- ATTENTION.
(cond ((null? l) '()) ; FIXME: raise error instead.
((null? (cdr l)) (car l))
(else (last-element-on-list (cdr l))))))
You can read more about lambda
in The Racket Guide. In particular, look at section 4.4.1 (Declaring a Rest Argument).
I think it will be better to raise an error
when calling your procedure on an empty list –
(define last-element-of-list
(lambda (l)
(cond ((null? l)
(error 'last-element-of-list "cannot get last element of empty list"))
((null? (cdr l))
(car l))
(else
(last-element-of-list (cdr l))))))
(last-element-of-list '(1)) ;; 1
(last-element-of-list '(1 2)) ;; 2
(last-element-of-list '(1 2 3)) ;; 3
(last-element-of-list '(1 2 3 4)) ;; 4
(last-element-of-list '()) ;; error: cannot get last element of empty list