0
;;; <- can one use cons to do  ((a . b) . (c . d))?


(define x (cons a b)); nil -- should it be error
(define x (cons 'a 'b)); (a . b)

(define y (cons 'c 'd)); (c . d)

(define z00 (cons x y)) ; (((a . b) c . d) <- cannot use cons to do  ((a . b) . (c . d))?
(define z01 (cons x 'y)) ; ((a . b) . y) 
(define z10 (cons 'x y)) ; (x c . d) 
(define z11 (cons 'x 'y)); (x . y))

(define z (list x y z00 z01 z10 z11)) 
        ; ((a . b) (c . d) ((a . b) c . d) ((a . b) . y) (x c . d) (x . y))

;;; and if not any other means or dot pair cannot have 2nd element like this?

ad absurdum
  • 19,498
  • 5
  • 37
  • 60
KWC
  • 121
  • 8

3 Answers3

2

Yes, you can. And the language has a wonderful predicate called equal? which will allow you to test this:

> (equal? (cons (cons 'a 'b) (cons 'c 'd))
          '((a . b) . (c . d)))
#t
> (equal? '((a . b) . (c . d))
          '((a . b) c . d))
#t

And you can even write a little display function which will confirm this:


(define (display-thing thing)
  (if (cons? thing)
      (begin
        (display "(")
        (display-thing (car thing))
        (display " . ")
        (display-thing (cdr thing))
        (display ")"))
      (display thing)))

And now

> (display-thing (cons (cons 'a 'b) (cons 'c 'd)))
((a . b) . (c . d))
> (display-thing '((a . b) . (c . d)))
((a . b) . (c . d))
> (display-thing '((a . b) c . d))
((a . b) . (c . d))

What this should all be telling you is that ((a . b) . (c . d)) and ((a . b) c . d) are merely different ways of writing a structurally identical object.

1

Pairs visualize differently based on their content. If the cdr of a pair contains the empty list it is a proper list an dthe dot and extra empty list is not shown:

(cons 'a '())
'(a . ())
; ==> (a)

A pair that has pair as it's cdr can be visualized as a list element without the . and extra parenthesis:

(cons 'b '(a))
'(b . (a))
; ==> (b a)
(cons 'b '(a . c))
'(b . (a . c))
; ==> (b a . c)

These are just made so that we can have (1 2 3) displayed instead of (1 . (2 . (3 . ()))) which is how it really is made.

If you were to not have a pair or a empty list in the cdr then it falls back to showing the dotted pair:

(cons 'a 'b)
'(a . b)
; ==> (a . b)

In your example '((a . b) . (c . d)) because there is a pair after a dot (eg. the cdr if the pair the visualization will remove the dot and one pair of parentheses and show it like ((a . b) c . d). This is the only acceptable correct way for a REPL to display this even though both your example and the display will be read in as the same structure.

There is a similar issue with numbers. In code you can use 10, #xa and #o12 to get the number 10 and the value will have no idea what format is was read in as and only show the base 10 in the REPL.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • Great. This is one of the issues I encounter when learning Lisp a decade ago. I picked it up again and sort of understanding it by asking and finally answer my own question. I think fundamentally lisp has 3 things: atom, dotted pair and dotted pair with .nil as the end called list. And you have presented it much better than mine. And help very much to clarify and confirm what my understanding is ... it is in the print (and internal they can be made.) You know what that (cons 'b '(a)) really get me. – KWC Apr 19 '21 at 12:12
-1

;;; ```
;;; <- can one use cons to do  ((a . b) . (c . d))?


(define x (cons a b)); nil -- should it be error
(define x (cons 'a 'b)); (a . b)

(define y (cons 'c 'd)); (c . d)

(define z00 (cons x y)) ; (((a . b) c . d) <- cannot use cons to do  ((a . b) . (c . d))?
(define z01 (cons x 'y)) ; ((a . b) . y) 
(define z10 (cons 'x y)) ; (x c . d) 
(define z11 (cons 'x 'y)); (x . y))
(define z22 (cons '(f g) '(h i)))
(define z2c (cons (cons 'f 'g) (cons 'h 'i)))

(define fgc (cons ('f 'g))); should it be error (nil) 
; actually not as 'f is an exoression (quote f) and f for some reason is nil it becomes nil from quote of nil abd so is the second one.  now (nil . nil) is (nil)

(define z (list x y z00 z01 z10 z11 z22 z2c fgc)) 
        ; ((a . b) (c . d) ((a . b) c . d) ((a . b) . y) (x c . d) (x . y))



;;; ```

;;; and if not any other means or dot pair cannot have 2nd element like this?

;;; possibly not


;;; as the cons join 2 pairs of dotted pairs and can generate one dotted pair
;;; ((a . b) . (c . d)) but the printing rule is reflected the list bias 

;;; this new dotted pair will have the first element as (( a . b) ... print as
;;;   ((a . b) ...
;;; the 2nd element it will consider whether it is an atom or another dotted pair 
;;;      (other possibilities like loop back or something else ... not sure)
;;; as (c . d) is a dotted pair the "printing" continues as a list would
;;; 
;;;      ((a . b) c ... 

;;; however the second element of (c . d) is not a dotted pair but an atom and print as 

;;;               . d) will it becomes

;;; hence even though you form the binary tree head the dot pair would display as a partial list

;;; you can have a list of dotted pairs like z 
;;; but not dotted pair of dotted pairs 

KWC
  • 121
  • 8