zepto icon indicating copy to clipboard operation
zepto copied to clipboard

RFC: make empty list the identity of `cons`

Open hellerve opened this issue 8 years ago • 7 comments

cons is the zepto function to append something to the start of a list. It is quite useful for working with lists, even though the behavior of zepto's implementation of this function differs from the standard Scheme implementation.

A few motivating examples of how cons currently works:

(cons 1 [2]) ; [1 2]
(cons [3] [4]) ; [[3] 4]
(cons 1 (cons 2)) ; pair[1, 2]
(cons 1) ; pair[1]

Ass you see, its normal type is a dotted list, but it will also work with regular lists. Well, that's nice already, isn't it? But what if we call it without an argument?

(cons) ; explosion!

It will fail! But wait, we just said it has a type associated with it! Wouldn't it make sense to return an empty dotted list then? Well... yes. The only problem with that is that dotted lists cannot be empty. They require at least one element to exist.

Hum... But, what if we do the next best thing then and just return an empty list? That violates the whole "its type is a dotted list" invariant, but it is really muddy to begin with and dotted lists should only be worked with if you really have to (i.e. in really fancy macros).

So, what this RFC proposes is the following behavior:

(cons) ; []

I hope that makes sense! Cheers

hellerve avatar Dec 12 '16 16:12 hellerve

An experimental implementation of this feature is provided in the new-cons branch.

hellerve avatar Dec 12 '16 16:12 hellerve

With this change, what would be the result of (cons 1 (cons)) for example?

arthurrauter avatar Dec 12 '16 16:12 arthurrauter

[1], because it would add 1 to an empty list.

hellerve avatar Dec 12 '16 16:12 hellerve

What is [] again?

4www avatar Dec 13 '16 09:12 4www

The empty list, similar to Javascript, Python, or Ruby.

hellerve avatar Dec 13 '16 09:12 hellerve

Ok, but does that mean there are multiple ways of writting a list and an empty list?

(1 2 3 )
()
(nil)
[1 2 3 ]
[]
[nil]
(list 1 2 3)
(list)
(list nil)

I guess my question could be why returning [] and not ()? So we now for sure this is an empty list and not parenthesis meant for something else?

4www avatar Dec 13 '16 09:12 4www

Okay, let me rephrase: [] is a quoted list[1]. Quoting is, as per usual in Lisp, the facility to separate code and data. To illustrate your example:

(1 2 3) ; will try to evaluate 1 as a function with the arguments 2 and 3
() ; cannot be evaluated
(nil) ; evaluates to nil, because nil is both a function and a value
[1 2 3] ; is a list of 1, 2, and 3
[] ; is an empty list
[nil] ; is a list of one element, nil
(list 1 2 3) ; list is a function to construct a list, so this list will be constructed at runtime
(list) ; will return []
(list nil) ; will return [nil]
; this form is a little like new Array(1,2,3) in Javascript vs. [1, 2, 3] in Javascript. One is a constant,
; the other is allocated at runtime.

I hope this helps.

So what we are really returning is a list datastructure, not code, thus [], which is equivalent to a quoted list '() or (quote ()). Reader macros FTW.

[1] Actually it is a reader macro for (quote ()).

hellerve avatar Dec 13 '16 09:12 hellerve