I am new to common lisp. Is there a CL library to pretty print collections, in my case, nested hash tables?
If you considering writing it yourself, here is a starting point using print-object. It is not implementation independent, but this works at least in LispWorks and SBCL.
(defmethod print-object ((object hash-table) stream)
(format stream "#HASH{~{~{(~a : ~a)~}~^ ~}}"
(loop for key being the hash-keys of object
using (hash-value value)
collect (list key value))))
First, CL does not have a "collection" type.
Second, some (most?) CL implementations will print hash tables with content if you set *print-array* to t.
Third, if your CL implementation does not do that, you can easily whip up your own, based on, say, hash-table->alist.
With the Serapeum library, we can use the dict constructor and enable pretty-printing with (toggle-pretty-print-hash-table):
(dict :a 1 :b 2 :c 3)
;; =>
(dict
:A 1
:B 2
:C 3
)
With the Rutils library:
if we enable pretty printing of hash-tables with (toggle-print-hash-table), they are printed like so:
rutils-user> #h(:foo 42)
#{
:FOO 42
}
It uses print-object under the hood, so its warning applies (not standard, but works in some implementations like SBCL).
The #h reader macro is a shortcut to create hash-tables.
Related
In my program I have constant strings, the values are known at compilation time. For each offset there are currently 2 associated strings. I first wrote the following code:
(eval-when (:compile-toplevel :load-toplevel :execute) ;; BLOCK-1
(defstruct test-struct
str-1
str-2))
(eval-when (:compile-toplevel) ;; BLOCK-2
(defparameter +GLOBAL-VECTOR-CONSTANT+ nil) ;; ITEM-1
(let ((vector (make-array 10
:initial-element (make-test-struct)
:element-type 'test-struct)))
(setf (test-struct-str-1 (aref vector 0)) "test-0-1")
(setf (test-struct-str-2 (aref vector 0)) "test-0-2")
(setf +GLOBAL-VECTOR-CONSTANT+ vector)))
(format t "[~A]~%" (test-struct-str-1 (elt +GLOBAL-VECTOR-CONSTANT+ 0)))
(format t "[~A]~%" (test-struct-str-2 (elt +GLOBAL-VECTOR-CONSTANT+ 0)))
This seems to work as it returns the following:
[test-2-1]
[test-2-2]
In BLOCK-1 the struct containing the data is defined, for compile-time, load-time and execute-time. In BLOCK-2, the code which create a vector and sets the values is executed, at compile-time.
But I have the following concerns:
This code seems unnecessary verbose
The strings are stored in a structure
I need to manually set the offset of each values ((aref vector 0), (aref vector 1), etc).
When I set ITEM-1 inside BLOCK-1 instead of BLOCK-2 I get an error in SBCL which I don't understand
What is the idiomatic way to define complex constants in Common Lisp?
It's not really clear what you want to do from your question.
First important note: your code is seriously broken. It's broken because you define +global-vector-constant+ only at compile time but refer to it later than that. If you compile this file and then load that compiled file into a cold image you will get errors.
It is absolutely critical when dealing with things like this to make sure that your code will compile in a cold Lisp. One of the classic problems with resident environments (which CL isn't really, compared to the way Interlisp-D was for instance) is to end up with systems which you can't cold build: I'm pretty sure I worked for several years with an Interlisp-D sysout that no-one knew how to cold build any more.
If what you want is an object (an array, for instance) whose initial value is computed at compile time and then treated as a literal, then the answer to that is, in general, a macro: macros are exactly functions which do their work at compile time, and so a macro can expand to a literal. In addition it must be the case that the object you want to be a literal is externalizable (which means 'can be dumped in compiled files') and anything involved in it is known about at compile time. Instances of some classes are externalizable by default, those of some other classes can be made externalizable by user code, and some are not externalizable at all (for instance functions).
In quite a lot of simple cases, like the one you gave, if I understand it, you don't really need a macro, and in fact you can almost always get away without one, although it may make your code easier to understand if you do use one.
Here is a simple case: many arrays are externalizable if their elements are
(defparameter *my-strings*
#(("0-l" . "0-r")
("1-l" . "1-r")))
This means that *my-strings* will be bound to a literal array of conses of strings.
A more interesting case is when the elements are, for instance structures. Well, structures are also externalizable, so we can do that. And in fact it's quite possible, still, to avoid a macro, although it now becomes a bit noisy.
(eval-when (:compile-toplevel :load-toplevel :execute)
(defstruct foo
l
r))
(defparameter *my-strings*
#(#s(foo :l "0-l" :r "0-r")
#s(foo :l "1-l" :r "1-r")))
Note that the following won't work:
(defstruct foo
l
r)
(defparameter *my-strings*
#(#s(foo :l "0-l" :r "0-r")
#s(foo :l "1-l" :r "1-r")))
It won't work because, at compile time, you are trying to externalize instances of a structure which is not yet defined (but it probably will work if the Lisp is not cold, and you might even be able to reload the compiled file you made that way). Again, in this case you can avoid the eval-when in a larger system by ensuring that the file which defines the foo structure is compiled and loaded before the file with the defparameter is loaded.
And even in more complex cases you can escape using a macro. For instance for many sorts of objects which are normally not externalizable you can teach the system how to externalize them, and then splice the object in as a literal using #.:
(eval-when (:compile-toplevel :load-toplevel :execute)
;; Again, this would be in its own file in a bigger system
(defclass string-table-wrapper ()
((strings)
(nstrings :initform 0)))
(defmethod initialize-instance :after ((w string-table-wrapper)
&key (strings '()))
(let ((l (length strings)))
(when l
(with-slots ((s strings) (n nstrings)) w
(setf s (make-array l :initial-contents strings)
n l)))))
(defmethod make-load-form ((w string-table-wrapper) &optional environment)
(make-load-form-saving-slots w :slot-names '(strings nstrings)
:environment environment))
) ;eval-when
(defgeneric get-string (from n)
(:method ((from string-table-wrapper) (n fixnum))
(with-slots (strings nstrings) from
(assert (< -1 n nstrings )
(n)
"bad index")
(aref strings n))))
(defparameter *my-strings*
#.(make-instance 'string-table-wrapper
:strings '("foo" "bar")))
Note that, of course, although the value of *my-strings* is a literal, code ran to reconstruct this object at load-time. But that is always the case: it's just that in this case you had to define what code needed to run. Instead of using make-load-form-saving-slots you could have done this yourself, for instance by something like this:
(defmethod make-load-form ((w string-table-wrapper) &optional environment)
(declare (ignore environment))
(if (slot-boundp w 'strings)
(values
`(make-instance ',(class-of w))
`(setf (slot-value ,w 'strings)
',(slot-value w 'strings)
(slot-value ,w 'nstrings)
,(slot-value w 'nstrtrings)))
`(make-instance ',(class-of w))))
But make-load-form-saving-slots is much easier.
Here is an example where a macro does perhaps least make reading the code easier.
Let's assume you have a function which reads an array of strings from a file, for instance this:
(defun file-lines->svector (file)
;; Needs CL-PPCRE
(with-open-file (in file)
(loop
with ltw = (load-time-value
(create-scanner '(:alternation
(:sequence
:start-anchor
(:greedy-repetition 1 nil
:whitespace-char-class))
(:sequence
(:greedy-repetition 1 nil
:whitespace-char-class)
:end-anchor)))
t)
for nlines upfrom 0
for line = (read-line in nil)
while line
collect (regex-replace-all ltw line "") into lines
finally (return (make-array nlines :initial-contents lines)))))
Then, if this function is available at macroexpansion time, you could write this macro:
(defmacro file-strings-literal (file)
(check-type file (or string pathname) "pathname designator")
(file-lines->svector file))
And now we can create a literal vector of strings:
(defparameter *fl* (file-strings-literal "/tmp/x"))
However you could perfectly well instead do this:
(defparameter *fl* #.(file-lines->svector "/tmp/x"))
Which will do the same thing, but slightly earlier (at read time, rather than at macroexpansion/compile time). So this is gaining nothing really.
But you could also do this:
(defmacro define-stringtable (name file &optional (doc nil docp))
`(defparameter ,name ,(file-lines->svector file)
,#(if docp (list doc) nil)))
And now your code reads like
(define-stringtable *st* "my-stringtable.dat")
And that actually is a significant improvement.
Finally note that in file-lines->svector that load-time-value is used to create the scanner exactly once, at load time, which is a related trick.
First of all, your let code can be simplified to
(defparameter +global-vector-constant+
(let ((vector ...))
...
vector))
Second, you can also do
(defparameter +global-vector-constant+
(make-array 10 :element-type 'test-struct :initial-content
(cons (make-test-struct :str-1 "test-0-1" :str-2 "test-0-2")
(loop :repeat 9 :collect (make-test-struct)))))
Note that the benefit of :element-type 'test-struct is generally limited to code self-documentation (see upgraded-array-element-type)
I have a use case where I want to update one of my map type variables inside a method call. To demonstrate here is a code snippet,
(defn func [mymap]
(conj mymap [1 2])) ;update mymap variable here such that changes are persistent after the method returns
(let [mymap {}
_ (func mymap)] (println mymap))
which outputs {} because I think a new map is created with the conj function. How do I update the mymap variable in func such that the output of the above program will be {1 2}?
If it is not possible in Clojure, how are such use cases handled in general?
Many choices. Simplest is to rebind the mymap variable. Consider:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn doit [mymap]
(into mymap {:b 42}))
(dotest
(let [m {:a 1}
m2 (doit m)]
(spyx m2)))
m2 => {:a 1, :b 42}
and we get what we expect.
Update the code to reuse the name m:
(dotest
(let [m {:a 1}
m (doit m)]
(spyx m)))
m => {:a 1, :b 42}
Here the 2nd usage of m creates a separate variable that shadows the first m. This works great and people do it accidentally all the time without even realizing it.
If you want to copy the behavior of Java, you need a Clojure atom to create a mutable storage location.
(dotest
(let [m-atom (atom {:a 1})]
(swap! m-atom doit)
(spyx #m-atom)))
(deref m-atom) => {:a 1, :b 42}
Here swap! applies the function doit to the contents
of m-atom, the puts the results as the new contents.
We need the #m-atom or (deref m-atom) to pull out the contents of the atom for printing.
The above convenience functions can be found here. I also have some great documentation references in this template project. Be especially sure to study the Clojure Cheatsheet daily.
Clojure uses immutable data types by default. This means, you cannot
mutate the data in place like you are used to from many other
programming languages.
The functional approach here is to use the result from the conj (the
last statement inside a defn is it's return value).
(let [mymap {}
result (func mymap)]
(println result))
The longer you can keep up with pure functions on immutable data the
easier your life will be; reasoning about your programs and testing
them becomes a lot easier.
There is of course the option to use mutable data classes from Java, but
don't use them unless you really have to.
And since nearly all programs need some state, there are also atom:s
I only mention this here, because short of def everywhere, atom
everywhere are the next best "trap" beginners run into.
I need to create a class at run-time, possibly without resorting to eval. Knowing that the metaclass protocol is not fully standardized in Common-Lisp, after browsing through the The Common Lisp Object System MetaObject Protocol, I tried the following code to create a class, instantiate it, and set a slot value of the instance to a number:
(defparameter *my-class*
(make-instance 'standard-class
:name 'my-class
:direct-slots '((:name x :readers (get-x) :writers ((setf get-x))))))
(defparameter *my-instance* (make-instance *my-class*))
(setf (get-x *my-instance*) 42) ;; => 42
Unfortunately this code works correctly on SBCL, but not on CCL, where the class creation seems to work, but the instance creation (make-instance *my-class*) causes the following error:
There is no applicable method for the generic function:
#<STANDARD-GENERIC-FUNCTION INITIALIZE-INSTANCE #x30200002481F>
when called with arguments:
(#<error printing CONS #x302001A9F6A3>
[Condition of type CCL:NO-APPLICABLE-METHOD-EXISTS]
I tried looking at closer-mop package, that should hide the differences between the various implementations for the meta-object protocol, but I could not find any function or class useful to my scope.
So the question is: is there a portable way of creating a class and instantiating it at run time by using directly the metaclass level of CLOS?
Usually one would use ENSURE-CLASS to create a class. The purpose of ENSURE-CLASS is to be the functional equivalent of DEFCLASS. Minus special implementation-specific things DEFCLASS does - for example to support features of the development environment.
You can use MAKE-INSTANCE, but for example it won't register the class under its name. It also would not call any additional ENSURE-CLASS-USING-CLASS methods.
Since the default for the metaclass is standard-class, CCL should also compute a default for the direct superclasses, which it does not - unfortunately.
I would hope that closer-mop fixes those incompatibilities, but I haven't checked.
In CCL:
? (ensure-class 'my-class
:direct-slots '((:name x
:readers (get-x)
:writers ((setf get-x))))
:direct-superclasses (list (find-class 'standard-object)))
#<STANDARD-CLASS MY-CLASS>
? (find-class 'my-class)
#<STANDARD-CLASS MY-CLASS>
? (let ((foo (make-instance 'my-class)))
(setf (get-x foo) 10)
(incf (get-x foo) 32)
(get-x foo))
42
LispWorks actually does it correctly. The metaclass defaults to standard-class and the direct superclass is then standard-object.
CL-USER 25 > (clos:ensure-class 'foobar
:direct-slots '((:name x
:readers (get-x)
:writers ((setf get-x)))))
#<STANDARD-CLASS FOOBAR 4020001713>
CL-USER 26 > (class-direct-superclasses *)
(#<STANDARD-CLASS STANDARD-OBJECT 40E018E313>)
CCL seems to require that you manually specify the direct superclasses as well.
(defparameter *my-class*
(make-instance 'standard-class
:name 'my-class
:direct-slots '((:name x :readers (get-x) :writers ((setf get-x))))
:direct-superclasses (list (find-class 'standard-object))))
I'm looking for a simple way to return a new structure which is a copy of an existing one with some fields changed, without modifying the original.
I get that you can use setf to change the data in one of the fields, like so:
[1]> (defstruct foo bar)
FOO
[1]> (defvar quux (make-foo :bar 12))
QUUX
[1]> (foo-bar quux)
12
[1]> (setf (foo-bar quux) 15)
15
[1]> (foo-bar quux)
15
But as I stated, this essentially destroys the original data, which isn't what I'm going for.
I could of course do something like this:
(defstruct foo bar baz) ; define structure
(defvar quux (make-foo :bar 12 :baz 200)) ; make new instance
(defvar ping (copy-foo quux)) ; copy instance
(setf (foo-bar ping) 15) ; change the bar field in ping
But it seems more like a work-around than anything.
In Erlang you can do something like this:
-record(foo, {bar, baz}). % defines the record
example() ->
Quux = #foo{bar = 12, baz = 200}, % creates an instance of the record
Ping = Quux#foo{bar = 15}. % creates a copy with only bar changed
No data modified.
PS Yes I'm aware that Common Lisp isn't Erlang; but Erlang made it convenient to work with records/structures immutably, and since functional style is encouraged in Common Lisp, it would be nice if there was a similar option available.
Erlang records are similar to Prolog structures. The Prolog I know implements this as a predicate named update_struct/4 which admits a macro expansion: it takes a type parameter and expands into two unifications. The same kind of processing is done in Erlang, according to the documentation. In Common Lisp, we don't need to pass the type explicitly, as shown with the following update-struct function:
(defun update-struct (struct &rest bindings)
(loop
with copy = (copy-structure struct)
for (slot value) on bindings by #'cddr
do (setf (slot-value copy slot) value)
finally (return copy)))
Example
CL-USER> (defstruct foo bar baz)
FOO
CL-USER> (defparameter *first* (make-foo :bar 3))
*FIRST*
CL-USER> (defparameter *second* (update-struct *first* 'baz 2))
*SECOND*
CL-USER> (values *first* *second*)
#S(FOO :BAR 3 :BAZ NIL)
#S(FOO :BAR 3 :BAZ 2)
Specification
Rainer Joswig kindly pointed out that:
There is one thing which is undefined by the standard: using SLOT-VALUE on structure objects is undefined. But it should work on most implementations, as they provide this feature. The only implementation where it does not seem to work is GCL.
Indeed, the HyperSpec says about SLOT-VALUE:
Note in particular that the behavior for conditions and structures is not specified.
An implementation might behave differently if the structured is backed by a list or vector (see the ̀:TYPE option). Anyway, if you need to be portable you'd better use classes.
This topic was also explained in detail by Rainer in common lisp: slot-value for defstruct structures.
Other immutable data-structures
Consider also using property lists, which play nicely with an immutable approach.
Say your initial list x is:
(:a 10 :b 30)
Then (list* :b 0 x) is the following list:
(:b 0 :a 10 :b 30)
... where the most recent value associated with :b shadows the ones after (see GETF).
Loop details
The bindings list is a property list, with alternation of keys and values (like keyword parameters).
In the LOOP expression above, I am iterating over the list of bindings using ON, which means that I am considering each sublist instead of each element. In other words (loop for x on '(a b c d)) successively binds x to (a b c d), (b c d), (c d) and finally (c).
However, since I provide a custom BY argument, the next element is computed using CDDR, instead of the default CDR (so, we advance by two cells instead of by one).
That allows me to consider each pair of key/value elements in the list, and bind them to slot and value thanks to the destructuring syntax.
Why there is no syntax sugar for funcall? We need it a lot. Won't it be great to write something like (&#do-something arg0 arg1 arg2) instead of (funcall do-something arg0 arg1 arg2) Why not add something like Ruby's &:method notation? Is there something already in the language?
There's nothing like that built into the language; you can easily assign the function to an additional name though, and use that. E.g., if you want to use &, you can:
CL-USER> (setf (symbol-function '&) (symbol-function 'funcall))
#<FUNCTION FUNCALL>
CL-USER> (&'list 1 2 3)
(1 2 3)
CL-USER> (&'cons 'x 'y)
(X . Y)
(There was a recent question on Stack Overflow about different ways to do that first line: How to stop evaluating lisp form when passed as function parameter?.)
Won't it be great to write something like (&#do-something arg0 arg1 arg2) instead of (funcall do-something arg0 arg1 arg2)?
Probably not. Common Lisp is a language that prefers expressive names for functions and macros. The name funcall is recognized, and it makes it clear that there's an indirect function call happening. Why would we want to obscure that? Evidently most people find funcall has the right balance between "short enough to write" and "long enough to be descriptive".
Why there is no syntax sugar for funcall?
You might call macros "syntax sugar" in Common Lisp, but there's no need for it here. Funcall is a function, not a special form or macro, so it's really very easy to alias it with another name, as shown above. The fact that most people don't do this should say something about how desirable it is.
There is no syntax for funcall, because we don't need it a lot (or else, define "we"). I mean, in a Lisp-2, such as Common Lisp, that's the trade-off, and unless you're doing some heavy lambda calculus, you get used to it.
If you really want to use a more succint syntax, you can define a dispatch macro character:
(set-dispatch-macro-character
#\# #\&
#'(lambda (stream subchar arg)
(let ((args-var (gensym)))
`(lambda (&rest ,args-var)
(declare (dynamic-extent ,args-var))
(apply ,(read stream t nil t) ,args-var)))))
(let ((my-function #'max))
(#&my-function 1 3 2))
Check if your compiler will optimize lambda forms and dynamic-extent &rest arguments passed to apply.
I advise against defining the single character & as a macro character, because it's a constituent character mostly used in the symbols &optional, &rest, &key, &allow-other-keys, &aux, &whole, &body and &environment.
If you're inclined to black magic:
(defun black-magic (stream sub-char numarg)
(declare (ignore sub-char numarg))
`(funcall ,#(read stream)))
(set-dispatch-macro-character
#\# #\! #'black-magic)
Rough example:
CL-USER> (defun foo (fn x y z)
#!(fn x y z))
FOO
CL-USER> (foo #'* 1 2 3)
6
CL-USER> (foo #'+ 1 1 1)
3
(It's better to use apply however... but it's even better to keep things simple and use nothing of this sort.)
Of couse we anyone can define something like that by reader macros, but i think it's not a very good idea to do such thing if you expecting than someone will read your code somtime.
Actually this sort of reader macro is syntactic sugar you're asking for. Do you reject your own idea now? Every time, when you use non-conventional syntactic sugar, you probably make things worse for your future code-readers.