How to pass common-lisp' local variable to maxima? - common-lisp

I am using maxima inside SBCL and I want to do the following-simple demo for real time plotting without pause/delay-:
(loop for j from 1 below 10 do
#$plot2d(sin(x),[x,0,?j*%pi])$)
error:range must be of the form [variable, min, max]; found: [x,0,%pi*j]
I have to use setf/defvar, but I want to use local variables.
Questions:
How to pass common-lisp' local variable to maxima?
Thanks in advance.

Maxima uses only dynamic scope, not lexical scope. Maxima variables are implemented as Lisp symbols which are declared special. In order for J to be visible to Maxima, it must be declared special in one way or another (either via DEFVAR/DEFPARAMETER or (DECLARE (SPECIAL ...)), I forget if there are other ways).
I know this is not satisfying since dynamic scope makes it possible to have name collisions and therefore subtle bugs. Maybe you can ensure there are no name collisions by using a gensym; maybe write a macro to substitute a gensym for another variable and declare the gensym special, something like that.

I am suing this macro:
(defmacro with-maxima (&body body)
"write normal maxima exprs."
`(progn
,#(mapcar (lambda (slot)
(destructuring-bind (&body args) slot
`(maxima:displa ,(read-from-string (concatenate 'string
"#$" (princ-to-string args) "$")))))
body)
,(read-from-string "#$reset()$")
,(read-from-string "#$kill(all)$")))
example :
(with-maxima
"y3: k-y1-2*y2"
"gradef(y1,t,v1)"
"gradef(y2,t,v2)"
"gradef(v1,t,a1)"
"gradef(v2,t,a2)"
"diff(y3,t)")

Related

How to define globally a user input as variable

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.

Franz LISP to Common LISP conversion questions

