'(bottom)
, because it is quoted, is considered a constant in Scheme. Everything that is quoted may share structure as well. eg.:
(define one '(bottom))
(define two '(bottom))
(eq? one two) ; ==> undefined
With undefined you can expect one scheme implementation to result in #f and another to result in #t. Even the same implementation might change depending on compiler settings.
To get your desired behavior you need to cons
in your procedure. Below is a version that uses list
to create unique lists for each call:
(define (make)
(list 'bottom))
;; test
(eq? (make) (make)) ; ==> #f
(eqv? (make) (make)) ; ==> #f
(equal? (make) (make)) ; ==> #t
If you want to use constants as a template you can use list-copy:
(define (make)
(list-copy '(bottom)))
Also note that constants are immutable. Strings in double quotes are also like quotes lists. In many of the Scheme reports violating the report may not signal an error, just start to behave strange. eg.
(define constant "horse")
(string-set! constant 0 #\H)
According to R5RS the above two lines are not Scheme since string-set!
is mutating a constant. In R6RS it should cause an exception with condition type &assertion to be raised. However, very few of the implementations do. You get the following effects:
(define (get-constant)
"horse")
(define constant (get-constant))
(string-set! (get-constant) 0 #\H)
constant ; ==> "Horse"
(get-constant) ; ==> "Horse"
EDIT
To comment on your addition:
(define (make)
(define b '(bottom))
(cons b b))
Here b
is still constant but the pair that holds the two are new at every execution just like in my version that used list
((list 'bottom)
is the same as (cons 'bottom '())
):
(eq? (make) (make)) ; ==> #f
(eq? (car (make)) (car (make))) ; ==> #t