Is it good idea to import something from cl-user package? As far as I know, contents of this package are not specified by the standard, so does import of functions from cl-user package break compatibility of a program? For example I use GNU CLISP and I want to use xor and ! functions in my program, I've imported them from cl-user package, but how do I know that other implementations include these functions as well? Is there any conventions or something?
On CLISP, both xor and ! are externals of the EXT package, not CL-USER. They are not standard functions, so you cannot rely on their existence when writing portable code.
You could write something along these lines to use the built-in functions on CLISP and homebrewn ones on other LISPs:
(in-package :my-package)
#+CLISP
(import 'ext:xor)
#-CLISP
(defun xor (&rest what)
;; your own xor implementation
...)
#+CLISP
(import 'ext:!)
#-CLISP
(defun ! (&rest what)
;; your own ! implementation
...)
Xor is also in alexandria, but with a bit different semantics.
It is a good idea to use wrapper libraries that encapsulate implementation-specific behaviour under a portable interface. This makes your code more portable, or at least facilitates making it more portable.
Related
This question already has answers here:
What makes Lisp macros so special?
(15 answers)
Closed 3 months ago.
I keep reading that Lisp macros are one of the most powerful features of the language. But reading over the specifications and manuals, they are just functions whose arguments are unevaluated.
Given any macro (defmacro example (arg1 ... argN) (body-forms)) I could just write (defun example (arg1 ... argN) ... (body-forms)) with the last body-form turned into a list and then call it like (eval (example 'arg1 ... 'argN)) to emulate the same behavior of the macro. If this were the case, then macros would just be syntactic sugar, but I doubt that syntactic sugar would be called a powerful language feature. What am I missing? Are there cases where I cannot carry out this procedure to emulate a macro?
I can't talk about powerful because it can be a little bit subjective, but macros are regular Lisp functions that work on Lisp data, so they are as expressive as other functions. This isn't the case with templates or generic functions in other languages that rely more on static types and are more restricted (on purpose).
In some way, yes macros are simple syntactic facilities, but you are focused in your emulation on the dynamic semantics of macros, ie. how you can run code that evaluates macros at runtime. However:
the code using eval is not equivalent to expanded code
the preprocessing/compile-time aspect of macros is not emulated
Lexical scope
Function, like +, do not inherit the lexical scope:
(let ((x 30))
(+ 3 4))
Inside the definition of +, you cannot access x. Being able to do so is what "dynamic scope" is about (more precisely, see dynamic extent, indefinite scope variables). But nowadays it is quite the exception to rely on dynamic scope. Most functions use lexical scope, and this is the case for eval too.
The eval function evaluates a form in the null lexical environment, and it never has access to the surrounding lexical bindings. As such, it behaves like any regular function.
So, in you example, calling eval on the transformed source code will not work, since arg1 to argnN will probably be unbound (it depends on what your macro does).
In order to have an equivalent form, you have to inject bindings in the transformed code, or expand at a higher level:
(defun expand-square (var)
(list '* var var))
;; instead of:
(defun foo (x) (eval (expand-square 'x))) ;; x unbound during eval
;; inject bindings
(defun foo (x) (eval `(let ((z ,x)) (expand-square z))))
;; or expand the top-level form
(eval `(defun foo (x) ,(expand-square 'x)))
Note that macros (in Common Lisp) also have access to the lexical environment through &environment parameters in their lambda-list. The use of this environment is implementation dependent, but can be used to access the declarations associated with a variable, for example.
Notice also how in the last example you evaluate the code when defining the function, and not when running it. This is the second thing about macro.
Expansion time
In order to emulate macros you could locally replace a call to a macro by a form that emulates it at runtime (using let to captures all the bindings you want to see inside the expanded code, which is tedious), but then you would miss the useful aspect of macros that is: generating code ahead of time.
The last example above shows how you can quote defun and wrap it in eval, and basically you would need to do that for all functions if you wanted to emulate the preprocessing work done by macros.
The macro system is a way to integrate this preprocessing step in the language in a way that is simple to use.
Conclusion
Macros themselves are a nice way to abstract things when functions can't. For example you can have a more human-friendly, stable syntax that hides implementation details. That's how you define pattern-matching abilities in Common Lisp that make it look like they are part of the language, without too much runtime penalty or verbosity.
They rely on simple term-rewriting functions that are integrated in the language, but you can emulate their behavior either at compile-time or runtime yourself if you want. They can be used to perform different kinds of abstraction that are usually missing or more cumbersome to do in other languages, but are also limited: they don't "understand" code by themselves, they don't give access to all the facilities of the compiler (type propagation, etc.). If you want more you can use more advanced libraries or compiler tools (see deftransform), but macros at least are portable.
Macros are not just functions whose arguments are unevaluated. Macros are functions between programming languages. In other words a macro is a function whose argument is a fragment of source code of a programming language which includes the macro, and whose value is a fragment of source code of a language which does not include the macro (or which includes it in a simpler way).
In very ancient, very rudimentary, Lisps, before people really understood what macros were, you could simulate macros with things called FEXPRs combined with EVAL. A FEXPR was simply a function which did not evaluate its arguments. This worked in such Lisps only because they were completely dynamically scoped, and the cost of it working was that compilation of such things was not possible at all. Those are two enormous costs.
In any modern Lisp, this won't work at all. You can write a toy version of FEXPRs as a macro (this may be buggy):
(defmacro deffex (fx args &body body)
(assert (every (lambda (arg)
(and (symbolp arg)
(not (member arg lambda-list-keywords))))
args)
(args) "not a simple lambda list")
`(defmacro ,fx ,args
`(let ,(mapcar (lambda (argname argval)
`(,argname ',argval))
',args (list ,#args))
,#',body)))
So now we could try to write a trivial binding construct I'll call with using this thing:
(deffex with (var val form)
(eval `(let ((,var ,val)) ,form)))
And this seems to work:
> (with a 1 a)
1
Of course, we're paying the cost that no code which uses this construct can ever be compiled so all our programs will be extremely slow, but perhaps that is a cost we're willing to accept (it's not, but never mind).
Except, of course, it doesn't work, at all:
> (with a 1
(with b 2
(+ a b)))
Error: The variable a is unbound.
Oh dear.
Why doesn't it work? It doesn't work because Common Lisp is lexically scoped, and eval is a function: it can't see the lexical bindings.
So not only does this kind of approach prevent compilation in a modern Lisp, it doesn't work at all.
People often, at this point, suggest some kind of kludge solution which would allow eval to be able to see lexical bindings. The cost of such a solution is that all the lexical bindings need to exist in compiled code: no variable can ever be compiled away, not even its name. That's essentially saying that no good compilers can ever be used, even for the small part of your programs you can compile at all in a language which makes extensive use of macros like CL. For instance, if you ever use defun you're not going to be able to compile the code in its body. People do use defun occasionally, I think.
So this approach simply won't work: it worked by happenstance in very old Lisps but it can't work, even at the huge cost of preventing compilation, in any modern Lisp.
More to the point this approach obfuscates the understanding of what macros are: as I said at the start, macros are functions between programming languages, and understanding that is critical. When you are designing macros you are implementing a new programming language.
The function find-data-from-command works fine when I run it without first doing the 'quickload' of the package. If I load the package it gives the error that split-sequence is undefined.
I have tried to reload split-sequence after loading the custom package. Doesn't work
(ql:quickload :<a-custom-package>)
(defun find-data-from-command (x desired-command)
(setq desired-data ())
(loop for line = (read-line x nil)
while (and line (not desired-data)) do
(progn
(setq commands (first (split-sequence ":" line)))
(setq data (split-sequence "," (first (rest (split-sequence ":" line)))))
(print (cons "command:" commands))
(cond
((equal commands desired-command) (return-from find-data-from-command data))))))
FIND-DATA-FROM-COMMAND
SIGMA 24 >
(setq obj-type (find-data-from-command (open "log.txt") "types"))
Error: Undefined operator SPLIT-SEQUENCE in form (SPLIT-SEQUENCE ":" LINE).
The problem is nothing to do with Quicklisp, it's to do with a package you've defined somewhere called SIGMA. In particular somewhere in your code is a form which looks like:
(defpackage "SIGMA" ;or :sigma or :SIGMA or #:sigma or ...
...
(:use ...)
...)
And then later
(in-package "SIGMA")
And the problem with this is that your package definition has an explicit (:use ...) clause.
defpackage, and the underlying function make-package has slightly interesting behaviour for the :use clause (or keyword argument in the case of make-package):
if none is given then there is an implementation-defined default;
if one is given then it overrides the default.
The idea, I think, is that implementations may want to provide a bunch of additional functionality which is available by default, and this functionality can't be in the CL package since the contents of that package is defined in the standard. So if you just say
(defpackage "FOO")
Then the implementation is allowed (and, perhaps, encouraged), to make the use-list of FOO have some useful packages in it. These packages might be the same ones that are in the default use-list of CL-USER, but I'm not sure that's required: the whole thing is somewhat under-specified.
The end result of this is that if you want to define packages which both make use of implementation-defined functionality and have explicit use-lists you have to resort to some slight trickery. How you do this is slightly up to you, but since you are by definition writing implementation-dependent code where you are defining packages like this, you probably want to make it clear that what you are doing is implementation-dependent, by some form like
(defpackage :foo
(:use ...)
#+LispWorks
(:use :lispworks :harlequin-common-lisp :cl)
...)
Or, if you just want some particular set of symbols
(defpackage :foo
(:use ...)
#+LispWorks
(:import-from :lispworks #:split-sequence))
Note that this is not quite the same thing as using a package containing the symbol.
In all these cases if your code has pretensions to be portable then there should be appropriate clauses for other implementations and a way of knowing when you're trying to run on an implemention you haven't yet seen: how to do this is outwith the scope of this answer I think.
Solved it.
The quickloading of the custom package was taking me into the package. I did not realize that. So I had to specify split-sequence is from outside. So, I replaced all occurrences of split-sequence in the function definition with
LISPWORKS:split-sequence
Then it worked.
If any one has a better solution, please do let me know. Thanks
I have this file:
#lang racket
(provide install global-var)
(define global-var 'test)
(define (install)
(set! global-var '(aaa)))
(install)
And I start the repl, typing so:
Welcome to Racket v5.3.5.
> (define global-var "test007")
> global-var
"test007"
> (require "test.rkt")
'(install)
> global-var
'test
Is it possible to load only some definitions from the file test.rkt, such that the loading does not change the value of global-var, only if I call myself (install), after I load?
I want to use only the standard racket system, not outside packages that are not installed by default in racket.
The short answer is: probably not. You should think of a racket module as a pre-compiled bundle of code that exports certain functions. Any expressions at the top level (such as the call to 'install' here) are conceptually part of the module's setup; allowing a user to use the definitions without running the setup code would invalidate the assumptions of the module writer---not nice for the writer of the module.
To take an example, I have a sound library; requiring the sound library module initializes the sound playback. If there were a tricky way to load the module without running this code, my invariants would be violated.
Perhaps you can explain why it's inconvenient for you to edit the source code?
I'm trying to write something that works in both DrRacket/plt-r5rs and Gambit/gsi.
The problem I'm having is that (load "foo.scm") in Gambit does not load define-syntax-blocks. Using (include "foo.scm") in Gambit works, but of course results in a syntax error in DrRacket.
Is there any way to solve this so that I can write portable R5RS code?
Things I've tried:
Redefining (include "foo.scm") to (load "foo.scm") and vice versa. Problem: Illegal to redefine macros in Gambit.
Wrapping said redefinitions in an (if gambit ...). Problem: Illegal to put define inside if(unless inside another define).
Passing string with filename to an include in the library file instead. Problem: Includes in Gambit seem to happen before interpretation starts.
In case it helps: In Racket you can use include in r5rs files:
#lang r5rs
(#%require (only racket include))
(include "foo.scm")
If you define #%require to do nothing in Gambit, then you can use the same source file in both implementations.
It's very hard to write a module that's compatible with both Gambit and Racket.
There are indeed ways you can test for a specific implementation and define things conditionally. There are, in fact, two systems for doing this: SRFI 0 and SRFI 7. Most implementations support one or the other. Not very many support both.
Gambit supports SRFI 0. Racket supports SRFI 7.
How can i get a lambda list specification of a some function parameters, or at least a number of arguments it takes?
For example:
(defun a (a b) )
(get-arg-list #'a) ;-> '(a b)
Common Lisp provides the function FUNCTION-LAMBDA-EXPRESSION which may be able to recover the source expression, which then includes the lambda list.
LispWorks has defined a function FUNCTION-LAMBDA-LIST which returns the arglist.
Many other implementations have some form of ARGLIST function in some internal package.
Many Common Lisp users use SLIME, a very clever editor extension for the GNU Emacs editor. It has a backend for Common Lisp called SWANK. The SWANK sources provide all kinds of interfaces to the various Common Lisp implementations, including getting the arglist of functions.
This is implementation specific, but this CLHS function might get you started - http://clhs.lisp.se/Body/f_descri.htm
The easiest way to do this is to use the SWANK library which is used by SLIME.
The way to use it is to load SLIME, which is most easily done through Quicklisp:
(ql:quickload "swank")
Then, you can get the argument list using the following function:
CL-USER> (swank-backend:arglist #'a)
(A B)