Format both an expression and its result without eval - common-lisp

I am trying to format an arbitrary expression, say (+ 2 3), and at the same time, its result, 5.
I have the following:
(defun expr-and-result (expr)
(format t "~a returns ~a~%" expr (eval expr)))
CL-USER> (expr-and-result '(+ 2 3))
(+ 2 3) returns 5
Though it's a simple matter by using eval, I'm curious if this effect can be accomplished without it (because I heard a lot that eval is to be avoided).
I understand that quoting the argument is necessary, because otherwise the given expression will be evaluated as the first step in calling expr-and-result, and only its result could be used inside expr-and-result. Therefore, any possible solution requires the input to be quoted, right?
I thought a bit about macros but I feel like it's the wrong approach to what I am looking for.
Edit: My intent was to construct a simple test-suite, such as:
(progn
(mapcar #'expr-and-result
'((= (my-remainder 7 3) 1)
(= (my-remainder 7 3) 2)))
'end-of-tests)
Outputs:
(= (MY-REMAINDER 7 3) 1) returns T
(= (MY-REMAINDER 7 3) 2) returns NIL
END-OF-TESTS
After reading Paulo's comment, it seems that eval is the shortest and cleanest solution for my purposes.

Here is a simple macro:
(defmacro exec-and-report (form)
`(format t "~S returns ~S~%" ',form ,form))
(macroexpand '(exec-and-report (+ 1 2)))
==>
(FORMAT T "~S returns ~S~%" '(+ 1 2) (+ 1 2)) ;
T
(exec-and-report (+ 1 2))
==>
(+ 1 2) returns 3
NIL
PS. I second #Sylvester's suggestion not to reinvent the wheel

Related

Common Lisp Returning members of a list from one index to another

This is what ive tried till now, but im getting some errors and im kinda confused
What is want to do is:
For example calling (sub-list((2 3 4 5 6) 2 3))
will result in a recursive function like
x = 1,(sub-list('(3 4 5 6) 2 3))
x = 2, cons (car ls) (sub-list((4 5 6) 2 3))
x = 3 ,cons (car ls) (sub-list((5 6) 2 3))
x = 4 , nil since x is now greater than to.
and it should backtrack to return (4 5) something like that
(defvar *x* 1)
(defun sub-list(ls from to)
(cond
((<= *x* from) (sub-list((cdr ls) from to)))
((<= from *x* to)
(let (*x* (+ *x* 1))
cons a (sub-list((cdr ls) from to)))))
((> *x* to) nil)))
As a general recommendation, using a global and special variable to track internal state is not recommended.
As #coredump pointed out in a comment, Sublist in Lisp has an answer pointing in the right direction.
To avoid the special variable, you can (in principle) change the start and end index (as pointed out by #ScottHunter).
This means that you can change your "start accumulating" from (<= *x* from) to (<= from 0) and your "end accumulating" to (<= to 0).
This also requires changing each recursive call to be something like (sub-list (cdr list) (1- from) (1- to)) (and gets rid of the bug in the initial skip phase, where you are not incrementing *x*).

Computing linear combination of vectors in Common Lisp

I'm working on some numerical computations in Common Lisp and I need to compute a linear combination of several vectors with given numerical coefficients. I'm rewriting a piece of Fortran code, where this can be accomplished by res = a1*vec1 + a2*vec2 + ... + an*vecn. My initial take in CL was to simply write each time something like:
(map 'vector
(lambda (x1 x2 ... xn)
(+ (* x1 a1) (* x2 a2) ... (* xn an)))
vec1 vec2 ... vecn)
But I soon noticed that this pattern would recur over and over again, and so started writing some code to abstract it away. Because the number of vectors and hence the number of lambda's arguments would vary from place to place, I figured a macro would be required. I came up with the following:
(defmacro vec-lin-com (coefficients vectors &key (type 'vector))
(let ((args (loop for v in vectors collect (gensym))))
`(map ',type
(lambda ,args
(+ ,#(mapcar #'(lambda (c a) (list '* c a)) coefficients args)))
,#vectors)))
Macroexpanding the expression:
(vec-lin-com (10 100 1000) (#(1 2 3) #(4 5 6) #(7 8 9)))
yields the seemingly correct expansion:
(MAP 'VECTOR
(LAMBDA (#:G720 #:G721 #:G722)
(+ (* 10 #:G720) (* 100 #:G721) (* 1000 #:G722)))
#(1 2 3) #(4 5 6) #(7 8 9))
So far, so good...
Now, when I try to use it inside a function like this:
(defun vector-linear-combination (coefficients vectors &key (type 'vector))
(vec-lin-com coefficients vectors :type type))
I get a compilation error stating essentially that The value VECTORS is not of type LIST. I'm not sure how to approach this. I feel I'm missing something obvious. Any help will be greatly appreciated.
You've gone into the literal trap. Macros are syntax rewriting so when you pass 3 literal vectors in a syntax list you can iterate on them at compile time, but replacing it with a bindnig to a list is not the same. The macro only gets to see the code and it doesn't know what vectors will eventually be bound to at runtime when it does its thing. You should perhaps make it a function instead:
(defun vec-lin-com (coefficients vectors &key (type 'vector))
(apply #'map
type
(lambda (&rest values)
(loop :for coefficient :in coefficients
:for value :in values
:sum (* coefficient value)))
vectors))
Now you initial test won't work since you passed syntax and not lists. you need to quote literals:
(vec-lin-com '(10 100 1000) '(#(1 2 3) #(4 5 6) #(7 8 9)))
; ==> #(7410 8520 9630)
(defparameter *coefficients* '(10 100 1000))
(defparameter *test* '(#(1 2 3) #(4 5 6) #(7 8 9)))
(vec-lin-com *coefficients* *test*)
; ==> #(7410 8520 9630)
Now you could make this a macro, but most of the job would have been done by the expansion and not the macro so basically you macro would expand to similar code to what my function is doing.
Remember that macros are expanded at compile-time, so the expression ,#(mapcar #'(lambda (c a) (list '* c a)) coefficients args) has to be meaningful at compile-time. In this case, all that mapcar gets for coefficients and args are the symbols coefficients and vectors from the source code.
If you want to be able to call vec-lin-com with an unknown set of arguments (unknown at compile-time, that is), you'll want to define it as a function. It sounds like the main problem you're having is getting the arguments to + correctly ordered. There's a trick using apply and map to transpose a matrix that may help.
(defun vec-lin-com (coefficients vectors)
(labels
((scale-vector (scalar vector)
(map 'vector #'(lambda (elt) (* scalar elt)) vector))
(add-vectors (vectors)
(apply #'map 'vector #'+ vectors)))
(let ((scaled-vectors (mapcar #'scale-vector coefficients vectors)))
(add-vectors scaled-vectors))))
This isn't the most efficient code in the world; it does a lot of unnecessary consing. But it is effective, and if you find this to be a bottleneck you can write more efficient versions, including some that can take advantage of compile-time constants.

Recursive Factorial Function in Common-Lisp

Ok, I'm been learning COMMON LISP programming and I'm working on a very simple program to calculate a factorial of a given integer. Simple, right?
Here's the code so far:
(write-line "Please enter a number...")
(setq x (read))
(defun factorial(n)
(if (= n 1)
(setq a 1)
)
(if (> n 1)
(setq a (* n (factorial (- n 1))))
)
(format t "~D! is ~D" n a)
)
(factorial x)
Problem is, when I run this on either CodeChef or Rexter.com, I get a similar error: "NIL is NOT a number."
I've tried using cond instead of an if to no avail.
As a side note, and most bewildering of all, I've seen a lot of places write the code like this:
(defun fact(n)
(if (= n 1)
1
(* n (fact (- n 1)))))
Which doesn't even make sense to me, what with the 1 just floating out there with no parentheses around it. However, with a little tinkering (writing additional lines outside the function) I can get it to execute (equally bewildering!).
But that's not what I want! I'd like the factorial function to print/return the values without having to execute additional code outside it.
What am I doing wrong?
One actually needs to flush the I/O buffers in portable code with FINISH-OUTPUT - otherwise the Lisp may want to read something and the prompt hasn't yet been printed. You better replace SETQ with LET, as SETQ does not introduce a variable, it just sets it.
(defun factorial (n)
(if (= n 1)
1
(* n (factorial (- n 1)))))
(write-line "Please enter a number...")
(finish-output) ; this makes sure the text is printed now
(let ((x (read)))
(format t "~D! is ~D" x (factorial x)))
Before answering your question, I would like to tell you some basic things about Lisp. (Neat fix to your solution at the end)
In Lisp, the output of every function is the "last line executed in the function". Unless you use some syntax manipulation like "return" or "return-from", which is not the Lisp-way.
The (format t "your string") will always return 'NIL as its output. But before returning the output, this function "prints" the string as well.
But the output of format function is 'NIL.
Now, the issue with your code is the output of your function. Again, the output would be the last line which in your case is:
(format t "~D! is ~D" n a)
This will return 'NIL.
To convince yourself, run the following as per your defined function:
(equal (factorial 1) 'nil)
This returns:
1! is 1
T
So it "prints" your string and then outputs T. Hence the output of your function is indeed 'NIL.
So when you input any number greater than 1, the recursive call runs and reaches the end as input 1 and returns 'NIL.
and then tries to execute this:
(setq a (* n (factorial (- n 1))))
Where the second argument to * is 'NIL and hence the error.
A quick fix to your solution is to add the last line as the output:
(write-line "Please enter a number...")
(setq x (read))
(defun factorial(n)
(if (= n 1)
(setq a 1)
)
(if (> n 1)
(setq a (* n (factorial (- n 1))))
)
(format t "~D! is ~D" n a)
a ;; Now this is the last line, so this will work
)
(factorial x)
Neater code (with Lisp-like indentation)
(defun factorial (n)
(if (= n 1)
1
(* n (factorial (- n 1)))))
(write-line "Please enter a number...")
(setq x (read))
(format t "~D! is ~D" x (factorial x))
Common Lisp is designed to be compiled. Therefore if you want global or local variables you need to define them before you set them.
On line 2 you give x a value but have not declared the existence of a variable by that name. You can do so as (defvar x), although the name x is considered unidiomatic. Many implementations will give a warning and automatically create a global variable when you try to set something which hasn’t been defined.
In your factorial function you try to set a. This is a treated either as an error or a global variable. Note that in your recursive call you are changing the value of a, although this wouldn’t actually have too much of an effect of the rest of your function were right. Your function is also not reentrant and there is no reason for this. You can introduce a local variable using let. Alternatively you could add it to your lambda list as (n &aux a). Secondarily your factorial function does not return a useful value as format does not return a useful value. In Common Lisp in an (implicit) progn, the value of the final expression is returned. You could fix this by adding a in the line below your format.
For tracing execution you could do (trace factorial) to have proper tracing information automatically printed. Then you could get rid of your format statement.
Finally it is worth noting that the whole function is quite unidiomatic. Your syntax is not normal. Common Lisp implementations come with a pretty printer. Emacs does too (bound to M-q). One does not normally do lots of reading and setting of global variables (except occasionally at the repl). Lisp isn’t really used for scripts in this style and has much better mechanisms for controlling scope. Secondarily one wouldn’t normally use so much mutating of state in a function like this. Here is a different way of doing factorial:
(defun factorial (n)
(if (< n 2)
1
(* n (factorial (1- n)))))
And tail recursively:
(defun factorial (n &optional (a 1))
(if (< n 2) a (factorial (1- n) (* a n))))
And iteratively (with printing):
(defun factorial (n)
(loop for i from 1 to n
with a = 1
do (setf a (* a i))
(format t “~a! = ~a~%” i a)
finally (return a)))
You can split it up into parts, something like this:
(defun prompt (prompt-str)
(write-line prompt-str *query-io*)
(finish-output)
(read *query-io*))
(defun factorial (n)
(cond ((= n 1) 1)
(t (* n
(factorial (decf n)))))
(defun factorial-driver ()
(let* ((n (prompt "Enter a number: "))
(result (factorial n)))
(format *query-io* "The factorial of ~A is ~A~%" n result)))
And then run the whole thing as (factorial-driver).
Sample interaction:
CL-USER 54 > (factorial-driver)
Enter a number:
4
The factorial of 4 is 24

COND clause with test only

When COND is given only one test clause and nothing else at all it always returns the test result:
CL-USER> (cond (t))
T
CL-USER> (cond ((> 5 10)))
NIL
Isn't COND just a way to write IF statements?
This doesn't hold for this as when rewriting COND with test only:
CL-USER> (if (> 5 1))
error while parsing arguments to DESTRUCTURING-BIND:
too few elements in
((> 5 1))
to satisfy lambda list
(SB-IMPL::TEST SB-IMPL::THEN &OPTIONAL SB-IMPL::ELSE):
between 2 and 3 expected, but got 1
If it is this way then how does COND exactly transform every clause into IF version?
When COND is given only one test clause and nothing else at all it always returns the test result:
That's right. According to the HyperSpec entry on cond:
results---the values of the forms in the first clause whose test-form yields true, or the primary value of the test-form if there are no forms in that clause, or else nil if no test-form yields true.
Isn't COND just a way to write IF statements?
Well, cond is declared to be a macro, and if to be a special operator, so you can think of it that way, although the expansion of cond isn't defined specifically. But if is defined with syntax that requires a then-part, whereas cond isn't. Here's what a cond clause with no forms expands to (in SBCL):
CL-USER> (pprint (macroexpand '(cond ((+ 2 3)))))
(LET ((#:G1013 (+ 2 3)))
(IF #:G1013
#:G1013
(COND)))
The value of the form is saved in a value and then used as the then-part. When there are forms in the clause, they're wrapped in a progn (which returns the value of its last form):
CL-USER> (pprint (macroexpand
'(cond
((= 2 3) 42 78)
((+ 2 3))
((= 4 5) (print 'something-else)))))
(IF (= 2 3)
(PROGN 42 78)
(COND ((+ 2 3)) ((= 4 5) (PRINT 'SOMETHING-ELSE))))

Average using &rest in lisp

So i was asked to do a function i LISP that calculates the average of any given numbers. The way i was asked to do this was by using the &rest parameter. so i came up with this :
(defun average (a &rest b)
(cond ((null a) nil)
((null b) a)
(t (+ (car b) (average a (cdr b))))))
Now i know this is incorrect because the (cdr b) returns a list with a list inside so when i do (car b) it never returns an atom and so it never adds (+)
And that is my first question:
How can i call the CDR of a &rest parameter and get only one list instead of a list inside a list ?
Now there is other thing :
When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there.
My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
EDIT: I know the function only does the + operation, i know i have to divide by the length of the b list + 1, but since i got this error i'd like to solve it first.
(defun average (a &rest b)
; ...
)
When you call this with (average 1 2 3 4) then inside the function the symbol a will be bound to 1 and the symbol b to the proper list (2 3 4).
So, inside average, (car b) will give you the first of the rest parameters, and (cdr b) will give you the rest of the rest parameters.
But when you then recursively call (average a (cdr b)), then you call it with only two arguments, no matter how many parameters where given to the function in the first place. In our example, it's the same as (average 1 '(3 4)).
More importantly, the second argument is now a list. Thus, in the second call to average, the symbols will be bound as follows:
a = 1
b = ((3 4))
b is a list with only a single element: Another list. This is why you'll get an error when passing (car b) as argument to +.
Now there is other thing : When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there. My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
(null b) will only be truthy when b is the empty list. But when you call (average a '()), then b will be bound to (()), that is a list containing the empty list.
Solving the issue that you only pass exactly two arguments on the following calls can be done with apply: It takes the function as well as a list of parameters to call it with: (appply #'average (cons a (cdr b)))
Now tackling your original goal of writing an average function: Computing the average consists of two tasks:
Compute the sum of all elements.
Divide that with the number of all elements.
You could write your own function to recursively add all elements to solve the first part (do it!), but there's already such a function:
(+ 1 2) ; Sum of two elements
(+ 1 2 3) ; Sum of three elements
(apply #'+ '(1 2 3)) ; same as above
(apply #'+ some-list) ; Summing up all elements from some-list
Thus your average is simply
(defun average (&rest parameters)
(if parameters ; don't divide by 0 on empty list
(/ (apply #'+ parameters) (length parameters))
0))
As a final note: You shouldn't use car and cdr when working with lists. Better use the more descriptive names first and rest.
If performance is critical to you, it's probably best to fold the parameters (using reduce which might be optimized):
(defun average (&rest parameters)
(if parameters
(let ((accum
(reduce #'(lambda (state value)
(list (+ (first state) value) ;; using setf is probably even better, performance wise.
(1+ (second state))))
parameters
:initial-value (list 0 0))))
(/ (first accum) (second accum)))
0))
(Live demo)
#' is a reader macro, specifically one of the standard dispatching macro characters, and as such an abbreviation for (function ...)
Just define average*, which calls the usual average function.
(defun average* (&rest numbers)
(average numbers))
I think that Rainer Joswig's answer is pretty good advice: it's easier to first define a version that takes a simple list argument, and then define the &rest version in terms of it. This is a nice opportunity to mention spreadable arglists, though. They're a nice technique that can make your library code more convenient to use.
In most common form, the Common Lisp function apply takes a function designator and a list of arguments. You can do, for instance,
(apply 'cons '(1 2))
;;=> (1 . 2)
If you check the docs, though, apply actually accepts a spreadable arglist designator as an &rest argument. That's a list whose last element must be a list, and that represents a list of all the elements of the list except the last followed by all the elements in that final list. E.g.,
(apply 'cons 1 '(2))
;;=> (1 . 2)
because the spreadable arglist is (1 (2)), so the actual arguments (1 2). It's easy to write a utility to unspread a spreadable arglist designator:
(defun unspread-arglist (spread-arglist)
(reduce 'cons spread-arglist :from-end t))
(unspread-arglist '(1 2 3 (4 5 6)))
;;=> (1 2 3 4 5 6)
(unspread-arglist '((1 2 3)))
;;=> (1 2 3)
Now you can write an average* function that takes one of those (which, among other things, gets you the behavior, just like with apply, that you can pass a plain list):
(defun %average (args)
"Returns the average of a list of numbers."
(do ((sum 0 (+ sum (pop args)))
(length 0 (1+ length)))
((endp args) (/ sum length))))
(defun average* (&rest spreadable-arglist)
(%average (unspread-arglist spreadable-arglist)))
(float (average* 1 2 '(5 5)))
;;=> 3.25
(float (average* '(1 2 5)))
;;=> 2.66..
Now you can write average as a function that takes a &rest argument and just passes it to average*:
(defun average (&rest args)
(average* args))
(float (average 1 2 5 5))
;;=> 3.5
(float (average 1 2 5))
;;=> 2.66..

Resources