I would like to define a function to-string that does the opposite of the following.
> (read-from-string "(foo a b)")
(FOO A B) ;
The functions write-to-string and prin1-to-string do what you want:
> (read-from-string "(foo \"Hi\" 17)")
(FOO "Hi" 17) ;
> (prin1-to-string '(FOO "Hi" 17))
"(FOO \"Hi\" 17)"
> (write-to-string '(FOO "Hi" 17))
"(FOO \"Hi\" 17)"
The function write-to-string additionally takes keyword arguments that allow you to adjust the result:
> (write-to-string '(FOO "Hi" 17) :case :downcase)
"(foo \"Hi\" 17)"
This appears to work
(with-output-to-string (s)
(princ '(1 2 3) s))
Related
I want to select from a list of functions. And apply a choosen function to arguments.
(defvar fn '(#'(lambda (x) (* x x)) #'(lambda (x) (+ x x))))
(apply (nth 1 fn) '(5))
Above code does not work what could be wrong?
If you use Lisp one can interactively explore these data structures:
CL-USER 50 > '(#'(lambda (x) (* x x)) #'(lambda (x) (+ x x)))
((FUNCTION (LAMBDA (X) (* X X)))
(FUNCTION (LAMBDA (X) (+ X X))))
Above is a list. What type are the elements:
CL-USER 51 > (mapcar #'type-of *)
(CONS CONS)
Above says that the elements are not functions, but cons cells.
We now evaluate the list elements:
CL-USER 52 > (mapcar #'eval **)
(#<anonymous interpreted function 40600010FC>
#<anonymous interpreted function 406000112C>)
What type are these elements of? Now they are functions:
CL-USER 53 > (mapcar #'type-of *)
(FUNCTION FUNCTION)
fn is not a list of functions. Since you quoted the list, none of the function expressions are evaluated. So you just have a list of lists of the form (FUNCTION (LAMBDA (X) ...)).
Use list to make the list and evaluate all the arguments:
(defvar fn (list #'(lambda (x) (* x x)) #'(lambda (x) (+ x x))))
Or use backquote and comma:
(defvar fn `(,#'(lambda (x) (* x x)) ,#'(lambda (x) (+ x x))))
'(#'(lambda (x) (* x x)) #'(lambda (x) (+ x x)))) is a quoted expression. fn is a list of symbols in your example.
You actually want the lambdas to be evaluated to functions so you would remove the quote and write:
(defvar *fn* (list (lambda (x) (* x x)) (lambda (x) (+ x x))))
Now each function object can indeed be used as argument to apply:
(apply (car *fn*) (list 3))
=> 9
funcall also exists. See if you can understand how it differs from apply by reading the HyperSpec. You would call it like this:
(funcall (cadr *fn*) 3)
=> 6
In Common Lisp I can define a two-level macro and expand the macro like this:
(defmacro calc (a op b)
(list op a b))
(defmacro twice (x)
(list 'calc x '+ x))
(twice 10)
(macroexpand-1 '(twice 10))
(macroexpand '(twice 10))
Output:
20
(CALC 10 + 10)
(+ 10 10)
Now I am trying to do the same thing in MIT Scheme:
(define-syntax calc
(syntax-rules ()
((_ a op b)
(op a b))))
(define-syntax twice
(syntax-rules ()
((_ x)
(calc x + x))))
(twice 10)
How can I do the equivalent of macroexpand-1 and macroexpand in MIT Scheme?
In Racket, macroexpand would be
(syntax->datum
(expand-to-top-form '(twice 10)))
;; '(+ 10 10)
and macroexpand-1 would be
(syntax->datum (expand-once '(twice 10)))
;; '(calc 10 + 10)
There are papers for macro-debugging in scheme by M. Felleisen.
See here.
I'm looking for a way to modify a property value in a property list by multiplying it with a given factor similar to using incf for adding to a value.
With incf I could say:
(let ((seq '(:x 10 :y 3)))
(incf (getf seq :y) 3)
seq)
-> (:x 10 :y 5)
Using a macro I could obtain the result in the following way, but this uses getf twice:
(defmacro multf (place val)
`(setf ,place (* ,place ,val)))
(let ((seq '(:x 10 :y 3)))
(multf (getf seq :y) 2)
seq)
-> (:x 10 :y 6)
How would I do this so that I could obtain the same result using getf only once?
Maybe there are packages with this functionality, but I couldn't find it in the net. Any help is appreciated! This is no homework, I'm just trying to optimize my code and I'm curious to better understand the language. I read about setf-expanders and compiler-macros, but I don't know whether they apply here and how to make use of them.
but this uses getf twice
the first is a SETF form and the second one is a getter. The first one will be expanded by SETF.
A short definition of multf using define-modify-macro might be:
CL-USER 28 > (define-modify-macro multf (&optional (number 1)) *)
MULTF
CL-USER 29 > (let ((seq '(:x 10 :y 3)))
(multf (getf seq :y) 2)
seq)
(:X 10 :Y 6)
The full expansion in LispWorks looks like this:
(LET ((SEQ '(:X 10 :Y 3)))
(LET* ((#:G1158 :Y))
(LET* ()
(LET ((#:G1157 (* (GETF SEQ #:G1158) 2)))
(LET ((#:|Store-Var-1156| (SYSTEM::PRIMITIVE-PUTF SEQ #:G1158 #:G1157)))
(SETQ SEQ #:|Store-Var-1156|)
#:G1157))))
SEQ)
I would like to set aliases in common lisp(clisp to be exact) for commands that are used a lot, such as "defun" and "lambda" etc, is it possible to do this?
This is actually kind of a duplicate of this question, but I can not comment and the solution does not work for defun or lambda in both sbcl and clisp
Macros:
CL-USER 5 > (setf (macro-function 'dm) (macro-function 'defmethod))
#<Function DEFMETHOD 410009A014>
CL-USER 6 > (dm m1+ ((v vector)) (map 'vector #'1+ v))
#<STANDARD-METHOD M1+ NIL (VECTOR) 4130003913>
CL-USER 7 > (m1+ #(1 2 3 4))
#(2 3 4 5)
The whole point by macros is to provide a source rewriting service.. Thus I want to give you this and you can make that out of it:
(defmacro df (name (&rest arguments) &body body)
`(defun ,name ,arguments ,#body))
(df test (x) (+ x x))
(test 5) ; ==> 10
We have just shortened the name.. Lets make another one:
(defmacro df1 (name &body body)
`(defun ,name (_) ,#body))
(df1 test (+ _ _))
(test 5) ; ==> 10
And so on...
I need a function that concatenates multiple values into (simple) vector, similar to (concatenate ). However, unlike concatenate, it should be able to handle arguments that are not vectors or sequences.
I.e. it should work like this:
(concat #(1 2) 3) => #(1 2 3)
(concat 1 2 3) => #(1 2 3)
(concat 1 #(2 3 4)) => #(1 2 3 4)
(concat #(1 2) 2 #(3 4 5)) => #(1 2 3 4 5)
How can I do this? I think I've forgotten some trivial lisp construct that makes it possible.
As far as I can tell, concatenate can't do it. and I'm not quite sure how to use make it with macro (there's ,# consturct that inserts list into resulting lisp form, but but I'm not quite sure how to distinguish between non-sequences and sequences in this case).
The reduce approach in the other reply is quadratic in time.
Here is a linear solution:
(defun my-concatenate (type &rest args)
(apply #'concatenate type
(mapcar (lambda (a) (if (typep a 'sequence) a (list a)))
args)))
Since we can compute the length of the sequence, we can allocate the result sequence and then copy the elements into it.
(defun concat (type &rest items)
(let* ((len (loop for e in items
if (typep e 'sequence)
sum (length e)
else sum 1))
(seq (make-sequence type len)))
(loop with pos = 0
for e in items
if (typep e 'sequence)
do (progn
(setf (subseq seq pos) e)
(incf pos (length e)))
else
do (progn
(setf (elt seq pos) e)
(incf pos)))
seq))
CL-USER 17 > (concat 'string "abc" #\1 "def" #\2)
"abc1def2"
Above works well for vectors. A version for lists is left as an exercise.
defun my-concatenate (type &rest vectors)
(reduce (lambda (a b)
(concatenate
type
(if (typep a 'sequence) a (list a))
(if (typep b 'sequence) b (list b))))
vectors))
You can use reduce with a little modification of #'concatenate on your arguments. If one of the arguments is not a sequence, just transform it into a list (concatenate works even with mixed arguments of simple-vectors and lists).
CL-USER> (my-concatenate 'list #(1 2 3) 3 #(3 5))
(1 2 3 3 3 5)
CL-USER> (my-concatenate 'simple-vector #(1 2 3) 3 #(3 5))
#(1 2 3 3 3 5)
CL-USER> (my-concatenate 'simple-vector 1 #(2 3) (list 4 5))
#(1 2 3 4 5)
EDIT: well, you should probably accept the other answer.