How can i check if the first element of a list is equal to some character
I tried this code but i didn't work
(= (car lis) 'f)
any ideas?
In Lisp = is used for numeric comparison, while general-purpose comparison operators are different variants of equal (in CL there are four ones: eq for pointer comparison, eql for comparison of atoms, equal for comparison of structures and equalp, which is like equal with string collation - see: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node74.html).
In Common lisp you use eq for equality
(eql (car list) #\f)
Related
I was reading the documentation of an Emacs Lisp function called eql:
Return t if the two args are eq or are indistinguishable numbers.
What's the meaning of indistinguishable here? I'd been searching through the documentation but didn't find an explanation.
The eq predicate returns t only when comparing identical objects. But two values which compare equal are not guaranteed to be the same object; two literals with the same value are not even guaranteed to be the same object. So, (eq 1 1) may or may not evaluate to t. For number types eql compares values, so that (eql 1 1) will always evaluate to t. But, eql is a bit more subtle: (eql 1 1.0) will evaluate to 'nil since 1 and 1.0 are not indistinguishable, i.e., they do not share the same type. So, in the context of the quote, indistinguishable means that the operands have the same type and the same value.
I tried to create an example for cond and case and came up with a simple implementation of the fizz buzz problem (see Wikipedia for details).
My initial version is:
(defun is-fizz-buzz (n)
(cond ((and (zerop (mod n 3)) (zerop (mod n 5))) 'fizz-buzz)
((zerop (mod n 3)) 'fizz)
((zerop (mod n 5)) 'buzz)
(t n)))
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
('fizz "Fizz!")
('buzz "Buzz!")
('fizz-buzz "Fizz-Buzz!")
(otherwise n))))
Now, #RainerJoswig pointed out to me that my case is wrong. I was quite surprised, as it had worked as it should, but as he's way more experienced with Lisp than I am, he's most probably right (and in fact, he is).
I tried to read and understand http://clhs.lisp.se/Body/m_case_.htm, but now I'm left with more questions than answers. As I didn't want to discuss things in 140 characters and as it may be helpful for other Lisp beginners, I thought to publish my questions here.
Basically, the syntax of case is described as
case keyform {normal-clause}* [otherwise-clause] => result*
keyform is easy: It's a form that is evaluated to get the key that is being tested. For sure
(is-fizz-buzz n)
is a form and it returns a symbol, hence everything looks fine. Additionally, as I learned from Land of Lisp, case internally works with eq, and as eq is used to compare symbols, this should be fine as well.
Now, the normal-clause: This is defined as
(keys form*)
form* again is simple, it's just a number of forms, basically with an implicit progn. For keys, it tells me that this is a designator for a list of objects. Phew. Here my questions begin…
This document tells me that a designator is:
an object that denotes another object.
Hm. As case is working with eq, I would have expected that I need to give a symbol here. And why is keys a designator for a list of objects, not for a single one? May I have multiple symbols that I can compare against in a single branch? I guess the problem here comes down to not really understanding what is meant by a designator, but maybe someone can help me and push me into the right direction. How would you explain what a designator is in Lisp?
Then, I started playing around with the code, and I noticed that if I remove the ' character, things still work. The code
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
(fizz "Fizz!")
(buzz "Buzz!")
(fizz-buzz "Fizz-Buzz!")
(otherwise n))))
produces the very same result as the code above. Why is this? I would not even have expected this to be executable at all, as (fizz "Fizz!") to me looks like a function call of fizz, which doesn't exist. Why does this work?
And then, the final question is, when I run
(case 'quote ('foo 1) ('bar 2))
it returns 1 (which does not seem to be logical, I would have expected nil). If I change this to
(case 'quote ('foo 1) ('bar 2) (otherwise 3))
it still returns 1, not 3 as I now would have expected. From the documentation I don't get why my otherwise-clause obviously does not what it should do.
Any hints why these two cases behave like they do?
CASE use EQL not EQ. EQL is in most cases the default comparison. Thus case works for identity, numbers and characters.
The keyforms are NOT evaluated. Thus it makes no sense to quote objects. Quoting means stopping evaluation. But there is no evaluation -> no quote.
The keyform is either a single item, or a list of items
(case foo
(bar 'it-is-bar)
((1 2) 'one-or-two)
(1 'one))
((apple banana orange) 'either-apple-banana-or-orange)))
It also means that one the left side are constants, no variables. bar above is the symbol bar, not the variable bar.
Problem:
(case 'quote
('foo 'foo-or-quote))
because it really is
(case 'quote
((quote foo) 'foo-or-quote))
Okay, I was able to figure out some of the problems by myself, primarily by reading this question and the according answers. This explains to me why my otherwise-clause didn't work, and it also explains why
(case 'quote ('foo 1) ('bar 2))
is being evaluated the way it is. So I guess that my fizz-buzz function at least should be:
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
(fizz "Fizz!")
(buzz "Buzz!")
(fizz-buzz "Fizz-Buzz!")
(otherwise n))))
UPDATE
Okay, now after having re-read the aforementioned question and answers multiple times, I think I finally got what is meant by a list of objects, and hence my code should be:
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
((fizz) "Fizz!")
((buzz) "Buzz!")
((fizz-buzz) "Fizz-Buzz!")
(otherwise n))))
For keys, it tells me that this is a designator for a list of
objects. Phew. Here my questions begin…
This document
tells me that a designator is:
an object that denotes another object.
Hm. As case is working with eq, I would have expected that I need
to give a symbol here. And why is keys a designator for a list
of objects, not for a single one? May I have multiple symbols that I
can compare against in a single branch? I guess the problem here comes
down to not really understanding what is meant by a designator, but
maybe someone can help me and push me into the right direction. How
would you explain what a designator is in Lisp?
I originally posted this as a comment, but I think this might stand as a sufficient answer, if it's the core problem in the question, so I'm adding it as an answer.
The text you need is in the HyperSpec. 1.4.1.5 Designators notes
The specific nature of the object denoted by a "<> designator"
or a "designator for a <>" can be found in the Glossary entry
for "<> designator."
The glossary entry for list designator is what you need:
list designator n. a designator for a list of objects; that is,
an object that denotes a list and that is one of: a non-nil atom
(denoting a singleton list whose element is that non-nil atom) or a proper list (denoting itself).
Thus the symbol fizz (a non-nil atom) and the list (fizz) both designate the list (fizz), the list (quote fizz) (often abbreviated as 'fizz) designates itself, etc.
Once you've learned about list designators,they're a very handy concept to use in you own code. Just document that you accept a list designator, and then convert with (if (listp x) x (list x)), and you're in business. It's very helpful, and you'll find more uses for it than you expect. E.g., I used it just the other day in an answer to How to group any consecutive numbers or items of a given series.
I have a data set like this: '(("red" 3 5)("blue" 6 8)...)
Is it possible to use assoc when the keys are strings? None of the obvious attempts have worked for me in this simple test:
CL-USER> (defparameter ggg (list '("foot" 2) '(bar 5)))
GGG
CL-USER> ggg
(("foot" 2) (BAR 5))
CL-USER> (assoc 'bar ggg)
(BAR 5)
CL-USER> (assoc "foot" ggg)
NIL
CL-USER> (assoc '"foot" ggg)
NIL
CL-USER> (assoc 'foot ggg)
NIL
If you are sure that your list contains only strings, you can use the type-specific functions string= (case sensitive) or string-equal (case insensitive).
However, these functions also accept symbols, and mixtures of symbols and strings.
Thus (assoc "ABC" list :test #'string=) will find not only the key "ABC" but also any symbol whose name is "ABC", such as the symbol :abc or cl-use:abc or mypackage:abc.
The generic equal and equalp functions for comparing any two objects do not have this behavior. Like the aforementioned two, equal and equalp are, respectively, case sensitive and insensitive. However, they also compare other kinds of objects.
Unlike string= and string-equal, equal and equalp do not consider strings and symbols to be equivalent; that is, (equalp "FOO" 'FOO) -> nil. They also do not consider symbols having the same name to be equivalent: (equalp 'foo :foo) -> nil. When both arguments are symbols, equal and equalp apply the same test as the eq function.
So I would argue that an appropriate test for your associative list, since you have a mixture of string and symbolic keys, is one of the two functions equal and equalp.
These functions will also allow your list to have other kinds of keys like numbers. equalp will compare numbers by value, so that 1 and 1.0 are the same key, whereas equal is tighter. Both these functions recurse into lists. The lists (1 2) and (1 2) are equal even if they are not the same object (separately consed), whereas (1 2) and (1 2.0) are not equal, but are equalp (unless you have a very weird floating-point system). Also vector objects are not compared element-by-element by equal, but they are by equalp.
Even if you had strings only in the list, it's still better to use these two functions.
You are not going to get much, if any, performance benefit. string= still has to validate the types of the arguments to make sure they are supported types, and dispatch according to what combination of string and symbol the arguments are. equal dispatches according to numerous type possibilities, but this can be done efficiently.
Using overly type-specific functions, or inappropriately strict equality, as a matter of habit, is a poor practice in Lisp.
string= is used deliberately, however, not for saving machine cycles, but in situations when symbols must be compared as strings, or mixtures of symbols and strings. For instance, if you were implementing the loop macro, you might use string= for detecting the loop clause words, which according to the ANSI Common Lisp spec are treated as equivalent based on symbol name. Users can write (loop :for x below 42 ...) or (loop mypackage:for x below 42 ...). However (loop "FOR" ...) is not valid! So you could not rely only on string=; you'd have to validate that the clause word is a symbol.
(assoc "foot" ggg :test #'string-equal)
or
(assoc "foot" ggg :test #'string=)
Depending on whether you want the comparison to be case-sensitive.
? (assoc "foot" ggg :test #'equalp)
("foot" 2)
As others have pointed out already you can use different kinds of keys as described in the HyperSpec:
(setq alist '(("one" . 1)("two" . 2))) => (("one" . 1) ("two" . 2))
(assoc "one" alist) => NIL
(assoc "one" alist :test #'equalp) => ("one" . 1)
I have implemented this function. It is supposed to check the input that we have given to it, and if it is found in the list, a "True" will be shown on the screen. However, it just works for the numbers and if I give it a character I receive an error.
(defun element (x lst)
(dolist (item lst)
(if (= item x) (return t))))
How can I modify it so that it can also look for any characters given to it?
Thanks in advance.
There are several comparison operators. The general ones are eq, eql, equal and equalp. Look them up in the hyperspec.
For objects of specific types, there are often specialized comparators, e.g. string= and char=.
Finally, for list operations, there are functions like member, which can free you from writing loops by hand. They take an optional test parameter, through which you can pass the comparison function.
As you discovered, the = function only works with numbers.
If you try basing your function on find instead, you'll likely find that its default use of the eql function as its test provides the behavior you seek:
(defun element (needle haystack)
(not (null (find needle haystack))))
As alternates to find, you should also study its siblings member and position. In your case, since you only want to distinguish between the item having been found or not, you should choose the function that does the least work. My guess is that position loses here, and that member and find are equivalent; member returns the list from which it extracted the car, whereas find returns the car. In both functions, it's necessary to extract the car.
Easy, use #'eq instead of #'=, thus the 3rd line becomes: (if (eq item x) ...
Alternatively, you could use the built-in #'intersection to check if any of the given items are in the list, thus: (if (not (eq (intersection lst '(x)) nil)))
I had never really thought about whether a symbol could be a number in Lisp, so I played around with it today:
> '1
1
> (+ '1 '1)
2
> (+ '1 1)
2
> (define a '1)
> (+ a 1)
2
The above code is scheme, but it seems to be roughly the same in Common Lisp and Clojure as well. Is there any difference between 1 and quoted 1?
In Common Lisp, '1 is shorthand for (QUOTE 1). When evaluated, (QUOTE something) returns the something part, unevaluated. However, there is no difference between 1 evaluated and 1 unevaluated.
So there is a difference to the reader: '1 reads as (QUOTE 1) and 1 reads as 1. But there is no difference when evaluted.
Numbers are self-evaluating objects. That's why you don't have to worry about quoting them, as you do with, say, lists.
A symbol can be made from any string. If you want the symbol whose name is the single character 1, you can say:
(intern "1")
which prints |1|, suggesting an alternate way to enter it:
'|1|
Quoting prevents expressions from being evaluated until later. For example, the following is not a proper list:
(1 2 3)
This is because Lisp interprets 1 as a function, which it is not. So the list must be quoted:
'(1 2 3)
When you quote a very simple expression such as a number, Lisp effectively does not alter its behavior.
See Wikipedia: Lisp.
Well, they are in fact very different. '1 is however precisely the same as (quote 1). (car ''x) evaluates to the symbol 'quote'.
1 is an S-expression, it's the external representation of a datum, a number 1. To say that 1 is a 'number-object' or an S-expression to enter that object would both be acceptable. Often it is said that 1 is the external representation for the actual number object.
(quote 1) is another S-expression, it's an S-expression for a list whose first element is the symbol 'quote' and whose second element is the number 1. This is where it's already different, syntactic keywords, unlike functions, are not considered objects in the language and they do not evaluate to them.
However, both are external representations of objects (data) which evaluate to the same datum. The number whose external representation is 1, they are however most certainly not the same objects, the same, code, the same datum the same whatever, they just evaluate to the very same thing. Numbers evaluate to themselves. To say that they are the same is to say that:
(+ 1 (* 3 3))
And
(if "Strings are true" (* 5 (- 5 3)) "Strings are not true? This must be a bug!")
Are 'the same', they aren't, they are both different programs which just happen to terminate to the same value, a lisp form is also a program, a form is a datum which is also a program, remember.
Also, I was taught a handy trick once that shows that self-evaluating data are truly not symbols when entered:
(let ((num 4))
(symbol? num) ; ====> evaluates to #f
(symbol? 'num) ; ====> evaluates to #t
(symbol? '4) ; ====> evaluates to #f
(symbol? '#\c) ; #f again, et cetera
(symbol? (car ''x)) ; #t
(symbol? quote) ; error, in most implementations
)
Self evaluating data truly evaluate to themselves, they are not 'predefined symbols' of some sorts.
In Lisp, the apostrophe prevents symbols to be evaluated. Using an apostrophe before a number is not forbidden, it is not necessary as the numbers represent themselves. However, like any other list, it automatically gets transformed to an appropriate function call. The interpreter considers these numbers coincide with their value.
As has been pointed out, there is no difference, as numbers evaluate to themselves. You can confirm this by using eval:
(eval 1) ;=> 1
This is not limited to numbers, by the way. In fact, in Common Lisp, most things evaluate to themselves. It's just that it's very rare for something other than numbers, strings, symbols, and lists to be evaluated. For instance, the following works:
(eval (make-hash-table)) ;equivalent to just (make-hash-table)
In Lisp, quote prevent the following expression to be evaluated. ' is a shorthand for quote. As a result, '1 is same as (quote 1).
However, in Lisp, symbols can never be a number. I mean, 'abc is a symbol, but '123 is not (evaluated into) a symbol. I think this is wrong of the design of Lisp. Another case is not only #t or #f can be used as a Boolean expression.