Reputation: 1342
I'm working through a Scheme tutorial which asks for an exercise using sorting, "Sort by length of lists in descending order." I wrote this solution on my own:
(define (ls-len-sort ls)
(sort ls (lambda (x y) (> (length x) (length y)))))
but when I tested it, I didn't get the result I expected:
> (ls-len-sort '('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2)))
'('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2))
I expected '('(5 5 5 5 5) '(4 4 4 4) '(3 3 3) '(2 2) '(1))
.
Sorting works, comparing list lengths works.
> (sort '(1 3 5 4 2) >)
'(5 4 3 2 1)
> (sort '(1 3 5 4 2) (lambda (x y) (< (abs (sin x)) (abs (sin y)))))
'(3 4 1 2 5)
> (> (length '(2 2)) (length '(3 3 3)))
#f
> (> (length '(4 4 4 4)) (length '(3 3 3)))
#t
but sorting a list whose elements are lists does not:
> (sort '('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2)) (lambda (x y) (> (length x) (length y))))
'('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2))
I looked up the correct answer in the tutorial, and it's token by token the same as what I wrote:
(define (sort-length ls)
(sort ls (lambda (x y) (> (length x) (length y)))))
so I'm guessing perhaps this is a difference between Racket v8.4 [cs] vs the version of MIT-Scheme (R5RS) the tutorial is written for?
Upvotes: 0
Views: 151
Reputation: 7568
You got this result because of bad use of quote
. Quote isn't just different name for function list
, it's form which doesn't evaluate its argument and returns it. Compare these two examples:
> (list 1 2 3 (+ 2 2) 5)
(1 2 3 4 5)
> '(1 2 3 (+ 2 2) 5)
(1 2 3 (+ 2 2) 5)
Sometimes result will be the same:
> (list 1 2 3 4 5)
(1 2 3 4 5)
> '(1 2 3 4 5)
(1 2 3 4 5)
When a list is quoted, all objects inside are also quoted, so you don't have to quote them twice. As you can see, results are entirely different:
> '('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2))
('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2))
> '((1) (3 3 3) (5 5 5 5 5) (4 4 4 4) (2 2))
((1) (3 3 3) (5 5 5 5 5) (4 4 4 4) (2 2))
Which variant do you want? You can compare these two with list created with list
:
> (list (list 1) (list 3 3 3) (list 5 5 5 5 5) (list 4 4 4 4) (list 2 2))
((1) (3 3 3) (5 5 5 5 5) (4 4 4 4) (2 2))
When you'll use correct variant, sort will work:
(define (ls-len-sort ls)
(sort ls < #:key length))
> (ls-len-sort '((1) (3 3 3) (5 5 5 5 5) (4 4 4 4) (2 2)))
((1) (2 2) (3 3 3) (4 4 4 4) (5 5 5 5 5))
Upvotes: 1