I have a file with some lisp code and I want to compile it to fasl. I'm defining some functions and macros that use some of that functions and more functions that use these macros.
So when I tried to compile the file with
$ sblc --eval "(compile-file \"file.lisp\")" --eval "(quit)"
I got compilation errors about that the macro couldn't expand because the function is not defined. But everything has been compiling in the normal order:
; compiling (DEFUN MY-FUNCTION ...)
; compiling (DEFMACRO MY-MACRO-THAT-USES-MY-FUNCTION ...)
; compiling (DEFUN OTHER-FUNCTION-THAT-USES-MACRO ...)
; file: /path/to/file/file.lisp
; in: DEFUN OTHER-MY-FUNCTION-THAT-USES-MACRO
; (MY-MACRO-THAT-USES-MY-FUNCTION 1)
;
; caught ERROR:
; during macroexpansion of (MY-MACRO-THAT-USES-MY-FUNCTION 1). Use *BREAK-ON-SIGNALS* to
; intercept.
; The function COMMON-LISP-USER::MY-FUNCTION is undefined.
So then I tried to load the file first and then to compile it:
sbcl --eval "(load \"file.lisp\")" --eval "(compile-file \"file.lisp\")" --eval "(quit)"
And this worked without warning or errors.
But this solution looks ugly because of:
1) I need to specify the file twice (even if I write the bash script, this doesn't look so good)
2) It looks like the file is compiled twice: first time when I load it and second time when I actually compile it.
3) If I'll do it from repl, the file will be loaded to it and sometimes this can be bad. What if I just want to compile the file, but not load it?
So I see 3 variant here:
1) I'm doing something completely wrong.
2) I need to regroup macros and functions several files and load only necessary function with load but not the whole file. (this doesn't help with any of the problems but make them less significant)
3) There is a command that does does what I want to do and I just couldn't find it.
So how should I compile such type of files?
Thanks for help in advance.
That's a frequent question. Probably already answered on Stackoverflow.
during compilation, the code of functions is generated, but not loaded into the compiler.
macros OTOH are also made available in the compile-time environment
Two solutions:
separate files: one which defines macros and the needed functions, another one where the macros are being used. Load the macro and its support code, before compiling dependent files.
use EVAL-WHEN with :load-toplevel, :compile-toplevel and :execute around the functions which are needed at compile-time. :compile-toplevel makes sure than any enclosed top-level code gets executed during compilation - for a defun this would define the function at compile-time, too.
See: http://www.lispworks.com/documentation/HyperSpec/Body/s_eval_w.htm#eval-when
Note, that you don't need two evals in your example. You can also write --eval "(progn (load ...) (compile-file ...)) or even --eval "(let ((file ...)) (load file) (compile-file file)).
Related
I am a noob Lisper and am attempting Adam Tornhill's Lisp for the Web tutorial using Portacle Emacs.
I would very much appreciate an explanation of why the set-up code below will run happily and change the REPL cursor to RETRO-GAMES> if entered line by line in the REPL but does not seem to work if compiled in the buffer. (The first time it compiles it often throws an error saying it can't find the quickload packages; the REPL cursor never changes.)
If anyone can shed light on what this implies for compiled programs, it would be great. I'm struggling to understand the value of programming directly into a REPL rather than a saved file. If there are any noob-level resources on what a fully compiled program "looks like" in terms of whether it includes the type of loady code below, a link would make my day. Thank you.
(load "C:/Users/USER/portacle/all/quicklisp/quicklisp/setup.lisp")
(ql:quickload :cl-who)
(ql:quickload :hunchentoot)
(ql:quickload :parenscript)
(defpackage :retro-games
(:use :cl :cl-who :hunchentoot :parenscript))
(in-package :retro-games)
(defclass game ()
((name :initarg :name)
(votes :initform 0)))
To see why this code is a problem for compilation, consider what the compiler must do when compiling a file containing it, in a 'cold' Lisp image, where 'cold' here specifically means 'without Quicklisp loaded'. To see this, divide it into chunks. For the sake of argument we'll imagine that the way the file compiler works is to read a form from the file, compile it, and write it out. It does have to work in a way which is equivalent to this for our purposes so that's OK here.
First chunk
(load "C:/Users/USER/portacle/all/quicklisp/quicklisp/setup.lisp")
load is a normal function and the call to it occurs at top level in the file: what the compiler will do is to compile code so that, when the file is loaded this load is called. The compiler will not itself execute load, and so Quicklisp will not be loaded at compile time.
Second chunk
(ql:quickload :cl-who)
(ql:quickload :hunchentoot)
(ql:quickload :parenscript)
This code has two problems. In a cold lisp the QL package does not exist, because the previous load was not executed at compile-time, so the reader will raise an exception when reading these forms. Compilation will stop here.
If the Lisp is not cold and in particular if the QL package does exist (so, if the Lisp image which is doing the compilation does have Quicklisp loaded into it) then the compiler will simply write code which causes these three ql:quickload calls to take place at load-time, and will not load these three QL systems now.
In a cold lisp you will not get beyond this step. In a Lisp with Quicklisp loaded at compile time you will.
Third chunk
(defpackage :retro-games
(:use :cl :cl-who :hunchentoot :parenscript))
This chunk will only be reached in a Lisp where Quicklisp is loaded at compile time. This is a package definition, and it has effect at compile time, as it must do. But, at compile time, the calls in the second chunk have not yet taken place: this package definition refers to packages which do not exist. So this is a compile-time error and compilation will stop here.
If the Lisp doing the compilation not only has Quicklisp loadad but also has the three QL systems loaded, this will succeed.
Fourth chunk
(in-package :retro-games)
This will only be reached in a lisp which, at compile time, has both Quicklisp and the three QL systems loaded into it. In that case it tells the compiler that the following forms are to be read in the retro-games package. Otherwise it is never reached.
Fifth chunk
(defclass game ()
((name :initarg :name)
(votes :initform 0)))
In the unlikely event the compiler gets this far, this defines a class called retro-games::game.
What the problem is
The problem is that the compiler is, well, a compiler: what it does is compile code for later execution. But the later parts of your source depend on the earlier parts of your source having been loaded.
There are two ways to deal with this.
If you are only writing a very small amount of code, then you can tell the compiler that some things must happen at compile time as well as at load time. The way you do this is by eval-when, and the particular incantation you want is something like this, for chunks one and two:
(eval-when (:compile-toplevel :load-toplevel :execute)
(load "C:/Users/USER/portacle/all/quicklisp/quicklisp/setup.lisp"))
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload :cl-who)
(ql:quickload :hunchentoot)
(ql:quickload :parenscript))
Note you must have two separate incantations of eval-when because the QL package needs to be brought into being by the first so that the second can be read.
The semantics of eval-when are mildly hairy, but this incantation will do what you want: it will tell the compiler to load these things and make sure that they are also run at load time.
The second way of dealing with this, which is appropriate for larger systems, is to have one or more files which build the compile-time environment for later files, and which are compiled and loaded before the later files, under the control of something like ASDF. In this case you typically want some minimal bootstrap file, which perhaps simply needs to make sure that Quicklisp is loaded and then ask Quicklisp (and hence ASDF) to compile and load everything else, with dependency management looked after by those tools, so there would be no ql:quickloads at all. How to set up something like this is beyond this answer however!
I have to write a game in Lisp. In order to make it clear, I wanted to split the code in different .lisp files.
How can I call a function out of a function in the other file?
E.g. file1.lisp has a function called function1 and file2.lisp has a function called function2.
How can I call function2 out of function1?
Thanks!
Just so you know, there are a variety of different Lisp systems. I'll post the answer for Common Lisp.
The naive way is to use (load "filename.lisp"), but that doesn't really work very well after a while. Therefore...
Common Lisp has a library called "ASDF", which handles packaging and file management. There's a bit of setup to ASDF.
Create directory where ASDF looks for files.
Add this information to my Lisp system's init file.
I use this in my .sbclrc file (assuming that I created a .asdf file in ~) :
(pushnew "~/.asdf/" asdf:*central-registry* :test #'equal)
I usually use a previously built ASDF file and then modify it.
Here's a sample ASDF file's contents:
(asdf:defsystem #:cl-linq
:depends-on ( #:alexandria #:anaphora)
:components ((:file "cl-linq"))
:name "cl-linq"
:version "0.1"
:maintainer "Paul Nathan"
:author "Paul Nathan"
:licence "LLGPL"
:description "CL LINQ style interface with strains of SQL"
:long-description
"DSL for managing and querying datasets in a SQL/LINQ style
syntax. cl-linq provides a simple and usable set of primitives to
make data examination straightforward. ")
I put this code in a file cl-linq.asd next to my source code (cl-linq.lisp from the component "cl-linq" in the defsystem) and then symlink the cl-linq.asd file to my ~/.asdf/ directory.
Within my cl-linq.lisp file I include this:
(defpackage :cl-linq
(:use
:common-lisp
:anaphora)
(:export
#:query
#:cl-linq-select))
(in-package :cl-linq)
So for your case, I would have 2 components; each with their own defpackage form, exporting the functions out that the other package needed.
For the examples, I've taken the code from CL-LINQ, a project of mine. You are quite free to use it as a template.
This is for Emacs Lisp (aka elisp)
Create a file at this location: ~/.emacs.d/init.el
Create a file at this location: ~/.emacs.d/file1.el
Create a file at this location: ~/.emacs.d/file2.el
Now, open up ~/.emacs.d/init.el and write (and then save):
(load "~/.emacs.d/file1.el")
(load "~/.emacs.d/file2.el")
(defun run-both-functions ()
(interactive)
(switch-to-buffer "*Messages*")
(first-function)
(sit-for 2)
(second-function))
Now, open up ~/.emacs.d/file1.el and write (and then save):
(defun first-function ()
(message "My name is Fred."))
Now, open up ~/.emacs.d/file2.el and write (and then save):
(defun second-function ()
(message "My name is George."))
Now, restart Emacs and type: M-x run-both-functions RET
Any functions that you put into any of the three (3) files mentioned above will be accessible to other functions. You will note that run-both-functions includes an (interactive) statement, which means that the user can call the function with M-x or a keyboard shortcut.
If you use the function load it can be useful to not specify the file type.
Loading files: fasl or source
Instead of (load "foo.lisp") one can call (load "foo"). Typically Common Lisp provides the feature of compiling Lisp files to fasl (fast load) files. Those are usually pre-compiled byte code or native code. Typically the Common Lisp implementation will load the compiled code if a file exists for it. This saves time (because compiled code usually can be loaded much faster than Lisp source code) and the code usually is faster (because a file compiler has compiled it).
Often one uses a function to load the compiled file if it is newer, or first compile the source file to a new compiled file.
Loading a file, based on the current file being loaded
In (load "foo") the file foo is not a complete filename. For example we don't know the directory where it is loaded from. This depends on things like the value of *default-pathname-defaults* or in some implementations on a current directory (typical for Unix systems). It may be useful to load the file based on the file we are currently loading - if loading one file triggers more files to be loaded. For this Common Lisp has the variables *load-pathname* and *load-truename* (which is the real filename as used with the filesystem).
To load a file foo in the same directory as the currently loaded file call:
(load (merge-pathnames "foo" *load-pathname*))
To load a file foo in a subdirectory bar of the same directory as the currently loaded file call:
(load (merge-pathnames "bar/foo" *load-pathname*))
With Common Lisp I done it like this:
In file1.lisp I define a function sayHello and export that function under the package name helloLisp
(defpackage :helloLisp
(:use :common-lisp)
(:export #:sayHello))
(in-package :helloLisp)
(defun sayHello () (print "Hello!"))
In the file file2.lisp I require this file like that:
(require "helloLisp" "./file1.lisp")
(helloLisp:sayHello)
Tested with SBCL 1.4.11
So I just got Land of Lisp and started to do the first program.
I have a couple questions.
Is there a way to just write some code and run it through a compiler, or interpreter, and not use the REPL thing? I don't like it much. I can't seem to go back if I messed up. It just kinda says "Ha you screwed up, retype that whole function."
I would also like to know what the point of REPL is.
Non-REPL work flow
Edit your file
Compile the file using compile-file; fix errors and warnings; repeat.
Load the file using load; evaluate the form you want; repeat
Example
$ cat > f.lisp <<EOF
(defun f (x) (if (zerop x) 1 (* (f (1- x)) x)))
EOF
$ clisp -q -norc -c f.lisp
;; Compiling file /home/sds/f.lisp ...
;; Wrote file /home/sds/f.fas
0 errors, 0 warnings
$ clisp -q -norc -i f.fas -x '(f 10)'
;; Loading file f.fas ...
;; Loaded file f.fas
3628800
$
The Right Way
Use an IDE, e.g., Emacs with SLIME.
This way, you edit the code in an editor which supports auto-indent and shows you help for each standard symbol.
You compile and test the functions as soon as you write them, giving you a very short development cycle. Under the hood this is accomplished by the IDE interacting with the REPL (this answers your last question).
What is REPL?
Read-Eval-Print loop is a faster, more versatile version of the Edit-Compile-Run loop.
Instead of operating in terms of whole programs (which can be slow to compile and whose execution can be tedious to navigate to the specific location being tested), you operate in terms of a specific function you work on.
E.g., in gdb, you can execute a function with print my_func(123), but if you change my_func, you have to recompile the file and relink the whole executable, and then reload it into gdb, and then restart the process.
With Lisp-style REPL, all you need to do is re-eval the (defun my-func ...) and you can do (my-func 123) at the prompt.
I have the following code in a clj (clojure) namespace.
(ns project.clojure.clojurescript-macros)
(def trace-history (atom []))
; hmm, you could run out of memory on recursive functions here?
; Fortunately functions aren't actually recursive in clojure. :]
(defmacro push-args [name args]
`(swap! trace-history
(fn [stack#]
(conj stack# [~name (zipmap ~(vec (map str args)) ~args)]))))
(push-args :hello [:a :b :c])
within another cljs (clojurescript) namespace, I have the following
(ns project.clojurescript.user
(:require-macros [project.clojure.clojurescript-macros :as c]))
(c/push-args :hello [:a :b :c])
I compile my clojurescript code, and open it in my browser, Unfortunately, I get the following error.
Uncaught TypeError: Cannot read property 'trace_history' of undefined main.js:22348
(anonymous function) main.js:22348
Looking at line 22348 in my compiled clojurescipt code, I see the following.
cljs.core.swap_BANG_.call(null, project.clojure.trace_history, function(stack__6402__auto__) {
return cljs.core.conj.call(null, stack__6402__auto__,
cljs.core.PersistentVector.fromArray(["\ufdd0'hello",
cljs.core.zipmap.call(null,
cljs.core.PersistentVector.fromArray([":a", ":b", ":c"], true),
cljs.core.PersistentVector.fromArray(["\ufdd0'a", "\ufdd0'b", "\ufdd0'c"],
true))],
true))
});
The problem is that project.clojure.trace_history has not been defined anywhere in main.js . I understand what is wrong, but I am unsure as to how I might fix it. I have tried out other solutions, such as putting trace-history in a shared clojure file and putting trace history in a cljs file itself. None seem to work. Given that I want to have a shared global atom between all compilations of this macro, how can I do so in Clojurescript?
An atom is run-time data, a macro is a compile-time construct. It doesn't really make sense for a macro to have a "shared global atom" - what your macro there does is compile to code which simply expects there to be a symbol called trace-history in the current NS.
If you simply want to write common code which can use an atom, then you should write it such that can take the atom as an argument rather than assuming its existence via a hardcoded symbol name.
If you mean you want the same atom's value to be available to you on both the client and server of a Clojure+ClojureScript application, you'll need to write your own code to coordinate the value via Ajax calls... that's not something built in to the language.
This is how I export symbols :bar and :baz from package foo:
(in-package :cl-user)
(defpackage foo
(:use :cl)
(:export :bar :baz))
(in-package :foo)
When I remove :baz from the list of exported symbols SBCL complains and the compilation fails.
warning:
FOO also exports the following symbols:
(FOO:BAZ)
How can I make SBCL make forget about :baz without reloading SLIME?
SBCL:
* (apropos "unexport")
UNEXPORT (fbound)
* (documentation 'unexport 'function)
"Makes SYMBOLS no longer exported from PACKAGE."
* (apropos "unintern")
UNINTERN (fbound)
* (documentation 'unintern 'function)
"Makes SYMBOL no longer present in PACKAGE. If SYMBOL was present then T is
returned, otherwise NIL. If PACKAGE is SYMBOL's home package, then it is made
uninterned."
Search led me here, but I had slightly different issue.
; caught WARNING:
; MY-PACKAGE also uses the following packages:
; (DEPENDENCY)
For this case, one needs
* (documentation 'unuse-package 'function)
"Remove PACKAGES-TO-UNUSE from the USE list for PACKAGE."
There is plenty of documentation on these issues, which you should read or reread. This package/symbol thing sounds trivial enough at first sight, but it is different enough from what other languages do to be worth some reading (i.e. trying to reuse knowledge from other languages is particularly risky when it comes to packages and symbols).
If, after reading the docs, you still have trouble, try rereading them (the experience gained by having trouble will help you focus on the relevant sections; rereading without getting into trouble between readings is not very productive IMHO).
Some links I found useful:
http://www.lispworks.com/documentation/HyperSpec/Body/11_.htm
http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html
http://www.flownet.com/ron/packages.pdf