I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In addition, I am using SBCL, Emacs, and Slime.
By the end of chapter 9, the author shows the dribble tool.
He shows the following:
I tried to reproduce the commands presented by the author. Considering the inputs, the only difference was the fact that I put a different location to save the file. In my environment, I did:
CL-USER> (dribble "/home/pedro/miscellaneous/misc/symbolic-computation/teste-tool.log")
; No value
CL-USER> (cons 2 nil)
(2)
CL-USER> '(is driblle really working?)
(IS DRIBLLE REALLY WORKING?)
CL-USER> "is dribble useful at all?"
"is dribble useful at all?"
CL-USER> (dribble)
; No value
The file was indeed created:
$ readlink -f teste-tool.log
/home/pedro/miscellaneous/misc/symbolic-computation/teste-tool.log
Note that I did not get messages such as "Now recording in file --location---" in the REPL while I was typing. But this may vary according to the Lisp implementation.
The big surprise was that, unfortunately, the file was empty. Thus, dribble did not work as expected.
Did I do something wrong?
Yes, by default, within Slime I don't think this works.
It will work within the SBCL Repl:
➜ sbcl
This is SBCL 2.0.1.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (dribble "dribble-test.lisp")
* (* 8 5)
40
* "Will this work?"
"Will this work?"
* (dribble)
* %
Which can be confirmed:
➜ cat dribble-test.lisp
* (* 8 5)
40
* "Will this work?"
"Will this work?"
* (dribble)
Saving "REPL history" seems less useful with Slime IMO because of all the "non-REPL evaluation" that you do by e.g. selecting a function or an expression or region and evaluating that in the REPL.
To actually save and view history within Slime, see slime-repl-save-history and associated functions; you can even merge histories from independent Repls if you so choose :-)
Related
I'm using Clozure Common Lisp on Windows. When using the DRIBBLE command and evaluating some simple forms followed by closing the DRIBBLE stream, a specified file is created but nothing is written into it.
(DRIBBLE "test.log")
(+ 2 2)
(LIST 'a 'b 'c)
(DRIBBLE)
Is this a known limitation of CCL on Windows or a problem with my environment?
If you look at the source code for dribble (in particular, process-dribble), you can see that CCL redirects the *TERMINAL-IO* stream to a two-way stream. If you try to write directly to that stream (and possible call finish-output after, to be sure), then the file is going to being written to.
> (dribble "/tmp/log")
> (print "test" *terminal-io*)
> (dribble)
The use case for dribble, at least as implemented in CCL (the behaviour of dribble is practically unspecified), is to be used from the terminal, where you cannot easily record your session. Under an IDE like Lispbox/Slime, there are other mechanisms to store commands, such as the buffer that holds the current REPL.
Recently, I have come across the so-called hash-dot Common Lisp reader macro and am wondering how it works and what it does. Using search engines was not of much help, so any examples, explanations and especially uses-cases are most welcome.
In the spec this is called sharpsign dot. It does read-time evaluation. You can search the Common Lisp hyper spec for that. I don’t have it to hand but I believe in Emacs with slime one can look up the documentation for reader macros. Do C-c C-d C-h to see if there is a command for that.
#.foo reads as whatever (eval foo) returns. Thus:
CL-USER> '((+ 1 2) #.(+ 1 2))
((+ 1 2) 3)
CL-USER> (read)
#.(* 3 4)
12
This question already has answers here:
operator #+ and #- in .sbclrc
(2 answers)
Closed 6 years ago.
Recently I tried to read code about cl-mysql, but got stuck with the #+.
Tried to google it, but not work, so turn to here
(defun make-lock (name)
#+sb-thread (sb-thread:make-mutex :name name)
#+ecl (mp:make-lock :name name)
#+armedbear (ext:make-thread-lock)
#+ (and clisp mt) (mt:make-mutex :name name)
#+allegro (mp:make-process-lock :name name))
And looks like it is for different backend lisp compiler. But still no idea why write something like this.
Anyone can help me make it clear, thx.
#+ is a reader-macro that checks if a keyword is in the special variable *FEATURES*. If it isn't there, the following form will be skipped over (by the reader; the compiler will never see it). There is also #- which does the opposite.
There are some things that aren't part of the Common Lisp standard, but are important enough that all (or most) implementations provide a non-standard extension for them. When you want to use them in code that needs to work on multiple implementations, you have to use read-time conditionals to provide the correct code for the current implementation. Mutexes (and threads in general) are one of those things.
Of course there may be features provided by third party libraries as well. The contents of *FEATURES* will look something like this:
(:SWANK :QUICKLISP :SB-BSD-SOCKETS-ADDRINFO :ASDF-PACKAGE-SYSTEM :ASDF3.1
:ASDF3 :ASDF2 :ASDF :OS-UNIX :NON-BASE-CHARS-EXIST-P :ASDF-UNICODE :64-BIT
:64-BIT-REGISTERS :ALIEN-CALLBACKS :ANSI-CL :ASH-RIGHT-VOPS
:C-STACK-IS-CONTROL-STACK :COMMON-LISP :COMPARE-AND-SWAP-VOPS
:COMPLEX-FLOAT-VOPS :CYCLE-COUNTER :ELF :FLOAT-EQL-VOPS
:FP-AND-PC-STANDARD-SAVE :GENCGC :IEEE-FLOATING-POINT :INLINE-CONSTANTS
:INTEGER-EQL-VOP :INTERLEAVED-RAW-SLOTS :LARGEFILE :LINKAGE-TABLE :LINUX
:LITTLE-ENDIAN :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLADDR
:OS-PROVIDES-DLOPEN :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL
:OS-PROVIDES-PUTWC :OS-PROVIDES-SUSECONDS-T :PACKAGE-LOCAL-NICKNAMES
:PRECISE-ARG-COUNT-ERROR :RAW-INSTANCE-INIT-VOPS :SB-DOC :SB-EVAL :SB-FUTEX
:SB-LDB :SB-PACKAGE-LOCKS :SB-SIMD-PACK :SB-SOURCE-LOCATIONS :SB-TEST
:SB-THREAD :SB-UNICODE :SBCL :STACK-ALLOCATABLE-CLOSURES
:STACK-ALLOCATABLE-FIXED-OBJECTS :STACK-ALLOCATABLE-LISTS
:STACK-ALLOCATABLE-VECTORS :STACK-GROWS-DOWNWARD-NOT-UPWARD :SYMBOL-INFO-VOPS
:UNIX :UNWIND-TO-FRAME-AND-CALL-VOP :X86-64)
So if you wanted to write code that depends on Quicklisp for example, you could use #+quicklisp. If you wanted code that is only run if Quicklisp is not available, you'd use #-quicklisp.
You can also use a boolean expression of features. For example,
#+(or sbcl ecl) (format t "Foo!")
would print Foo! on either SBCL or ECL.
#+(and sbcl quicklisp) (format t "Bar!")
would only print Bar! on SBCL that has Quicklisp available.
One could imagine that we can write:
(defun make-lock (name)
(cond ((member :sb-thread *features)
(sb-thread:make-mutex :name name))
((member :ecl *features*)
(mp:make-lock :name name))
...))
But that does usually not work, because we can't read symbols when their package is not existing and some packages are implementation/library/application specific. Packages are not created at read time in a lazy/automatic fashion.
In Common Lisp, reading a symbol of a package, which does not exist, leads to an error:
CL-USER 1 > (read-from-string "foo:bar")
Error: Reader cannot find package FOO.
1 (continue) Create the FOO package.
2 Use another package instead of FOO.
3 Try finding package FOO again.
4 (abort) Return to level 0.
5 Return to top loop level 0.
In your example sb-thread:make-mutex is a symbol which makes sense in SBCL, but not in Allegro CL. Additionally the package SB-THREAD does not exist in Allegro CL. Thus Allegro CL needs to be protected from reading it. In this case, the symbol sb-thread:make-mutex will only be read, if the the feature sb-thread is present on the cl:*features* list. Which is likely only for SBCL, or a Lisp which claims to have sb-threads available.
The feature expressions here prevents the Lisp from trying to read symbols with unknown packages - the packages are unknown, because the respective software is not loaded or not available.
Lisp is said to enable redefinitions of its core functions.
I want to define an alias to the function cl:documentation function, such that
(doc 'write 'function) === (documentation 'write 'function)
How can this be done and made permanent in SBCL?
Creating an Alias
You are not trying to redefine (i.e., change the definition of) the system function documentation, you want to define your own function with a shorter name which would do the same thing as the system function.
This can be done using fdefinition:
(setf (fdefinition 'doc) #'documentation)
How to make your change "permanent" in common lisp
There is no standard way, different implementation may do it differently, but, generally speaking, there are two common ways.
Add code to an init file - for beginners and casual users
SBCL
CLISP
Clozure
ECL
The code in question will be evaluated anew every time lisp starts.
Pro:
Easy to modify (just edit file)
Takes little disk space
Normal lisp invocation captures the change
Con:
Evaluated every time you start lisp (so, slows start up time if the code is slow)
Save image - for heavy-weight professionals
SBCL
CLISP
Clozure
ECL - not supported
The modified lisp world is saved to disk.
Pro:
Start uptime is unaffected
Con:
Requires re-dumping the world on each change
Lisp image is usually a large file (>10MB)
Must specify the image at invocation time
Even though #sds has already answered pretty thoroughly I just wanted to add that the utility library serapeum has defalias
I use a simple macro for this:
(defmacro alias (to fn)
`(setf (fdefinition ',to) #',fn))
e.g.
(alias neg -) => #<Compiled-function ... >
(neg 10) => -10
Other answers include detail about how to make this permanent.
I love the idea of image-based languages, and lately I've been toying with Common Lisp via sbcl. I've read in a few places about how through being able to save and load back an image of the virtual machine, you can evolve an application or set of apps running on that image.
I get how to load code into an image and get it running, slime makes this sort of thing very nice, but my question is this: How can I tell what functions are defined in an image? Let's say I want to make an update to a function days or months after it has been running and I can't remember the name. Is there any way to get to the code or even just the names of the functions defined in an the image?
Now, I do write the code out into source and load it in via the repl, so I have a copy there, but it seems like this would be an obvious feature.
Common Lisp has the idea of packages. Packages are kind of a registry for symbols and are used as namespaces for symbols. You can ask Common Lisp for a list of all packages.
CL-USER 1 > (list-all-packages)
(#<The SQL-COMMON package, 0/4 internal, 28/32 external>
#<The LOOP package, 245/256 internal, 3/4 external>
#<The COMM package, 0/4 internal, 940/1024 external>
#<The REG package, 41/64 internal, 0/4 external>
...)
Each packages stores the interned symbols in some data structure. You can ask Common Lisp which symbols are interned in a package.
CL-USER 2 > (loop for symbol being
each external-symbol in (find-package "COMMON-LISP")
collect symbol)
(MAKE-ARRAY INVOKE-DEBUGGER STRING-TRIM ...)
To make that easier, Common Lisp provides functions APROPOS and APROPOS-LIST.
CL-USER 3 > (apropos "MAKE-LOCK")
MP::INTERNAL-MAKE-LOCK (defined)
MP:MAKE-LOCK (defined)
WWW-UTILS:MAKE-LOCK (defined)
MAKE-LOCK
RESOURCES::MAKE-LOCK (defined)
MINIPROC:MAKE-LOCK (defined)
Functions, Classes, etc. use symbols as their identifier. You can also ask a symbol, which function it denotes.
CL-USER 4 > (symbol-function 'www-utils:make-lock)
#<Function WWW-UTILS:MAKE-LOCK 41E006A69C>
Sometimes a Common Lisp also records the definition of functions. Then the function FUNCTION-LAMBDA-EXPRESSION can be used to retrieve 'it'.
CL-USER 5 > (defun foo (a) (* (sin a) a))
FOO
CL-USER 6 > (pprint (function-lambda-expression 'foo))
(LAMBDA (A)
(DECLARE (SYSTEM::SOURCE-LEVEL #<EQ Hash Table{0} 41403151C3>))
(DECLARE (LAMBDA-NAME FOO))
(* (SIN A) A))
But usually nowadays Common Lisp implementations don't use the recorded definitions, but record the locations of the source for each Lisp construct.
Most Common Lisp implementations can track the source locations in an implementation specific way.
The Common Lisp standard defines a function ED.
CL-USER 7 > (ed 'www-utils:make-lock)
This calls an editor (internal or external) and should open the source code for that function. To make that work, Common Lisp needs to keep track of the source location for each function. Next the editor needs to have access to that source. Sometimes the location recorded is an absolute path /Users/joswig/lisp/utils.lisp . If the editor wants to open that file, it should be accessible. But it is also possible to use logical pathnames like http:server;utils.lisp . This is then translated into a real physical pathname. This translation can later be configured. So it would be possible to move a Lisp to a different machine with different pathnames, configure the logical pathname HTTP and then the Lisp still finds all source code, even though it is on a different machine with a different file system structure. So, to make it work may need some configuration. But it is a very useful feature and it is widely used.
How the recording of source code and how the recording of source locations work is implementation dependent and is a feature of the respective Lisp in combination with its development environment. Better Lisp implementations have a lot of features in this area.
You can also use do-symbols or do-external-symbols if you prefer:
example:
>> (do-external-symbols (s (find-package :foo-package)) (print s))
FOO-PACKAGE:XXX
FOO-PACKAGE:YYY
FOO-PACKAGE:ZZZ
NIL
Where XXX, YYY & ZZZ are all external symbols in the package :foo-package.