I often want to output lists and also print their position in the list e.g.
'(a b c) would become "1:A 2:B 3:C"
As FORMAT already supports iterating over a given list, I was wondering whether it also provides some sort of counting directive?
E.g. the FORMAT string could look like this: "~{~#C:~a~}" whereas ~#C would be the counter.
If you want a boring answer, here you go:
(format T "~:{~a:~a ~}" (loop for i from 0 for e in '(x y z) collect (list i e)))
And now for a more interesting one! Similarly to #Renzo's answer, this uses the Tilde directive to achieve its work.
(defvar *count* 0)
(defvar *printer* "~a")
(defun iterate-counting (stream arg c at)
(declare (ignore c))
(let ((*count* (if at -1 0)))
(destructuring-bind (*printer* delimiter &rest args) arg
(format stream (format NIL "~~{~~/iterate-piece/~~^~a~~}" delimiter) args))))
(defun iterate-piece (stream arg &rest dc)
(declare (ignore dc))
(incf *count*)
(format stream *printer* *count* arg))
This uses two special variables to make it both thread-safe and to allow nesting. I won't say that it's handy to use though. The first item of the argument to list has to be a format string that denotes how to print the argument and counter. For such a format list, the first argument is the counter, and the second argument is the actual item to list. You can switch those around if you need to using the asterisk directive. The second item should be a string to print as the delimiter between each item. Finally, the rest of the list has to be the actual items to print.
(format T "~/iterate-counting/" '("~a:~a" " " x y z))
=> 1:X 2:Y 3:Z
(format T "~/iterate-counting/" '("~a:~/iterate-counting/" " " ("~a>~a" "," 0 1 2) ("~a>~a" "," a b c) ("~a>~a" "," x y z)))
=> 1:1>0,2>1,3>2 2:1>A,2>B,3>C 3:1>X,2>Y,3>Z
If you want it to start counting from zero, add an # modifier to the iterate-counting:
(format T "~#/iterate-counting/" '("~a:~a" " " x y z))
=> 0:X 1:Y 2:Z
I wouldn't personally use this, as it's far less than obvious what is going on if you stumble across the directive uninitiated. It would probably be much less confusing for the potential future reader to write a tailored function for this, than trying to ab/use format.
A not so simple but reusable way of producing a numbered list is by using the ~/ directive (Tilde Slash: Call Function) with a user-defined function. For instance:
(let ((position 0))
(defun init-pos(str arg col at)
(declare (ignore str arg col at))
(setf position 0))
(defun with-pos(str arg col at)
(declare (ignore col at))
(format str "~a:~a" (incf position) arg)))
and then write format like this one:
(format nil "~/init-pos/~{~/with-pos/~^ ~}" nil '(a b c))
Note that, as said in a comment, this solution has two limitations:
You cannot use it if you need to format objects in concurrent threads, and
you cannot use it for nested lists.
Related
I'm trying to implement the macro-function OR in Lisp
My attempt:
(defmacro or2 (test &rest args)
`(if ,test ,test (if (list ,#args) (or2 ,#args) nil)) )
However, if I test with something like this:
(or2 (print 1) 2 )
1
1
1
Whereas with the default OR:
(or (print 1) 2)
1
1
I understand that this is because of my two ,test at the beginning of my if clause, but I don't see how i could avoid it. How could I avoid applying twice the test effects ?
How would you solve the problem of side-effects if you had to code it by hand?
(or2 (print 1) 2)
Intermediate variable
Most probably, you would do this:
(let ((value (print 1)))
(if value value 2))
You need to define a local variable which holds the value of the first expression, so that later you can reference the variable instead of re-evaluating the same expression more than once.
But what if you already have a variable named value in the lexical context where you expand the code? What if, instead of 2, you were referencing that other value? This problem is named variable capture.
Gensym
In Common Lisp, you introduce a fresh symbol, that is guaranteed to not be already bound to anything, using GENSYM.
(let ((symbol (gensym)))
`(let ((,symbol ,test))
(if ,symbol ,symbol ...)))
Recursive expansion
(list ,#args)
The above is the same as writing directly ,args.
But you are confusing macroexpansion and execution times. If you inject args directly in the code, it will be evaluated (most likely, this is going to fail as a bad function call). What you want instead is to test if args is non-null during macroexpansion.
Besides, you should probably first test if your list of expression contains more than one element, in order to simplify the generated code.
Roughly speaking, you have to take into account the following cases:
(or2) is nil
(or2 exp) is the same as exp
(or2 exp &rest args) is the same as the following, where var is a fresh symbol:
`(let ((,var ,exp))
(if ,var ,var (or2 ,#args)))
Please make use of macroexpand-1:
(macroexpand-1 '(or2 (print 1) 2))
; ==> (if (print 1) (print 1) (if (list 2) (or2 2) nil)) ;
; ==> t
With macros you wish the order of evaluation to be expected and you wish expressions to only be evaluated once. Thus the expansion should have been something like this:
(let ((tmp (print 1)))
(if tmp
tmp
(or2 2)))
And tmp should be a symbol generated by gensym. Also when args is nil you should expand or2 to only test:
(defmacro or2 (test &rest args)
(if (endp args)
test
(let ((tmp (gensym "tmp")))
`(let ((,tmp ,test))
(if ,tmp
,tmp
(or2 ,#args))))))
you can make use of macros to simplify this:
(defmacro or2 (test &rest args)
(if (endp args)
test
(once-only (test)
`(if ,test
,test
(or2 ,#args)))))
I've been struggling with this for two days now, and I can't find the answer.
What I want is to define three variables, a, b, and c each with a value of 0.
Naive:
(dolist (lbl '(a b c)) (defvar lbl 0))
Doesn't do what I want. a, b, and c remain undefined, and lbl now has a value of 0.
I think I may understand why this can't work: defvar is a macro, not a function, and as such I am passing it the form lbl, not the current value of label (which is a, b, c in turn). I think.
But in the resulting macroexpansion, shouldn't lbl eventually be linked-up(?) or evaluated(?) to the value I'm intending? Obviously not, either because it can't be done or I'm doing it wrong.
I want to understand:
How to make this work: (dolist (lbl '(a b c)) (defvar lbl 0))
What's going wrong under the hood. I have a feeling it has something to do with symbols or the mechanics of the quote operator.
Here are a few options:
With eval, by building a defvar expression:
(dolist (lbl '(a b c))
(eval `(defvar ,lbl 0))
With proclaim and setf of symbol-value (note: set is deprecated, since 1994 for what it's worth):
(dolist (lbl '(a b c))
(proclaim `(special ,lbl))
(setf (symbol-value lbl) 0))
This is actually mostly what defvar does (see notes in the linked page), but each Lisp implementation usually also records source file location, as they do for other defining macros.
Under the hood, defvar is a macro that makes the variable special (i.e. with dynamic extent bindings in the current dynamic environment; note: there's no portable undoing for this!), and optionally initializes it if it's not yet bound.
The fact that it's a macro means it doesn't evaluate its arguments, so it can take the variable name literally, and it does so. As such, (defvar lbl 0) will define the variable lbl, not the symbol stored in a lbl variable.
The fact that it optionally initializes the variable means that the initializing expression will not even be evaluated if the variable is boundp. So, its secondary effects won't happen if the variable is already initialized. This might or might not be expected.
Note that this expression isn't actually evaluated at macro-expansion time, it's left for evaluation when the expansion is evaluated, which in a REPL means right after macro expansion (and possibly after compilation, depending on the Lisp implementation; read more about evaluation and compilation, it's quite interesting).
Similar:
(dolist (lbl '(a b c))
(let ((lbl 0))
(print lbl)))
Why is lbl 0 and not some of a, b, c?
Because LET binds the symbol lbl and not its value.
Similar with (DEFVAR FOO 3).
Imagine following code:
(DEFVAR FOO 3)
(LET ((FOO 3)) ...)
Now, if we compile this code, the Lisp compiler recognizes the DEFVAR declaration and now knows that FOO is a special global variable. Thus in the let form FOO will be dynamically bound.
Compare this code:
(dolist (v '(FOO)) (eval `(DEFVAR ,v 3)))
(LET ((FOO 3)) ...)
The compiler won't see the DEFVAR and does not know that it should be a global special variable. In the LET form, FOO will have a lexical binding.
Thus DEFVAR needs to be a macro which knows the symbol at compile time (!) and which expands into a form that informs the compiler that the symbol is a special global variable. The form also sets the value when executed.
Thus the best way to create multiple DEFVAR declarations from a list of variables is to write a macro, which expands into a PROGN form with multiple DEFVARs. Inside the PROGN, the compiler will still recognize them.
CL-USER 21 > (pprint (macroexpand '(defvar* (a b c) 0)))
(PROGN (DEFVAR A 0) (DEFVAR B 0) (DEFVAR C 0))
Implemented as:
(defmacro defvar* (vars initial-value)
`(progn
,#(loop for var in vars
do (check-type var symbol)
collect `(defvar ,var ,initial-value))))
Note that it makes sense to check that the variables are really provided as symbols.
defvar is a special form which makes sure the symbol of it's first argument is a bound variable. If the variable is not bound the evaluated expression of the second argument becomes the bound variables value. Thus:
(defvar *x* 10) ; if *x* was not bound it's now 10
(defvar *x* 20) ; since *x* is defined nothing happens
Notice that *x* is not evaluated but is used unevaluated. In order to get the same functionality by using a variable that evaluates to a symbol which you want to exist as a variable in global scope you need to do something like this:
(defvar b 10)
(dolist (lbl '(a b c))
(when (not (boundp lbl))
(setf (symbol-value lbl) 0)))
Still, neither of the ones not already bound becomes special like with defvar, but at least you get the same behaviour:
(list a b c) ; => (0 10 0)
Perhaps you should just do:
(defvar *a* 0)
(defvar *b* 0)
(defvar *c* 0)
If you have a lot of variables you need to do this with you can do:
(defmacro defvars (lst value)
(loop :for e :in lst
:collect `(defvar ,e ,value) :into result
:finally (return (cons 'progn result))))
(defparameter *w* 10)
(defvars (*q* *w* *e*) 1)
(list *q* *w* *e* ; ==> (1 10 1)
Also, it's really important to earmuff your global variables. Once special it will follow dynamic binding. eg.
(defun test ()
(let ((*b* 15))
(test2)))
(defun test2 ()
*b*)
(test) ; ==> 15
Reimplementing DEFVAR
You can approximate the behavior of defvar with a function like this:
(defun %defvar (symbol value documentation)
"Define a global special variable.
symbol---a symbol
value---nil or a function of zero arguments
documentation---nil or a documentation string
returns symbol
Proclaim SYMBOL globally as a special variable. If VALUE is non-nil,
then if SYMBOL is not already bound, SYMBOL is assigned the value
returned by calling VALUE. DOCUMENATION is assigned as the
documentation of type variable to for SYMBOL."
(prog1 symbol
;; make it globally special
(proclaim (list 'special symbol))
;; if a value is provided, and symbol isn't
;; already bound, set its value to the result
;; of calling the value-function
(when (not (null value))
(unless (boundp symbol)
(setf (symbol-value symbol)
(funcall value))))
;; set the documentation
(setf (documentation symbol 'variable) documentation)))
Then you can do, e.g.,
CL-USER> (%defvar '*the-answer* (lambda () 42) "the answer")
*THE-ANSWER*
CL-USER> *the-answer*
42
CL-USER> (documentation '*the-answer* 'variable)
"the answer"
And with your original code, you could do something like:
(dolist (lbl '(a b c)) (%defvar lbl (lambda () 0)))
Now, how does this relate to what defvar actually does? Well, you could now implement a defvar like macro by doing:
(defmacro define-var (symbol &optional (value nil value-p) documentation)
`(%defvar
',symbol
,(if value-p `(lambda () ,value) 'nil)
,documentation))
This expands as we'd expect:
CL-USER> (macroexpand-1 '(define-var *the-answer* 42 "the answer"))
(%DEFVAR '*THE-ANSWER* (LAMBDA () 42) "the answer")
You can actually use macroexpand to look at what an implementation does, too. E.g., in SBCL:
CL-USER> (macroexpand-1 '(defvar *the-answer* 42 "the answer"))
(PROGN
(EVAL-WHEN (:COMPILE-TOPLEVEL) (SB-IMPL::%COMPILER-DEFVAR '*THE-ANSWER*))
(SB-IMPL::%DEFVAR '*THE-ANSWER* (UNLESS (BOUNDP '*THE-ANSWER*) 42) 'T
"the answer" 'T (SB-C:SOURCE-LOCATION)))
This isn't too much different from what we wrote above, though it's handling the non-evaluation of the form when the variable is already bound in a slightly different way, and it's also got some handling for recording a source location. The general idea is the same, though.
Why things don't get "linked up"
But in the resulting macroexpansion, shouldn't lbl eventually be
linked-up(?) or evaluated(?) to the value I'm intending?
The original code is:
(dolist (lbl '(a b c)) (defvar lbl 0))
We can macroexpand this to see what it becomes (in SBCL):
CL-USER> (macroexpand '(dolist (lbl '(a b c)) (defvar lbl 0)))
(BLOCK NIL
(LET ((#:N-LIST1022 '(A B C)))
(TAGBODY
#:START1023
(UNLESS (ENDP #:N-LIST1022)
(LET ((LBL (TRULY-THE (MEMBER C B A) (CAR #:N-LIST1022))))
(SETQ #:N-LIST1022 (CDR #:N-LIST1022))
(TAGBODY (DEFVAR LBL 0)))
(GO #:START1023))))
NIL)
T
Now, we can still see LBL in two places, including in (defvar LBL 0). So why don't things get "matched up"? To see that, we need to remember that the defvar inside the let will also be macroexpanded. To what? This:
CL-USER> (macroexpand '(DEFVAR LBL 0))
(PROGN
(EVAL-WHEN (:COMPILE-TOPLEVEL) (SB-IMPL::%COMPILER-DEFVAR 'LBL))
(SB-IMPL::%DEFVAR 'LBL (UNLESS (BOUNDP 'LBL) 0) 'T NIL 'NIL
(SB-C:SOURCE-LOCATION)))
But now we see that SBCL's internals are getting the symbol named "LBL"; the call (sb-impl::%defvar 'lbl …) is calling the function sb-impl::%defvar with the symbol lbl, and there's no connection between that symbol and the lexical variable that happens to be represented in the source by the same symbol. After all, if you write:
CL-USER> (let ((a 89))
(list 'a a))
(A 89)
You want to be able to get the symbol a and the number 89, right? The macroexpansion of defvar includes a call to a function with the quotation of one of the arguments to macro.
Is there a repeat directive for (format) in Common lisp, something like(I know this won't work):
(format t "~5C" #\*)
Just wondering if there isn't a more elegant way to do it than this:(from rosettacode
)
(defun repeat-string (n string)
(with-output-to-string (stream)
(loop repeat n do (write-string string stream))))
(princ (repeat-string 5 "hi"))
(defun write-repeated-string (n string stream)
(loop repeat n do (write-string string stream)))
(write-repeated-string 5 "hi" *standard-output*))
Generally you can use the format iteration:
(format t "~v#{~A~:*~}" 5 "hi")
~A can output all kinds of items, not just characters. For more information see uselpa's linked answers.
Above takes the iteration number from the first argument. Thus the v behind the tilde.
The rest of the arguments will be consumed by the iteration. Thus the #.
Inside the iteration we go back one element. Thus ~:*.
It's similar to (format t "~v{~A~:*~}" 5 '("hi")), which might be simpler to understand.
I want my function to print each item in the list and sublist without quotes and return the number of items. The output of the list also needs to be in order, but my function is printing in reverse. I'm not sure why, is there any reasons why? Any suggestions to how I can recursively count the number of items and return that number? In addition why is the last item printed is supposed to be 9.99 instead of 100.999?
Edit: Thanks for the help so far. Just last question: Is there a way to make any output like DAY to be in lower case (day), or is that something that can't be done?
My function:
(defun all-print (inlist)
(cond
((not (listp inlist))
(format t "Error, arg must be a list, returning nil")
())
((null inlist) 0)
((listp (car inlist))
(ffn (append (car inlist)(cdr inlist))))
(t
(format t "~a " (car inlist) (ffn (cdr inlist))))))
My output example:
CL-USER 1 > (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
100.999 -5.9 DAY -10 9 3 night 5
NIL
What it's suppose to output example:
5 night 3 9 -10 day -5.9 9.99 ;print
8 ;returns
It looks like all-print is supposed to be called ffn, since it looks like those are supposed to be recursive calls. In the rest of this answer, I'm just going to use ffn since it's shorter.
Why the output is in reverse
At present, your final cond clause makes the recursive call before doing any printing, because your recursive call is an argument to format:
(format t "~a " (car inlist) (ffn (cdr inlist)))
; ------------ -----------------
; 3rd 4th
All the arguments to format, including the 4th in this case, are evaluated before format is called. The 4th argument here will print the rest of the list, and then format will finally print the first element of the list. Your last cond clause should do the printing, and then make the recursive call:
(cond
…
(t
(format t "~a " (car inlist))
(ffn (cdr inlist))))
Why you get 100.999 rather than 9.99
You're getting 100.999 in your output rather than 9.99 (or something close to it) because the value of (* 100.999) is simply the value of 100.999. I'm guessing that you wanted (* 10 0.999) (note the space between 10 and 0.99). That still won't be quite 9.99 because of floating point arithmetic, though, but it will be close.
How to get the number of elements printed
uselpa's answer provides a good solution here. If you're supposed to return the number of elements printed, then every return value from this function should be a number. You have four cases,
not a list — returning nil is not a great idea. If this can't return a number (e.g., 0), then signal a real error (e.g., with (error "~A is not a list" inlist).
inlist is empty — return 0 (you already do)
(car inlist) is a list — here you make a recursive call to ffn. Since the contract says that it will return a count, you're fine. This is one of the reasons that it's so important in the first case (not a list) that you don't return a non-number; the contract depends on every call that returns returning an number.
In the final case, you print one item, and then make a recursive call to ffn. That recursive call returns the number of remaining elements that are printed, and since you just printed one, you need to add one to it. Thus the final cond clause should actually be something like the following. (Adding one to something is so common that Common Lisp has a 1+ function.)
(cond
…
(t
(format t "~a " (car inlist))
(1+ (ffn (cdr inlist))))) ; equivalent to (+ 1 (ffn (cdr inlist)))
A more efficient solution
We've addressed the issues with your original code, but we can also ask whether there are better approaches to the problem.
Don't append
Notice that when you have input like ((a b c) d e f), you create the list (a b c d e f) and recurse on it. However, you could equivalently recurse on (a b c) and on (d e f), and add the results together. This would avoid creating a new list with append.
Don't check argument types
You're checking that the input is a list, but there's really not much need to do that. If the input isn't a list, then using list processing functions on it will signal a similar error.
A new version
This is somewhat similar to uselpa's answer, but I've made some different choices about how to handle certain things. I use a local function process-element to handle elements from each input list. If the element is a list, then we pass it to print-all recursively, and return the result of the recursive call. Otherwise we return one and print the value. (I used (prog1 1 …) to emphasize that we're returning one, and printing is just a side effect. The main part of print-all is a typical recursion now.
(defun print-all (list)
(flet ((process-element (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x)))))
(if (endp list)
0
(+ (process-element (first list))
(print-all (rest list))))))
Of course, now that we've pulled out the auxiliary function, the iteration is a bit clearer, and we see that it's actually a case for reduce. You might even choose to do away with the local function, and just use a lambda function:
(defun print-all (list)
(reduce '+ list
:key (lambda (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x))))))
Here's my suggestion on how to write this function:
(defun all-print (lst)
(if (null lst)
0 ; empty list => length is 0
(let ((c (car lst))) ; bind first element to c
(if (listp c) ; if it's a list
(+ (all-print c) (all-print (cdr lst))) ; recurse down + process the rest of the list
(progn ; else
(format t "~a " c) ; not a list -> print item, then
(1+ (all-print (cdr lst)))))))) ; add 1 and process the rest of the list
then
? (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
5 night 3 9 -10 DAY -5.9 100.999
8
I want to convert ("USERID=XYZ" "USERPWD=123") to "USERID=XYZ&USERPWD=123". I tried
(apply #'concatenate 'string '("USERID=XYZ" "USERPWD=123"))
which will return ""USERID=XYZUSERPWD=123".
But i do not know how to insert '&'? The following function works but seems a bit complicated.
(defun join (list &optional (delim "&"))
(with-output-to-string (s)
(when list
(format s "~A" (first list))
(dolist (element (rest list))
(format s "~A~A" delim element)))))
Use FORMAT.
~{ and ~} denote iteration, ~A denotes aesthetic printing, and ~^ (aka Tilde Circumflex in the docs) denotes printing the , only when something follows it.
* (format nil "~{~A~^, ~}" '( 1 2 3 4 ))
"1, 2, 3, 4"
*
This solution allows us to use FORMAT to produce a string and to have a variable delimiter. The aim is not to cons a new format string for each call of this function. A good Common Lisp compiler also may want to compile a given fixed format string - which is defeated when the format string is constructed at runtime. See the macro formatter.
(defun %d (stream &rest args)
"internal function, writing the dynamic value of the variable
DELIM to the output STREAM. To be called from inside JOIN."
(declare (ignore args)
(special delim))
(princ delim stream))
(defun join (list delim)
"creates a string, with the elements of list printed and each
element separated by DELIM"
(declare (special delim))
(format nil "~{~a~^~/%d/~:*~}" list))
Explanation:
"~{ iteration start
~a print element
~^ exit iteration if no more elements
~/%d/ call function %d with one element
~:* move one element backwards
~}" end of iteration command
%d is just an 'internal' function, which should not be called outside join. As a marker for that, it has the % prefix.
~/foo/ is a way to call a function foo from a format string.
The variables delim are declared special, so that there can be a value for the delimiter transferred into the %d function. Since we can't make Lisp call the %d function from FORMAT with a delimiter argument, we need to get it from somewhere else - here from a dynamic binding introduced by the join function.
The only purpose of the function %d is to write a delimiter - it ignores the arguments passed by format - it only uses the stream argument.
Melpa hosts the package s ("The long lost Emacs string manipulation library"), which provides many simple string utilities, including a string joiner:
(require 's)
(s-join ", " (list "a" "b" "c"))
"a, b, c"
For what it's worth, very thinly under the hood, it's using a couple lisp functions from fns.c, namely mapconcat and identity:
(mapconcat 'identity (list "a" "b" "c") ", ")
"a, b, c"
A bit late to the party, but reduce works fine:
(reduce (lambda (acc x)
(if (zerop (length acc))
x
(concatenate 'string acc "&" x)))
(list "name=slappy" "friends=none" "eats=dogpoo")
:initial-value "")
Assuming a list of strings and a single character delimiter, the following should work efficiently for frequent invocation on short lists:
(defun join (list &optional (delimiter #\&))
(with-output-to-string (stream)
(join-to-stream stream list delimiter)))
(defun join-to-stream (stream list &optional (delimiter #\&))
(destructuring-bind (&optional first &rest rest) list
(when first
(write-string first stream)
(when rest
(write-char delimiter stream)
(join-to-stream stream rest delimiter)))))
With the newish and simple str library:
(ql:quickload "str")
(str:join "&" '("USERID=XYZ" "USERPWD=123"))
It uses format like explained in the other answers:
(defun join (separator strings)
" "
(let ((separator (replace-all "~" "~~" separator)))
(format nil
(concatenate 'string "~{~a~^" separator "~}")
strings)))
(author of it, to make simple things like this simple).