I started learning common lisp a few days ago so keep in mind i'm a total noob, here's my code:
ELISP> (member nil '(2 3 nil))
(nil)
ELISP> (if (member nil '(2 3 nil))
'true
'false)
true
so my question is how is "if" returning true?
I checked the documentation for member:
If some element satisfies the test, the tail of list beginning with this element is returned; otherwise nil is returned.
In your case you have a three-element list (the elements being 2, 3, and nil).
nil is a member of this list, so (member nil '(2 3 nil)) returns a sublist starting at the found element:
(nil) ; a one-element list
This value is true because only nil itself is false; a single-element list containing nil is not false.
This behavior is correct. (NIL) is a list of the length 1, thus a non-empty list, thus treated as T when occuring in conditions.
Try this:
(if NIL 'true 'false) ;; false
(if () 'true 'false) ;; false
(if '() 'true 'false) ;; false
(if 'NIL 'true 'false) ;; flase
;; that are all four "identities" of NIL in CL.
;; they are even `eq` to each other, since every lisp has only one
;; physical address for NIL in their implementation.
;; I imagine it like kind of the root `/` for unix systems ...
;; but (NIL) or ('NIL) or ('()) or (()) are a lists with 1 element in them. thus evaluated to `T`.
(if '(NIL) 'true 'false) ;; true
(if '(()) 'true 'false) ;; true
(if '('()) 'true 'false) ;; true
(if '('NIL) 'true 'false) ;; true
This is like in set theory of mathematics: An empty set has no elements, thus it is empty. But if you put into it the empty set, it is not empty any more, but contains the element 'empty set' as its element.
It can be quite philosophical. Kind of this set contains the idea/representation of an empty set as its element ... and this is not nothing but something.
Related
I am trying to use generic functions' ability to specify behaviour based on the first argument of a list.
In other words, I want the list (atypelist 1 2 3) and the list (btypelist 1 2 3) to have their individual behaviour when passed to foo. So far, this is what I came up with:
(deftype atypelist (lst)
`(eq (car ,lst) 'atypelist))
(deftype btypelist (lst)
`(eq (car ,lst) 'btypelist))
(defmethod foo ((lst atypelist))
(format nil "success atypelist: ~S" lst))
(defmethod foo ((lst btypelist))
(format nil "success btypelist: ~S" lst))
However, when I call (typep (list 'atypelist 1 2 3) 'atypelist) I get the following error:
error while parsing arguments to DEFTYPE ATYPELIST:
too few elements in
()
to satisfy lambda list
(LST):
exactly 1 expected, but got 0
I am guessing the error is in my definition of atypelist.
Questions:
Is there a better way to get the functionality I am looking for?
If yes - what is the way?
If not - how to properly define a type on a list/cons that has a particular symbol in the car?
Before I start: what you want to do can't work, and is confused in two ways.
Firstly deftype defines a type in terms of other type specifiers: the body of a deftype form must expand into a type specifier, not an expression, as yours does. And deftype's arguments are not the thing you want to check the type for, they are parts of the type specification.
In this case you want to specify that the thing is a cons, and that its car is eql to something. Fortunately there are specializing type specifiers for both of these things, and you end up with something like this:
(deftype cons-with-specified-car (x)
`(cons (eql ,x) t))
And now
> (typep '(1) '(cons-with-specified-car 1))
t
> (typep '(a) '(cons-with-specified-car a))
t
> (typep '() '(cons-with-specified-car a))
nil
And if you want:
(deftype cons-with-a ()
'(cons-with-specified-car a))
and now
> (typep '(a) 'cons-with-a)
t
Secondly none of this will work because this it not how CLOS works. CLOS dispatches on classes not types, and you have merely defined a type, not a class: your method definitions simply cannot work, since classes cannot be parametrized in this way like types can.
Some ways you might achieve what you want.
If what you want to do is to dispatch on the first element of a list, then the obvious approach, if you want to use CLOS, is to use a two-level approach where you first dispatch on the class of the thing (cons is a class), and then use eql specializers to pick out the things you want.
(defgeneric select (it)
(:method ((it cons))
(select* (car it) it))
(:method (it)
nil))
(defgeneric select* (key it)
(:method (key it)
(format t "~&unknown key ~S in ~S~%" key it)))
(defmethod select* ((key (eql 'a)) it)
(format t "~&~S begins with a~%" it))
However in a case like this, unless you very much want the extensibility that CLOS gets you (which is a good reason to use CLOS here), I'd just use typecase. You could do this using the type defined above:
(defun select (it)
(typecase it
((cons-with-specified-car a)
'(cons a))
(cons
'cons)
(t
nil)))
or, probably simpler, just use what the deftype expands into:
(defun select (it)
(typecase it
((cons (eql a) t)
'(cons a))
(cons
'cons)
(t
nil)))
Finally probably what anyone doing this would actually write (again, assuming you do not want the extensibility CLOS gets you) is:
(defun select (it)
(typecase it
(cons
(case (car it)
...))
(t
...)))
Here is a possible solution, using the type specifier satisfies:
CL-USER> (defun is-atypelist (list)
(eq (car list) 'atypelist))
IS-ATYPELIST
CL-USER> (defun is-btypelist (list)
(eq (car list) 'btypelist))
IS-BTYPELIST
CL-USER> (deftype atypelist ()
`(satisfies is-atypelist))
ATYPELIST
CL-USER> (deftype btypelist ()
`(satisfies is-btypelist))
BTYPELIST
CL-USER> (typep (list 'atypelist 1 2 3) 'atypelist)
T
CL-USER> (typep (list 'atypelist 1 2 3) 'btypelist)
NIL
Note that this does not define a class, but a type, if this is what you need.
Is there a better way to get the functionality I am looking for?
1. Wrap your lists in container types
(defclass lst () ((items :initarg :items :reader items)))
(defclass alst (lst) ())
(defclass blst (lst) ())
It may be a little bit more cumbersome to work with but this is pretty much straightforward and not too suprising.
2. Douple-dispatch
(defgeneric foo (val))
(defgeneric foo/tag (tag val))
For example:
(defmethod foo ((c cons))
(destructuring-bind (tag . list) c
(foo/tag tag list)))
3. Define a custom method combination
It should be possible to hack the meta-object protocol dispatch mechanism to dispatch on the first item of a list. I wouldn't recommend it however.
4. Use a different dispatch mechanism
Use a completely different dispatching mechanism outside of CLOS, like pprint-dispatch does. For example you may want to use trivia or optima pattern-matching libraries, or cl-algebraic-data-type. This may be more useful if you are dealing with trees of symbols.
I have written a function that accepts a list of characters and checks how many times the instances of the vowels are in the list.
The following error appears when I try the function:
; contains?: undefined;
; cannot reference undefined identifier
; [,bt for context]
The function :
(define (count list)
(if (and(null? (cdr list))
(contains?(vowels)(car list)))
(+ counter 1)
(if(and (contains?(vowels)(car list))
(not(contains?(vowels)(cadr list))))
(+ counter 1)
(count(cdr list)))))
contains? is not part of either R5R, R6RS, or R7RS and thus is not part of any current Scheme standard.
In the current standard we have something that works in its place: member, memv, and memq:
(member '(b) '((a) (b) (c))) ; ==> ((b) (c))
(member '(q) '((a) (b) (c))) ; ==> #f
member uses equal? to check for same object. The others use eqv? (numbers) and eq? (identity).
I just started writing this function and I was wondering if there was a way, that if just the &key argument was entered, the &optional list could be ignored.
(defun test (&optional arg (i 0) &key (size s))
...)
I would like to be able to run
(test arg)
or
(test arg i)
but also
(test :size)
Now this is a better mock up but I don't know where to put :size in params list
(defun test (&optional arg (i 0))
(cond ((eq arg nil) (return-from test (test-1)))
((listp arg)
(return-from test (test-2 arg)))
((pointerp arg) (mem-aref (test-3 arg) :int i))
(:size (size-test arg))
(t nil)))
so i can run (test) and get:
<output of (test-1)>
I can run (test '(1 2 3)) and get:
<output of (test-2 arg)>
I can run (test <pointer> 0)
and output is:
<output of (mem-aref (test-3 arg) :int i)>
I can run (test :size) and get:
<output of (test-size arg)>
Mixing optional and keyword arguments
Mixing optional and keyword arguments is still something that's not all that easy to do. If a function accepts an optional argument, then you won't be able to use the keyword arguments unless the optional argument is also provided. Otherwise, the first keyword would be interpreted as the optional argument, and so on. See, for instance, this Stack Overflow question: How can I have optional arguments AND keyword arguments to the same function?. As the answer to that question points out, it's usually a bug-prone practice to mix optional and keyword arguments. Common Lisp does it with read-from-string, and it often leads people into trouble.
What you're proposing, though, isn't just having a function that uses both keyword and optional arguments, but, from the sounds of it, is actually doing some checking of the types of arguments, and taking one behavior in one case, and another in another. In this case, if i is supposed to be a number, then you could check the first argument, and if it's a number, then treat it as the optional argument, and the rest as keyword arguments, and if it's not a number, then treat the whole list as keyword arguments. You can do that with an &rest argument that you destructure in different ways:
(defun frob (&rest args)
(flet ((frob-driver (i size)
(list i size)))
(if (or (endp args) (numberp (first args)))
;; no args, or the first argument is a number (and thus
;; not a keyword argument)...
(destructuring-bind (&optional (i 'default-i) &key (size 'default-size)) args
(frob-driver i size))
;; otherwise, there are some non-numeric arguments at
;; beginning, so it must be the keyword list, and that the
;; "optional" wasn't provided.
(destructuring-bind (&key (size 'default-size) &aux (i 'default-i)) args
(frob-driver i size)))))
(frob 10 :size 50) ; give i and size
;=> (10 50)
(frob :size 60) ; give size, but not i
;=> (default-i 60)
(frob 40) ; give i, but not size
;=> (40 default-size)
(frob) ; give neither
;=> (default-i default-size)
Keyword arguments without keyword symbols
In the comments, you mentioned that you'd like to be able to use non-keyword symbols as keywords in argument lists. This is easy enough. In the HyperSpec, ยง3.4.1 Ordinary Lambda Lists describes the syntax for keyword arguments:
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
This means that you can define functions like this:
(defun frob (&key foo ((bar-keyword bar-variable) 'default-baz))
(list foo bar-variable))
(frob :foo 1 'bar-keyword 2)
;=> (1 2)
(frob :foo 3)
;=> (3 default-baz)
(frob 'bar-keyword 2)
;=> (nil 2)
You have to use a &rest argument list and process it in the function.
Mixing optional and keyword arguments should be avoided. It is BAD style to use optional and keyword arguments. This has been the source for countless errors with the few functions which use that (like READ-FROM-STRING).
In short, "no". There's no way of making that happen. As a general rule, try to stay away from mixing &rest, &optional and &key arguments, since their interactions are subtle and will more frequently trip you up than actually be useful.
Furthermore, if :size is a keyword argument, hen (test :size) is missing one argument (the value to bind size to). Your best bet is probably to look a arg to see if it is :size or something else.
Posting as answer because I solved the main issue here is the resultant code I came up with, The cond statements are what matter. The &args usage created another issue and that post is being discussed here. The ((symbolp (cadr args)) (%vector-float-size (first args))) line is what I came up with from Joshua Taylors kindly written and extremely informative answer.
(defun vector-float (&rest args)
(cond ((eq (first args) nil) (return-from vector-float (%vector-float)))
((listp (first args))
(c-arr-to-vector-float (first args)))
((symbolp (cadr args)) (%vector-float-size (first args)))
((pointerp (first args)) (mem-aref (%vector-float-to-c-array (first args)) :float (second args)))
(t nil)))
Here's the thing: I don't "get" setf-expanders and would like to learn how they work.
I need to learn how they work because I've got a problem which seems like a typical example for why you should learn setf-expanders, the problem is as follows:
(defparameter some-array (make-array 10))
(defun arr-index (index-string)
(aref some-array (parse-integer index-string))
(setf (arr-index "2") 7) ;; Error: undefined function (setf arr-index)
How do I write a proper setf-expander for ARR-INDEX?
(defun (setf arr-index) (new-value index-string)
(setf (aref some-array (parse-integer index-string))
new-value))
In Common Lisp a function name can not only be a symbol, but also a list of two symbols with SETF as the first symbol. See above. DEFUN thus can define SETF functions. The name of the function is (setf arr-index).
A setf function can be used in a place form: CLHS: Other compound forms as places.
The new value is the first argument then.
CL-USER 15 > some-array
#(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
CL-USER 16 > (setf (arr-index "2") 7)
7
CL-USER 17 > some-array
#(NIL NIL 7 NIL NIL NIL NIL NIL NIL NIL)
Rainer's answer is spot on. Before ANSI Common Lisp, it was necessary to use defsetf to define an expander for simple places that could be set with a simple function call. setf functions like (setf arr-index) came into the language with CLOS and simplify a lot of things. In particular, setf functions can be generic.
Can somebody explain why the function eval behaves like this?
(eval (list 'cons t nil)) returns (T)
(eval (list 'cons 'a nil)) causes an error
(eval (list 'cons ''a nil)) returns (A)
Thanks a lot.
First:
(CONS T NIL)
T is a constant and returns T when evaluated. NIL is also a constant and evaluates to NIL. (CONS T NIL) then returns (T . NIL), which is shorter written as (T).
Second:
(CONS A NIL)
A is a variable. It is possibly undefined. Evaluating it will lead to an error when A is undefined.
Third:
Now you should think about the third form...
One more thing that you may want to note is that third form is embedding the symbol A in the list. Usually this is the form which is mostly taught in Lisp books for learning by experimenting on REPL. However in actual programs / functions, you may be using initially more of putting value or list represented by A in the list and not the symbol A.
e.g.
(setf a 2)
(eval (list 'cons a nil)) => (2) [A is evaluated before list is evaluated; (eval '(cons 2 nil))]
(eval (list 'cons 'a nil)) => (2) [A is evaluated when (eval '(cons a nil)) is evaluated]
(eval (list 'cons ''a nil)) => (A) [A does not get evaluated as call is (eval '(cons 'a nil)); 'a is symbol A]
If you don't do (setf a 2) in the beginning, 1st and 2nd both forms will give error. This is because when a is evaluated, it is not bounded (i.e. crudely, it does not have any value associated with it)