From: W. James on 5 Jan 2010 04:29 Thomas A. Russ wrote: > Cecil Westerhof <Cecil(a)decebal.nl> writes: > > > I can not find much about case, but I found the following: > > case is a conditional that chooses one of its clauses to > > execute by comparing a value to various constants, which are > > typically keyword symbols, integers, or characters (but may be > > any objects). > > Well, the key item you need to consider for any of these comparison > constructs is to make sure you understand what predicate is used to do > the comparison for the selection of the items. From the HyperSpec: > > "If the test-key is the SAME as any key for that clause, the forms > in that clause are evaluated as an implicit progn, and the values > it returns are returned as the value of the case, ccase, or ecase > form." > > So, now we need to know what "SAME" means in this context. The > HyperSpec definition that is relevant is the second one: > > SAME: "... 2. (of objects if no predicate is implied by context) > indistinguishable by eql." > > So that means that EQL is the test used for matching. And constant > strings with the same characters may or may not be EQL, and this can > differ depending on whether the function or file is compiled or not. > > > So I would expect that I can use strings in a case statement. > > > > I tried the following: > > (defun do-command (this-command) > > (case this-command > > ("d" (display-recipe-names)) > > (otherwise (format t "#~a# is an unknown command~%" > > this-command)))) > > > > But when feeding this "d" I get: > > #d# is an unknown command > > > > So properly I need to do something special to use strings. How > > would I do this? > > Yes. You either need to make sure that they are the same object > (which can be a bit tricky for strings but is doable), or you need to > INTERN the strings and use symbols (which is the easy way to make it > work) or you need to use one of the 3rd party utility libraries that > implements a different CASE-like statement that can handle strings. > > Or, as an exercise in macro writing, you could write your own > STRING-CASE macro. That might be a nice learning exercise in its own > right. > > One method of making it work would be: > > (progn ;; Needed to have a single READER context > (defconstant D-COMMAND #1="d") > (defun do-command (this-command) > (case this-command > (#1# (format t "Found command ~A" this-command)) > (otherwise (format t "#~a# is an unknown command~%" > this-command))))) > > But to use this, you need to specify the stored constant D-COMMAND: > > (do-command d-command) > Found command d > NIL > > (do-command "d") > #d# is an unknown command > NIL > > So you can't use this to execute commands that you get, for example, > by reading in terminal input. To do that you would need to either > intern the string or use a different case structure. > > There is actually a cleverer solution that uses a hash table and > registered functions that doesn't even use case at all. It is nicely > extensible and very general. And it is dead simple to implement in > Lisp. Bigloo Scheme: (match-case "d" ("d" (print "displaying recipes")) (else (print "unknown command"))) --
From: refun on 5 Jan 2010 09:31 In article <87wrzxse0p.fsf(a)Traian.DecebalComp>, Cecil(a)decebal.nl says... > > I can not find much about case, but I found the following: > case is a conditional that chooses one of its clauses to execute by > comparing a value to various constants, which are typically keyword > symbols, integers, or characters (but may be any objects). > > So I would expect that I can use strings in a case statement. > > I tried the following: > (defun do-command (this-command) > (case this-command > ("d" (display-recipe-names)) > (otherwise (format t "#~a# is an unknown command~%" this-command)))) > > But when feeding this "d" I get: > #d# is an unknown command > > So properly I need to do something special to use strings. How would I > do this? A few solutions to your problem as I see it: 1. Use symbols instead of strings. 2. Make your own case-like macro which uses a hashtable. It would be an interesting exercise 3. Use a more general construct like SWITCH from the arnesi library. http://common-lisp.net/project/bese/docs/arnesi/html/api/macro_ 005FIT.BESE.ARNESI_003A_003ASWITCH.html You would use it like this: (defun do-command (this-command) (switch (this-command :test #'equal) ("d" (display-recipe-names)) (t (format t "#~a# is an unknown command~%" this-command)))) ;; The switch would expand to: (let ((#:g1110 this-command) (#:g1111 #'equal)) (cond ((or (funcall #:g1111 '"d" #:g1110)) (display-recipe-names)) (t (format t "#~a# is an unknown command~%" this-command)))) This shows that each test will be evaluated sequentially, which means it's less efficient than the hashtable solution.
From: Pillsy on 5 Jan 2010 09:50 On Jan 4, 10:27 pm, Kenneth Tilton <kentil...(a)gmail.com> wrote: [...] > One of the best ideas in Lisp is that of the symbol. Use them. Not strings. > (do-command 'd) > ...and... > (case cmd (d (display-recipe-names))) > If you get a string, quick, intern it. > kt > * But it /was/ funny to see the contorted monstrosities up with which > they came. kt Like using FIND-SYMBOL instead of INTERN. Heathens! Cheers, Pillsy
From: joswig on 5 Jan 2010 10:02 On 5 Jan., 15:31, refun <re...(a)nospam.gmx.com> wrote: > (defun do-command (this-command) > (switch (this-command :test #'equal) > ("d" (display-recipe-names)) > (t (format t "#~a# is an unknown command~%" this-command)))) Symbolics Common Lisp: (defun do-command (this-command) (scl:selector this-command equal ("d" (display-recipe-names)) (t (format t "#~a# is an unknown command~%" this-command))))
From: Kenneth Tilton on 5 Jan 2010 10:02
Pillsy wrote: > On Jan 4, 10:27 pm, Kenneth Tilton <kentil...(a)gmail.com> wrote: > [...] >> One of the best ideas in Lisp is that of the symbol. Use them. Not strings. > >> (do-command 'd) > >> ...and... > >> (case cmd (d (display-recipe-names))) > >> If you get a string, quick, intern it. > >> kt > >> * But it /was/ funny to see the contorted monstrosities up with which >> they came. kt > > Like using FIND-SYMBOL instead of INTERN. Heathens! > > Cheers, > Pillsy Now, Pillsy, we talked about you needing to read the notes: "Notes: find-symbol is operationally equivalent to intern, except that it never creates a new symbol." So if you /get/ a string (say, the column name of a CSV file) quick, intern it. Do not build a string version of Lisp. Why do You People bother trying to correct me? Even EG/RG acknowledges that I am the final arbiter of all things Lisp. His Kennyness -- http://www.stuckonalgebra.com |