I'm trying to make a function, which should give me a list of cities:
((London United-Kingdom)
(Paris France)
(New-York USA)
(Sydney Australia))
My code doesn't work, something is wrong but I don't know why. Here is my code:
(defun make-city (name country)
(list name country))
(defun cities
(list (make-city 'London 'United-Kingdom)
(make-city 'Paris 'France)
(make-city 'New-York 'USA)
(make-city 'Sydney 'Australia)))
Does anyone know where is a problem? It must be in (defun cities....), but where?
use defvar ("define variable") instead of defun ("define function") for cities.
Common Lisp is a "lisp-2", scheme is a "lisp-1".
Related
Is there a way, in common lisp, to receive a user input, say "foo", and defvar a global variable *foo*?
For example (which does NOT work):
(defun global-name (s)
"Takes s and changes it to *s*"
(concatenate 'string "*" s "*"))
(defun add-global-var (var)
"defvars a global variable and adds it to *global-list*"
(let ((var-name (global-name var)))
(defvar var-name var)
(push var-name *global-list*)))
; Used like this:
(add-global-var "myvar")
In this case, the var-name is a string, and will not work with defvar.
Déjà vu... I asked these kinds of questions 20+ years ago ;-)
Your question
Yes, you can do that (but no, you do not want to!)
(defun add-global-var (var-name &optional (package *package*))
(let ((var (intern var-name package)))
(proclaim `(special ,var))
(push var *global-list*)))
Please see
proclaim
intern
*package*
Alternatively, you can use a macro as the other answer suggests - in
fact, symbol creation at macroexpansion time (which is part of
compilation) is a very common thing,
cf. gensym.
Your problem
There is little reason to do this though.
Global variables created at run time were not available at compile time
and are, therefore, pretty useless.
Why do you want to do this?
If you want to map strings to values, you are much better off using an
equal hash table.
If you want to integrate with read,
you should call it while binding
*package*
to your internal temp package and then use
symbol-value
to store and retrieve values.
You will use intern to
map "variable names" to the symbols.
This is most likely a XY problem since it's very unusual to need to make a variable with a name made up in runtime. It's very common in compile time, but not runtime. #coredump has already covered compile time macros if that is what you are after.
Here is how you do it though:
(defun add-global-var (var)
"defvars a global variable and adds it to *global-list*"
(let ((var-name (intern (string-upcase (global-name var)))))
(set var-name var)
(push var-name *global-list*)))
set is deprecated, but I doubt it will ever be removed. Implementations might not be able to run as fast though since this is like messing with internals.
Since the names are not from source you you have no good use for the bidnings. because of this I would rather use a hash:
(defvar *bindings* (make-hash-table :test #'eq))
(defun add-binding (var)
(let ((var-name (intern (string-upcase (global-name var)))))
(setf (gethash var-name *bindings*) var)
*bindings*))
A reason to do this is as a part of your own little interpreter symbol table or something. You don't need a list of them since you can get all the keys from the hash as well as get the bound values.
Yes, with a macro:
(defvar *global-list* nil)
I changed global-name so that it also accepts symbols, to avoid thinking about whether the string should be upcased or not. With a symbol, the case is given by readtable-case (you can use uninterned symbols if you want to avoid polluting packages).
(defun global-name (name)
(check-type name (or string symbol))
(intern
(concatenate 'string "*" (string name) "*")))
I named the macro defvar*:
(defmacro defvar* (name)
`(push
(defvar ,(global-name name) ',name)
*global-list*))
Tests:
CL-USER> (defvar* #:foo)
(*FOO*)
CL-USER> (defvar* #:bar)
(*BAR* *FOO*)
Note:
You can also add an optional package argument like in #sds's answer, that's better.
Consider this question. Here the basic problem is the code:
(progv '(op arg) '(1+ 1)
(eval '(op arg)))
The problem here is that progv binds the value to the variable as variable's symbol-value not symbol-function. But, that's obvious because we didn't explicitly suggest which values are functions.
The Plan
So, in order to solve this problem, I thought of manually dynamically binding the variables, to their values based on the type of values. If the values are fboundp then they should be bound to the symbol-function of the variable. A restriction, is that match-if can't be a macro. It has to be a function, because it is called by a funcall.
Macro : functioner:
(defmacro functioner (var val)
`(if (and (symbolp ',val)
(fboundp ',val))
(setf (symbol-function ',var) #',val)
(setf ,var ,val)))
Function: match-if:
(defun match-if (pattern input bindings)
(eval `(and (let ,(mapcar #'(lambda (x) (list (car x))) bindings)
(declare (special ,# (mapcar #'car bindings)))
(loop for i in ',bindings
do (eval `(functioner ,(first i) ,(rest i))))
(eval (second (first ,pattern))))
(pat-match (rest ,pattern) ,input ,bindings))))
Here, the let part declares all the variables lexically (supposedly). Then declare declares them special. Then functioner binds the variables and their values aptly. Then the code in the pattern is evaluated. If the code part is true, then only the pattern-matcher function pat-match is invoked.
The Problem
The problem is that in the function, all it's arguments are evaluated. Thus bindings in the let and declare parts will be replaced by something like :
((v1 . val1)(v2 . val2)(v3 . val3))
not
'((v1 . val1)(v2 . val2)(v3 . val3))
So, it's treated as code, not a list.
So, I'm stuck here. And macros won't help me on this one.
Any help appreciated.
Not the answer you are looking for, but PROGV is a special operator; it is granted the ability to modify the dynamic bindings of variables at runtime; AFAIK, you can't simply hack it to operate on "dynamic function bindings".
The point of progv is to use list of symbols and values that are evaluated, meaning that you can generate symbols at runtime and bind them dynamically to the corresponding values.
You might be able to find a solution with eval but note that if you macroexpand into (eval ...), then you loose the surrounding lexical context, which is generally not what you want ("eval" operates on the null lexical environment). I speculate that you could also have a custom code walker which works on top-level forms but reorganizes them, when it finds your special operator, to bring the context back in, producing something like (eval '(let (...) ...)).
I am trying to learn common lisp through paradigms of artificial intelligence. one of the exercises in the book was to define a function that would return the last name of a given list without a certain suffix or word. As an example if the list contained bruce banner, phd it would return banner. here is my solution, however this would still return the last element regardless if it was a suffix or not
(Defun last-name (name)
(if (member (last name) *suffix*)
(Last-name (butlast name))
(last name)))
where
(defparameter *suffix* '( MD PHD DR))
a similar exercise was presented in the book omitting a prefix in a list using 'rest' instead of 'butlast' and returning the first element. That worked perfectly fine.
(defparameter *titles* '( Mr MRS MS SIR MADAM DR ADMIRAL MAJOR GENRAL ))
(Defun first-name (name)
(if (member (first name) *titles*)
(first-name (rest name))
(first name)))
I am not sure if I am missing anything in the last-name function or if my logic is incorrect. Any help is greatly appreciated!
Apologies if the text is long, it is my first post and I was not sure what level of detail I should include.
Thank you.
The reason is that last does not return the last element of a list, but a list containing the last element. That is:
(last '(bruce banner phd))
;; -> (PHD), not PHD
Actually, last gets an optional argument n after the list, argument which is set to 1 by default, and returns a list with the last n elements of the first parameter (see the manual).
So the function member does not return true.
Try to change the function in:
(defun last-name (name)
(if (member (car (last name)) *suffix*)
(Last-name (butlast name))
(car (last name))))
Why there is no syntax sugar for funcall? We need it a lot. Won't it be great to write something like (&#do-something arg0 arg1 arg2) instead of (funcall do-something arg0 arg1 arg2) Why not add something like Ruby's &:method notation? Is there something already in the language?
There's nothing like that built into the language; you can easily assign the function to an additional name though, and use that. E.g., if you want to use &, you can:
CL-USER> (setf (symbol-function '&) (symbol-function 'funcall))
#<FUNCTION FUNCALL>
CL-USER> (&'list 1 2 3)
(1 2 3)
CL-USER> (&'cons 'x 'y)
(X . Y)
(There was a recent question on Stack Overflow about different ways to do that first line: How to stop evaluating lisp form when passed as function parameter?.)
Won't it be great to write something like (&#do-something arg0 arg1 arg2) instead of (funcall do-something arg0 arg1 arg2)?
Probably not. Common Lisp is a language that prefers expressive names for functions and macros. The name funcall is recognized, and it makes it clear that there's an indirect function call happening. Why would we want to obscure that? Evidently most people find funcall has the right balance between "short enough to write" and "long enough to be descriptive".
Why there is no syntax sugar for funcall?
You might call macros "syntax sugar" in Common Lisp, but there's no need for it here. Funcall is a function, not a special form or macro, so it's really very easy to alias it with another name, as shown above. The fact that most people don't do this should say something about how desirable it is.
There is no syntax for funcall, because we don't need it a lot (or else, define "we"). I mean, in a Lisp-2, such as Common Lisp, that's the trade-off, and unless you're doing some heavy lambda calculus, you get used to it.
If you really want to use a more succint syntax, you can define a dispatch macro character:
(set-dispatch-macro-character
#\# #\&
#'(lambda (stream subchar arg)
(let ((args-var (gensym)))
`(lambda (&rest ,args-var)
(declare (dynamic-extent ,args-var))
(apply ,(read stream t nil t) ,args-var)))))
(let ((my-function #'max))
(#&my-function 1 3 2))
Check if your compiler will optimize lambda forms and dynamic-extent &rest arguments passed to apply.
I advise against defining the single character & as a macro character, because it's a constituent character mostly used in the symbols &optional, &rest, &key, &allow-other-keys, &aux, &whole, &body and &environment.
If you're inclined to black magic:
(defun black-magic (stream sub-char numarg)
(declare (ignore sub-char numarg))
`(funcall ,#(read stream)))
(set-dispatch-macro-character
#\# #\! #'black-magic)
Rough example:
CL-USER> (defun foo (fn x y z)
#!(fn x y z))
FOO
CL-USER> (foo #'* 1 2 3)
6
CL-USER> (foo #'+ 1 1 1)
3
(It's better to use apply however... but it's even better to keep things simple and use nothing of this sort.)
Of couse we anyone can define something like that by reader macros, but i think it's not a very good idea to do such thing if you expecting than someone will read your code somtime.
Actually this sort of reader macro is syntactic sugar you're asking for. Do you reject your own idea now? Every time, when you use non-conventional syntactic sugar, you probably make things worse for your future code-readers.
I need to define a variable with a name contained in another variable.
The following code does not work and it uses eval, therefore not very good style.
(defvar symbol "zap")
(eval `(defvar ,symbol 100))
(print zap)
It's usually better to use a hash table for that purpose.
First of all -- are you sure you need to do this?
Now, with that out of the way --
(defvar *symbol-name* "zap")
(let ((symbol (intern *symbol-name*)))
(proclaim `(special ,symbol))
(setf (symbol-value symbol) 100))
(print |zap|)
Note that |zap| will normally need to be quoted with pipes, because intern is case-sensitive, while the default readtable upcases symbols by default. So if you don't quote, as in (print zap), that is interpreted as (PRINT ZAP), with the wrong case for zap. Alternatively, you can upcase the interned symbol, with (intern (string-upcase *symbol-name*)).
Update after seeing what you're actually trying to do.
You definitely don't want to be defining global variables for that. A data structure that maps keys (A1...H4, etc) to numbers is what you want. In this case, your keys can be symbols or strings. And the data structure could be a hashtable, a plist or alist (among other choices). For example, a string-keyed hashtable would look like:
(defvar *table* (make-hash-table :test #'equalp))
(setf (gethash "A1" *table*) 42)
(print (gethash "A1" *table*)) ==> prints 42
If you absolutely want to do this, with global variables, I suspect that SET and SYMBOL-VALUE (and using symbols instead of strings) might do the trick. It definitely falls in the "hm, yes, you can do it that way, but I am not convinced it's the best way" territory, though.
However, you are most probably better off either using a hash-table or (skipping storage completely, if there's no need to mutate what A1 means further down the line) a function that parses the letter and digit apart and calculates the relevant value.
use SET:
CL-USER 13 > (defvar *some-symbol* '*this-is-some-symbol*)
*SOME-SYMBOL*
CL-USER 14 > (set *some-symbol* 42)
42
CL-USER 15 > *this-is-some-symbol*
42
or if it is a string:
(setf (symbol-value (find-symbol some-symbol-name)) 42)