I'm reviving an old LISP program from the early 1980s.
(It's the Nelson-Oppen simplifier, an early proof system.
This version was part of the Ford Pascal-F Verifier,
and was running in Franz LISP in 1982.) Here's
the entire program:
https://github.com/John-Nagle/pasv/tree/master/src/CPC4
I'm converting the code to run under clisp on Linux,
and need some advice. Most of the problems are with
macros.
HUNKSHELL
Hunkshell was a 1970s Stanford SAIL hack to support records with named fields in LISP. I think I've converted this OK; it seems to work.
https://github.com/John-Nagle/pasv/blob/master/src/CPC4/hunkshell.l
The original macro generated more macros as record update functions.
I'm generating defuns. Is there any reason to generate macros?
By the way, look at what I wrote for "CONCAT". Is there a better way
to do that?
DEFMAC
More old SAIL macros, to make macro definition easier before defmacro became part of the language.
https://github.com/John-Nagle/pasv/blob/master/src/CPC4/defmac.l
I've been struggling with "defunobj". Here's my CL version, partly converted:
; This macro works just like defun, except that both the value and the
; function-binding of the symbol being defined are set to the function
; being defined. Therefore, after (defunobj f ...), (f ...) calls the
; defined function, whereas f evaluates to the function itself.
;
(defmacro defunobj (fname args &rest b)
`(progn
(defun ,fname ,args ,b)
;;;;(declare (special ,fname)) ;;;; ***declare not allowed here
(setq ,fname (getd ',fname))))
If I made that declare a proclaim, would that work right?
And what replaces getd to get a function pointer?
SPECIAL
There are lots of (DECLARE (SPECIAL FOO)) declarations at top
level in this code. That's not allowed in CL. Is it
appropriate to use (PROCLAIM (SPECIAL FOO)) instead?
Concat
Essentially correct, but indentation is broken (like everywhere else - I suggest Emacs to fix it).
Also, you don't need the values there.
defunobj
I suggest defparameter instead
of setq. Generally speaking, before setting a variable (with, e.g., setq) one should establish it (with, e.g., let or defvar).
fdefinition is what
you are looking for instead of getd.
I also don't think you are using backquote right:
(defmacro defunobj (fname &body body)
`(progn
(defun ,fname ,#body)
(defparameter ,fname (fdefinition ',fname))))
Special
I think defvar and defparameter
are better than proclaim
special.
PS. Are you aware of the CR.se site?

What is the purpose of &environment in Common Lisp?

I am confused about the &environment parameter in common lisp. In particular, what is it useful for, and why is it a parameter, rather than a special variable?
EDIT: It would also be nice to see a concrete example of how &environment would be used in code.
Doc
Macro Lambda Lists:
&environment is followed by a single variable that is bound to an
environment representing the lexical environment in which the macro
call is to be interpreted. This environment should be used with
macro-function, get-setf-expansion, compiler-macro-function, and
macroexpand (for example) in computing the expansion of the macro, to
ensure that any lexical bindings or definitions established in the
compilation environment are taken into account.
Explanation
Operators which define macros (local or global) have to define how code is expanded before being evaluation or compiled, and thus may need to expand existing macros, whose expansion may depend on the environment - so the macro definitions need the environment.
Not a Special Variable
Special variables are more dangerous because the user might rebind them and because they are harder to handle correctly in multi-threaded code.
Example
All over the places.lisp:
(defmacro psetf (&whole whole-form
&rest args &environment env)
(labels ((recurse (args)
(multiple-value-bind (temps subforms stores setterform getterform)
(get-setf-expansion (car args) env)
(declare (ignore getterform))
(when (atom (cdr args))
(error-of-type 'source-program-error
:form whole-form
:detail whole-form
(TEXT "~S called with an odd number of arguments: ~S")
'psetf whole-form))
(wrap-let* (mapcar #'list temps subforms)
`(MULTIPLE-VALUE-BIND ,stores ,(second args)
,#(when (cddr args) (list (recurse (cddr args))))
,#(devalue-form setterform))))))
(when args `(,#(recurse args) NIL))))
From iolib/src/new-cl/definitions.lisp:
(defmacro defconstant (name value &optional documentation
&environment env)
(destructuring-bind (name &key (test ''eql))
(alexandria:ensure-list name)
(macroexpand-1
`(alexandria:define-constant ,name ,value
:test ,test
,#(when documentation `(:documentation ,documentation)))
env)))
For example when Lisp wants to macroexpand a form, it needs to know which name refers to what macro definition. This can depend on the globally available macros, locally bound macros via macrolet or what is available during compilation. Thus the environment object makes it possible to macroexpand a form with respect to different environments.
Environment variables provide to the macro author information about the declarations et. al. enforce when the macro was invoked. The macro author can then use that information to customize how he chooses to expand the macro. For example he might add or subtract debugging code based on declarations he finds in the environment. For example he might infer the type of expressions he was given to work with and add or subtract code to get better performance.
You can write a lot of Common Lisp code and never use &environment. There are situations where it becomes necessary, when those are would make good follow up question. Rainer hints at an answer to that.

Unbound variable in Common Lisp

I'm new to Lisp and I was reading about an text-generator example in ANSI Common Lisp, Chapter 8. I follow the example and defined a function "see" in the scope of a LET variable "prec",
(let ((prec '|.|))
(defun see (symb)
(let ((pair (assoc symb (gethash prev *words*))))
(if (null pair)
(push (cons symb 1) (gethash prev *words*))
(incf (cdr pair))))
(setf prev symb)))
and saved it into a lisp file.
Then when I returned to REPL and tried to invoke see after loading the compiled version of the file, an error occurred:
The variable PREV is unbound.
[Condition of type UNBOUND-VARIABLE]
How do I invoke see properly? And what's a lexical closure for? I'm all confused.
Thanks for helping.
Looks like you've typed prec instead of prev in the enclosing let form.
Lexical closures are functions that 'close over' a part of the lexical environment (hence the name). There are many good introductions to closures in lisp that I will not attempt to repeat here but, essentially, let is the most common way to manipulate the lexical environment; in this case, you want to add the binding for prev, which will then be available to code within the body of the form. Your function see will 'close over' this binding, and so each call to see has access to it, even though when you make these calls, you will no longer be in the lexical environment established by the let form. You could say the function definition takes the binding with it, in a sense.
As you appear to have mis-typed the name of the prev, your function is trying to refer to a binding that has not been established at that point in the code.

How to call particular function depending on variable that's passed in?

I'm fairly new to lisp but I've been playing around with it. I have several problems which I need clarifying. Below is my little macro that I defined.
(defmacro transform (query)
'(lambda (row)
(eq (nth 1 query) (nth 0 (nth 0 row)))
)
)
I'm just wondering how I can specify the function to use in the body dynamically? Say if I want to use the "+" or "-" function instead of "eq", or even another function that I defined? Like I thought it'd be possible to pass in the name of the function as a parameter but that obviously doesn't work. I also get variable unbound errors when I modify the list (query) that's passed in.
In the body of the macro, you can use all of Lisp's run-time library to generate the actual expansion. So, for example:
(defmacro transform (query &key (test 'eq))
(let ((row-var (gensym)))
`(lambda (,row-var)
(,test (nth 1 ,query) (nth 0 (nth 0 ,row-var))))))
This version uses the "backtick" instead of a plain apostrophe, which allows for "unquoting" of forms within the body, thus allowing the inclusion of generated forms into the result.
You can use this macro like your original version:
(transform (...))
or (passing an explicit test function):
(transform (...) :test equal)
Note, that you should not use plain symbols as variable names in macro expansions (as your row argument to the generated lambda expression) as that might accidentally interfer with the use of that symbol at the site of the use of your macro. You simply don't know when writing your macro, whether there will be a variable called row somewhere when your macro is used, and whether it is not already used within the query form/expression. Your original definition would "capture" the variable, possibly altering the meaning of whatever query does.
funcall is the answer! Decided to just pass it in and use funcall to evaluate the function.

Resources