Step Eval Common Lisp - lisp

I have been trying to find a method to do a "step" eval. Where I call the a function and it evaluates the most nested list for common lisp.
For example:
'(+ 2 (+ 3 4))
; would eval to:
'(+ 2 7)
In that example it just evaluated 3 + 4 and stopped right there. It did not continue on to eval 2 + 7 like what lisp would normally do.
So I want the code to find the most nested list and eval the most nested list, without evaluating the whole list.
For example:
'(+ 2 3 4 5 (+ 4 5 (- 5 6) 1 (+ 10 8 5 (- 10 11))) 10 7)
It would find the most nested list, (- 10 11), and eval it so:
'(+ 2 3 4 5 (+ 4 5 (- 5 6) 1 (+ 10 8 5 -1)) 10 7)
Again it only evaluates once, and does not evaluate the whole list at once.
Does anybody know how you could go about this to make a step evaluation for the most nested list? To use eval or something to execute the most nested part of the list without evaling the whole list at once? The problem I'm having is that I don't know how to evaluate the most nested list and then put it back together. I don't know how to approach this. Please enlighten me on how a master lisper would do this.

Us use step:
(step (+ 2 (+ 3 4)))
step 1 --> (+ 2 (+ 3 4))
Step 1 [4]> step
step 2 --> 2
Step 2 [5]> step
step 2 ==> value: 2
step 2 --> (+ 3 4)
Step 2 [6]> step
step 3 --> 3
Step 3 [7]> step
step 3 ==> value: 3
step 3 --> 4
Step 3 [8]> step
step 3 ==> value: 4
step 2 ==> value: 7
step 1 ==> value: 9
9
It doesn't do exactly what you want but it is pretty close. The reason is that Common Lisp is required to evaluate the expressions in exactly the order the stepper does it.

