guicho271828 / trivia

Pattern Matcher Compatible with Optima
Other
332 stars 22 forks source link

Surprising `list*` behavior #64

Closed sjl closed 7 years ago

sjl commented 7 years ago

I was trying to match the contents of a list to do something with it, like this:

(match foo
  ; if foo is a list, transform its contents
  ((list* contents) (mapcar #'whatever contents))
  ; otherwise...
)

But it appears that list* with a single argument will just match anything at all:

(match 'x ((list* foo) foo))
X

The docs in the wiki for list and list* say:

Both patterns checks if the object is of type list

so this seems like a bug in either the matcher or the docs...

guicho271828 commented 7 years ago

Well, this is a tricky thing and I discussed it with somebody else once. The doc should be fixed. The reasoning behind this decision is as follows:

Pattern matching & destructuring is a dual operation of object construction. If a vector is created with a constructor form (vector 1 2 3), the pattern which matches the object should also resemble the form, e.g. (vector a b c).

Since destructor & constructor are dual, it is better if the behavior of the pattern reflects the original function. And the list* on clhs says:

http://clhs.lisp.se/Body/f_list_.htm

If list* receives only one object, that object is returned, regardless of whether or not it is a list. 

I will fix both the wiki documentation and docstring.