How to get the compiler used in common lisp?
example imaginary:
(defun get-compiler ()
(RETURN-COMPILER-NAME))
(defun some-factory ()
(cond ((string= (get-compiler) "SBCL") (some))
((string= (get-compiler) "CMU") (some))
((string= (get-compiler) "MCL") (some))
((string= (get-compiler) "EXCL") (some))))
You can use lisp-implementation-type (see the manual):
CL-USER> (lisp-implementation-type)
"SBCL"
or
CL-USER> (lisp-implementation-type)
"Clozure Common Lisp"
Note that the function returns the name of the implementation, which is not necessarily a compiler. Some Common Lisp implementations can include an interpreter, a compiler, a translator to another programming language, etc.
Related
Could someone show me how to inline a function in Common Lisp?
I have a lot of small functions which are called all the time so it would be good to save the cost of these function calls.
For example, how would you inline the "standalone" function inside the "caller" function?
(defun standalone ()
(* 2 5))
(defun caller ()
(standalone))
(declaim (inline standalone))
(defun standalone ()
(* 2 5))
(defun caller ()
(standalone))
Documentation is here.
(But keep in mind that defining a function that always returns the numeric literal 10 doesn't make much sense...)
See the Cookbook: https://lispcookbook.github.io/cl-cookbook/performance.html#code-inline
The declaration inline replaces function calls with function body, if the compiler supports it. It will save the cost of function calls but will potentially increase the code size. The best situation to use inline might be those small but frequently used functions. The following snippets show how to encourage and prohibit code inline.
;; The globally defined function DISPATCH should be open-coded,
;; if the implementation supports inlining, unless a NOTINLINE
;; declaration overrides this effect.
(declaim (inline dispatch))
(defun dispatch (x) (funcall (get (car x) 'dispatch) x))
;; Here is an example where inlining would be encouraged.
;; Because function DISPATCH was defined as INLINE, the code
;; inlining will be encouraged by default.
(defun use-dispatch-inline-by-default ()
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here only affects this function.
(defun use-dispatch-with-declare-notinline ()
(declare (notinline dispatch))
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here affects all following code.
(declaim (notinline dispatch))
(defun use-dispatch-with-declaim-noinline ()
(dispatch (read-command)))
;; Inlining would be encouraged becuase you specified it.
;; The INLINE here only affects this function.
(defun use-dispatch-with-inline ()
(declare (inline dispatch))
(dispatch (read-command)))
Some implementations like the Allegro CL compiler ignore inline declarations.
Compiler macros as created by define-compiler-macro (different from defmacro!) can be also used instead to inline code.
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?
I thought I would be able to find this through Google, SO, or the books I'm reading, but it is proving elusive.
In the implementation I'm learning with, I can do the following at the top-level:
(defvar *foo* 4)
(set 'bar 3)
If I then call (describe '*foo*) and (describe 'bar), I get a description saying that *foo* is special and bar is non-special (among other details).
Is there a function that takes a symbol variable as an argument and returns true or false if it is special? If so, is describe probably implemented in part by calling it?
Context: I'm learning Common Lisp, but at work I have a system with a dialect of Lisp similar to Common Lisp, but the describe function is unimplemented. There's sort of an XY thing going on here, but I'm also trying to grok Lisp and CL.
Many Common Lisp implementations provide the function variable-information in some system dependent package.
Here in SBCL:
* (require :sb-cltl2)
NIL
* (sb-cltl2:variable-information '*standard-output*)
:SPECIAL
NIL
((TYPE . STREAM))
This function was proposed as part of some other functionality to be included into ANSI CL, but didn't make it into the standard. Still many implementations have it. For documentation see: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node102.html
A non-special variable's environment will be captured when you create a closure over it:
(let ((x 1))
(let ((f (lambda () x)))
(let ((x 2))
(eql 2 (funcall f)))))
;;=> NIL
A special variable's lexical environment will not:
(defvar *x*) ; *x* is special
(let ((*x* 1))
(let ((f (lambda () *x*)))
(let ((*x* 2))
(eql 2 (funcall f)))))
;;=> T
Using this approach, you could easily define a macro that will expand to code like the previous that will let you determine whether a symbol is globally proclaimed special:
(defmacro specialp (symbol)
(let ((f (gensym "FUNC-")))
`(let ((,symbol 1))
(let ((,f (lambda () ,symbol)))
(let ((,symbol 2))
(eql 2 (funcall ,f)))))))
(specialp x) ;=> NIL
(specialp *x*) ;=> T
Note that this isn't a function, it's a macro. That means that the macro function for specialp is getting called with the symbols X and *X*. This is important, because we have to construct code that uses these symbols. You can't do this with a function, because there'd be no (portable) way to take a symbol and create a lexical environment that has a lexical variable with that name and a lambda function that refers to it.
This also has some risks if you try to use it with certain symbols. For instance, in SBCL, if you try to bind, e.g., *standard-output* to something that isn't a stream or a stream designator, you'll get an error:
CL-USER> (specialp *standard-output*)
; in: SPECIALP *STANDARD-OUTPUT*
; (LET ((*STANDARD-OUTPUT* 1))
; (LET ((#:FUNC-1038 (LAMBDA # *STANDARD-OUTPUT*)))
; (LET ((*STANDARD-OUTPUT* 2))
; (EQL 2 (FUNCALL #:FUNC-1038)))))
;
; caught WARNING:
; Constant 1 conflicts with its asserted type STREAM.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
Defining globals with set or setq is not supported. There are 2 common ways to define globals:
(defparameter *par* 20) ; notice the earmuffs in the name!
(defvar *var* 30) ; notice the earmuffs in the name!
All global variables are special. Lexically scoped variables (not special) are not possible to get described. E.g.
(let ((x 10))
(describe 'x)) ; ==> X is the symbol X
It describes not the lexical variable but the symbol representation. It really doesn't matter since you probably never need to know in run time since you know this when you're writing if it's a bound lexical variable or global special by conforming to the earmuffs naming convention for global variables.
I believe the only way to get this information at run time* is by either using an extension to CL, as Rainer noted, or to use eval.
(defun specialp (x)
(or (boundp x)
(eval `(let (,x)
(declare (ignorable ,x))
(boundp ',x)))))
(Defect warning: If the variable is unbound but declared to be a type incompatible with nil, this could raise an error. Thanks Joshua for pointing it out in his answer.)
* The macro approach determines which symbol it is checking at macro expansion time, and whether that symbol is lexical or special at compile time. That's fine for checking the status of a variable at the repl. If you wanted to e.g. print all of the special variables exported by a package, though, you would find that to use the macro version you would end up having to use eval at the call site:
(loop for s being the external-symbols of :cl-ppcre
when (eval `(specialp-macro ,s)) do (print s))
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.
how would you / should you export symbols from a package, when you have not yet created them at the time of calling the defpackage macro?
(defpackage :package-a
(:use :cl)
(:export :fruit-type :animal-type :orange :apple :peach :cat :dog))
(deftype fruit-type () '(member ORANGE APPLE PEACH))
(deftype animal-type () '(member CAT DOG))
(defparameter *other-symbol-names*
'("A1" "A2" "B1" "B2")) ;imagine a longer list here
;with names generated by a function
(defparameter *other-symbols*
(mapcar #'(lambda (sym-name)
(import (make-symbol sym-name))
(find-symbol sym-name))
*other-symbol-names*))
(mapcar #'export *other-symbols*)
(setf A1 32 A2 33 B1 34 B2 35)
also there is another package
(defpackage :package-b
(:use :cl :package-a))
(in-package :package-b)
(format nil "~a ~a ~a ~a" |A1| |A2| |B1| |B2|)
I have read in "The Complete Idiot’s Guide to Common Lisp Packages" that
"Now that you’ve learned all about the myriad functions and macros that can be
used to manipulate packages you shouldn’t really be using any of them. Instead,
all of the functionality of IMPORT, EXPORT, SHADOW, etc. is all rolled up in a
single macro called DEFPACKAGE, which is what you should use for real (non-
prototype) code."
Is there a code smell in my above code? Also, how would you export the other symbols (cat dog animal-type, etc. -- there are many of them) to avoid duplication?
It's hard to say much without knowing more about your intent and requirements, but in many situations it would be better to have one or more hash tables (or similar) which contain your dynamically generated objects, and then export symbol(s) for your hash table(s).
Here's a hand-wavy example of how this can work. If you can edit and add some more information about your requirements and constraints I'll see if I can be more help.
(in-package :cl)
(defpackage :package-a
(:use :cl)
(:export *objects* put get)
(:shadow get))
(in-package :package-a)
(defvar *objects* (make-hash-table)
"Container for dynamically generated objects we want to expose to the
package's user.")
(defun put (name obj)
(setf (gethash name *objects*) obj))
(defun get (name &optional default)
(gethash name *objects* default))
;; Your code can put arbitrary objects into the hash table
(put :foo (lambda () :a-thunk))
(put :bar (lambda () :another))
;; And your users can retrieve them
(in-package :cl-user)
(use-package :package-a)
(funcall (get :foo)) ;; => :a-thunk
I used keywords for the names rather than symbols because keywords aren't local to packages (or, more specifically, they're all local to the keyword package. If you were to instead use 'foo and 'bar you'd be back to needing to export those symbols, or your user would need to use the package designator when refer to them (e.g. (get 'package-a::foo)).
You can also use strings as keys, though in that case you would want to create the table with (make-hash-table :test 'equal). The default hash table test is #'eql, which doesn't compare strings appropriately. Comparing keywords with #'eql is faster than comparing strings with #'equal (because keywords are a simple pointer comparison, as opposed to the character-by-character comparison necessary for strings) but the difference is likely insignificant unless you have specific reason to think otherwise.
This approach provides a better interface for your users, because now your have defined entry points, the opportunity for docstrings, defaults, and easier exploration at the REPL.