The order of evaluation is left-to-right, so it is not exactly right to evaluate the deepest nested list if you want to emulate Common Lisp's behaviour.
You rather have to evaluate the first nested form first. Assuming well-formed input:
(defun step-eval (form)
(let ((sub-index (position-if #'listp form)))
(if sub-index
;; there is a deeper list to step first
(append (subseq form 0 sub-index)
(list (step-eval (nth sub-index form)))
(subseq form (1+ sub-index)))
;; no deeper list, eval this
(eval form))))

Related

Is there a way to get information about a module at read time?

I've since this summer played around with making a toy language in Racket. Every form has a fixed arity and by default applies so parentheses are not needed. eg. + has arity 2 so + 3 + 4 5 is (+ 3 (+ 4 5)) and + + 3 4 5 is (+ (+ 3 4) 5).
To do this I'm storing in the main module the symbols and their arity. The reader doesn't care if it's a special form or procedure, but is there a better way to do this using features from racket? Thus I can import a module metadata and query that instead during parsing?
Here is one way to go from symbol to arity.
#lang racket
(define base-ns (make-base-namespace))
(define (symbol->arity s)
(parameterize ([current-namespace base-ns])
(procedure-arity (namespace-variable-value s))))
(symbol->arity 'cons)

push does not work as I would expect it - why?

I am experiencing a behavior of the push function that I don't get. Maybe someone could explain to me why Lisp behaves this way.
Supposed I define a list as a global variable, and then try to push a new value to it using the following code:
(defparameter *primes* '(3 5 7 11))
(push 2 *primes*)
Then *primes* is now (2 3 5 7 11). So far, so good.
Now I try to do the same thing, but without the *primes* variable, i.e.:
(push 2 '(3 5 7 11))
The result is an error message:
EVAL: 3 is not a function name; try using a symbol instead
Now I have two questions:
Why does this not work? I would expect that push returns the list (2 3 5 7 11), why does this not happen? Where am I wrong?
Apart from that, I don't get the error message. What is Lisp trying to tell me with 3 is not a function name? Of course, 3 is not a function name, but I don't try to call a function named 3 anywhere, do I?
Any help is appreciated :-)
If you read the CL Hyperspec for PUSH, you will read that push expects a place.
A place is something like a variable, a structure slot, a class slot, an array access, or similar. Since Lisp uses linked cons cells for lists, it does not make sense to push something in front of a cons cell, without a reference for that.
So above is simple: we can't push to a direct list.
Why this error message?
This gets a bit complicated...
(push 2 '(3 5 7 11))
Is actually:
(push 2 (quote (3 5 7 11))
A function can be a place, it then needs a corresponding setter function. Here the setter is thought to be (setf quote) - that's right, Common Lisp can sometimes have lists as function names, not only symbols.
If we look at the macroexpansion of above:
? (pprint (macroexpand '(push 2 (quote (3 5 7 11)))))
(LET* ((#:G328 2) (#:G327 (3 5 7 11)) (#:G326 (CONS #:G328 '#:G327)))
#:G327
#:G326
(FUNCALL #'(SETF QUOTE) #:G326 #:G327))
You can see that it tries to call the setter. But it also thinks that (3 5 7 11) is a Lisp form.
I give you an example, where it actually works, but we don't use quote, but a real accessor function:
CL-USER 40 > (let ((v (vector (list (list 'a 'b 'c) (list 'd 'e 'f))
(list (list 1 2 3) (list 4 5 6)))))
(print v)
(push 42 (first (aref v 1)))
(print v)
(values))
#(((A B C) (D E F)) ((1 2 3) (4 5 6)))
#(((A B C) (D E F)) ((42 1 2 3) (4 5 6)))
In above first is the getter and CL knows the corresponding setter. The form (aref v 1) is the call and returns the index 1 element of the vector. We are then pushing to the first list of the element.
Your call has a similar structure and (3 5 7 11) is at a similar position as (aref v 1). The Lisp system says that in (3 4 7 11) then number 3 is not a valid function. Which is correct. But the real error was about the push operation. Since the macro could not detect the error, the error gets later detected in the macro expanded code.
I have found only the emacs lisp manual push, but I guess it behaves similar for Common Lisp
— Macro: push element listname
This macro creates a new list whose car is element and whose cdr is the list specified by listname, and saves that list in listname.
So it seems push is modifying its argument listname, which isn't possible with a literal list. To do what you have in mind, one would use cons instead.
To the second part 3 is not a function name, I would say push, or some function inside it, tries to evaluate the literal list. Evaluating (3 5 7 11) means, call the function 3 with arguments 5 7 11. Hence the error message.
Again from emacs, Ctrl-h f push
push is a Lisp macro in `cl.el'.
(push X PLACE)
Insert X at the head of the list stored in PLACE.
Analogous to (setf PLACE (cons X PLACE)), though more careful about
evaluating each argument only once and in the right order. PLACE may
be a symbol, or any generalized variable allowed by `setf'.
setf in turn allows place to be a
symbolic references such as (car x) or (aref x i)
which explains, why push evaluates the second argument.
I think you need CONS in second case:
(cons 2 '(3 5 7 11)) => (2 3 5 7 11)

remove duplicated lists inside list in lisp [duplicate]

This question already has answers here:
Test if array is inside a list in lisp
(1 answer)
Remove duplicate strings from a list
(1 answer)
Closed 8 years ago.
How do i remove duplicated lists inside a list in common-lisp?
I tried this:
(remove-duplicates '( (1 2 3) (1 2 3)))
But it evaluates to ((1 2 3) (1 2 3)), not ((1 2 3)).
Thanks.
Use the keyword argument :test to specify the function that defines whether or not two items are duplicates of each other. Most lisp functions, including remove-duplicates, use eql to test for equality by default. eql is much stricter than equal, which is what you probably want to be using.
(remove-duplicates '((1 2 3) (1 2 3)) :test #'equal)
This evaluates to '((1 2 3)).
See this post for more detail about the difference between eql and equal.
Try:
(remove-duplicates '((1 2 3) (1 2 3)) :test #'equal)

Using lists with Common LISP

I'm just starting out with LISP, as in, just opened the book, I'm two pages into it. I'm trying to understand what is and what is not an acceptable fn call. Every time I try to execute
(1 2 3 4)
I get an illegal fn call error
same goes for
(cdr (1 2 3 4))
(first (1 2 3 4))
(a b c d)
Are CL programs unable to return lists? How would I go about using these functions or printing a list? I'm using the SLIME implementation if it matters. LISP is very different than anything I've worked with before and I want to be sure I'm getting it conceptually.
You need to quote lists if you are using them as constants. Otherwise, the system will try to call the function 1 on the arguments 2 3 4, which will not work (note that function calls have the same syntax as lists). Your examples should be:
'(1 2 3 4)
(cdr '(1 2 3 4))
(first '(1 2 3 4))
'(a b c d)
Hooo boy.
Look up Practical Common Lisp by Seibel. He's such a nice guy, he put it online for free reading. It's very useful.
Part of the definition of Lisp is this rule:
When a list is seen: Using the first element of the list, apply it to the rest of the list.
But wait: How do you actually enter lists then? There are two functions to do this: QUOTE and LIST.
As an example, let's print a list to the screen on standard out:
(format *standard-output* "~a" '(1 2 3 4))
For format, *standard-output* is aliased to t (well, at least in SBCL!), so usually we see (format t ....

What is WITH-STANDARD-IO-SYNTAX macro for?

The Practical Common Lisp page 25, explains the WITH-STANDARD-IO-SYNTAX as follows. "It ensures that certain variables that affect the behavior of PRINT are set to their standard values".
The usage is as follows.
(with-open-file (...)
(with-standard-io-syntax
(print ...
Should (print) be used in this macro? If not, what would happen?
Various dynamic variables affect the output produced by print. with-standard-io-syntax ensures those variables are set to the default values.
For example:
(let ((list '(1 2 3 4 5 6 7 8 9 10))
(*print-length* 5))
(print list)
(with-standard-io-syntax
(print list)))
Prints:
(1 2 3 4 5 ...)
(1 2 3 4 5 6 7 8 9 10)
It's particularly important if you're printing things with the intention of being able to read them later (like with prin1).