This question already has answers here:
How to debug in [Clozure] Common Lisp?
(3 answers)
Closed 5 years ago.
I am trying to understand how a function works in Lisp, I used Allegro Cl quite some time ago, and I remember it had a special function in the REPL, that let you see how a function worked step by step, like in Matlab. For example, if you had this function:
(+ 1
(* 2 3
(/ 6 2)
)
)
You could see each function step by step, like:
(+ 1
(* 2 3
3)
)
And then:
(+ 1
18)
And finally:
19
Many thanks in advance.
Thanks to jkiiski,
The code for showing step by step the function would be:
(step (+ 1 (* 2 3 (/ 6 2))))
and this shows in very detail how Lisp parses all the data and evaluates the function.
After many steps it gives:
[STEP] CG-USER(2):
result 6: 2
6: (/ 6 2)
[STEP] CG-USER(2):
result 5: 18
result 4: 18
result 3: 18
result 2: 18
2: (+ 1 18)
[STEP] CG-USER(2):
result 2: 19
result 1: 19
Related
I am new to scheme and I'm having problems with matrices in Scheme. I need to create a function that takes one big and one small square matrices (with the condition: the small's length should be divisor of big one) and make a new matrix with doing an operation on the big one with small one. I've successfully split the big matrix to size that I wanted and I’m successfully operating on it to get the result.
Here is how I did it:
(define (matrix-op big small x y)
(if (< y (/ (length big) (length small))))
(if (< x (/ (length big) (length small)))
(cons (calculate (split-y (split-x big small x) small y) small)
(matrix-op big small (+ x 1) y))
(matrix-op big small 0 (+ y 1)) ; <- this is where i need to split
)
'()
)
)
My calculate function returns only 1 atomic value so when I run the function like this it gives me an output like '(val val val val), but what i want is formatting the output like '((val val) (val val)). How can I do it? Thanks in advance.
I realized that I couldn't explain the problem properly. What i want to have is a function that takes two different square matrices one big and one small, Splits the big one to same size as smaller one, operates on them to create a new matrix that has the size m/n if the big one is mxm and small one is nxn. Example:
big '( small '(
(8 0 3 1 5 3 2 2) (8 4)
(7 1 1 4 3 7 1 4) (9 5)
(1 3 7 4 3 6 6 3) )
(0 9 8 6 5 6 4 3)
(1 7 6 9 6 6 7 2)
(5 7 1 0 2 9 5 3)
(0 5 4 6 6 6 3 0)
(3 6 2 7 7 5 7 0)
)
I need to split big over the same size as small and calculate results like:
for x=0 y=0 part is '( calculate result is 5
(8 0)
(7 1)
)
for x=1 y=0 part is '( calculate result is 2
(3 1)
(1 4)
)
I actually did returned the results calculated but with the method i gave above my return was like '(5 2 4 2 2 6 4 4 4 3 5 4 2 4 6 3) but I wanted to return as:
'(
(5 2 4 2)
(2 6 4 4)
(4 3 5 4)
(2 4 6 3)
)
So how can I manage to split the return list where i want to split?
I think you are trying to do too much at once. It is always OK to split a bigger problem into a smaller problem.
If I understand yours, the idea is to take two square matrics, one of which may be some multiple of the other’s dimensions, and perform a pair-wise operation on the elements. For example:
'((1 2 3) '((1 2 3) '((7 7 7) '(( 8 9 10)
(4 5 6) + '((7)) --> (4 5 6) + (7 7 7) --> (11 12 13)
(7 8 9)) (7 8 9)) (7 7 7)) (14 15 16))
I will continue with the assumption that this is what is desired.
Notice that if the two matrices were the same size, a simple nested map would easily combine all elements. What is left is the problem of the different sizes.
Solve that and you are golden.
Recap:
(define (f op small-M big-M)
(f-apply-pairwise-op
op
(f-biggify small-M (/ (length big-M) (length small-M)))
big-M))
Now you have broken the problem into two smaller pieces:
(define (f-apply-pairwise-op op A B) ...) ; produces pairwise 'A op B'
(define (f-biggify M n) ...) ; tile M n times wider and taller
Good luck!
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
So I have list structure as follows:
(defparameter *list* '( ((2 2 2) (0.1))
((5 5 5) (0.4))
((1 1 1) (1.2))
((3 3 3) (3.4))
((4 4 4) (4.5)) )
I want to sort it where it returns an output of
'( ((1 1 1) (1.2))
((2 2 2) (0.1))
((3 3 3) (3.4))
((4 4 4) (4.5)) )
So here is my attempt:
(sort *list*
#'(lambda (a b)
(< (squared a '(0 0 0))
(squared b '(0 0 0))))
:key #'first)
Where squared takes in two lists and calculates the squared distance of each element and sums them (ie (squared '(1 2 3) '(0 3 5)) => 48))
I am sorting the list of lists by its first element of the sublist '(# # #) and calculating the distance from '(0 0 0) then sorting by that distance.
But my attempt outputs the following => ((1) (1 1 1) (2) (3) (2 2 2) (4) (5) (3 3 3) (4 4 4) (5 5 5))
How do I sort by '(# # #) but also preserve the list structure? Also using Common Lisp!
Thank you!
EDIT
I had typed into lisp wrong but correctly into this forum. I had typed list as the following
(defparameter list '( (2 2 2) (0.1)
(5 5 5) (0.4)
(1 1 1) (1.2)
(3 3 3) (3.4)
(4 4 4) (4.5) ))
Careful: sort may destroy the input data. Your input as shown here contains literal data. Modifying literal data has undefined consequences. Use copy-tree or copy-list to create non-literal from literal data.
Actually my first attempt works! I just typed in list incorrectly (forgot some parenthesis). So it sorts and maintains the structure!
I am very new to scheme and am learning the basics right now. I understand that in (+ 1 2) + is like a function taking two inputs and returning the output. My quiz had a the question (+ (-(*))4 5) . According to DrRacket the answer is 8 but i am having a hard time understanding why it is the case. So I need help in understanding how the given expression evaluates to 8.
(*) evaluates to 1
so (+ (-1) 4 5) is the sum of (-1) + (4) + (5) which is 8
I am trying to implement the reverse algorithm in LISP. I am fairly new to the language so any help would be appreciated.
I have the following code in LISP, it seems logical to me but it doesn't output anything when I run it on terminal. This is what my rev.lisp file looks like:
(defun rev (list)
(if (atom list)
(append (rev (cdr list))
(list (rev (car list))))))
I run it on my terminal as:
%clisp rev.lisp
%
I am expecting the output 6 5 4 3 2 but it doesn't return anything.
You already have an answer, but here are some remarks.
Depending on your background and preferences, recursive algorithms are sometimes best understood with a trace of execution.
The TRACE macro can help you debug your code.
The exact output varies among implementation (here, I am using SBCL).
Since I would like to show you how many times APPEND is called and because tracing standard functions in not allowed1, I am defining a simple function around it and redefining your code to use it:
(defun append* (&rest args) (apply #'append args))
The result of TRACE is the following:
CL-USER> (rev '(2 3 4 5 6))
0: (REV (2 3 4 5 6))
1: (REV (3 4 5 6))
2: (REV (4 5 6))
3: (REV (5 6))
4: (REV (6))
5: (REV NIL)
5: REV returned NIL
5: (REV 6)
5: REV returned 6
5: (APPEND* NIL (6))
5: APPEND* returned (6)
4: REV returned (6)
4: (REV 5)
4: REV returned 5
4: (APPEND* (6) (5))
4: APPEND* returned (6 5)
3: REV returned (6 5)
3: (REV 4)
3: REV returned 4
3: (APPEND* (6 5) (4))
3: APPEND* returned (6 5 4)
2: REV returned (6 5 4)
2: (REV 3)
2: REV returned 3
2: (APPEND* (6 5 4) (3))
2: APPEND* returned (6 5 4 3)
1: REV returned (6 5 4 3)
1: (REV 2)
1: REV returned 2
1: (APPEND* (6 5 4 3) (2))
1: APPEND* returned (6 5 4 3 2)
0: REV returned (6 5 4 3 2)
(6 5 4 3 2)
Basics
First off, we see that REV is sometimes called on ATOM elements. Even though your implementation unwrap elements with CAR and wrap them back again with LIST, it makes little sense to do so. Reversing a list is a function that is applied on lists, and if you happen to pass a non-list argument, it should raise a red flag in your head. In order to build a recursive function for lists, it is generally sufficient to focus on the recursive definition of the datatype.
The LIST type is defined in Lisp as (OR NULL CONS), which is the union of the NULL type and the CONS type. In other words, a list is either empty or a cons-cell.
There are many ways to distinguish between both cases which differs mostly in style. Following the above approach with types, you can use ETYPECASE, which dispatches on the type of its argument and signals an error if no clause matches:
(defun rev (list)
(etypecase list
(null <empty>)
(cons <non-empty> )))
You could also use ENDP.
The reverse of an empty list is an empty list, and you are in the case where you can simply use WHEN and focus and the non-empty case:
(defun rev (list)
(when list
<non-empty>))
Above, we don't check that LIST is a cons-cell, it could be anything. However, the way we use it below can only apply on such objects, which means that runtime checks will detect errorneous cases early enough.
(defun rev (list)
(when list
(append* (rev (rest list))
(list (first list)))))
The above is quite similar to your code, except that I don't call REV on the first element. Also, I use FIRST and REST instead of CAR and CDR, because even though they are respective synonyms, the former better convey the intent of working with lists (this is subjective of course, but most people follow this rule).
Append
What the trace above shows that you might have missed when only reading the code is that APPEND is called for all intermediate lists. This is quite wasteful in terms of memory and processing, since APPEND necessarily has to traverse all elements to copy them in a fresh list. If you call APPEND n times, as you are doing since you iterate over a list of n elements, you end up with a quadratic algorithm (n2).
You can solve the memory issues by reusing the same intermediate list with NCONC in place of APPEND. You still have to iterate many times this list, but at least the same underlying cons cells are reused. Typically, a recursive reverse is written with an additional parameter, an accumulator, which is used to store intermediate results and return it at the deepest level:
(defun reverse-acc (list acc)
(etypecase list
;; end of input list, return accumulator
(null acc)
;; general case: put head of input list in front
;; of current accumulator and call recursively with
;; the tail of the input list.
(cons (reverse-acc (rest list)
(cons (first list) acc)))))
The above example is called with an empty accumulator. Even though it could be possible to let this function accessible directly to users, you might prefer to hide this implementation detail and export only a function with a single argument:
(defun rev (list) (reverse-acc list nil))
(trace rev reverse-acc)
0: (REV (2 3 4 5 6))
1: (REVERSE-ACC (2 3 4 5 6) NIL)
2: (REVERSE-ACC (3 4 5 6) (2))
3: (REVERSE-ACC (4 5 6) (3 2))
4: (REVERSE-ACC (5 6) (4 3 2))
5: (REVERSE-ACC (6) (5 4 3 2))
6: (REVERSE-ACC NIL (6 5 4 3 2))
6: REVERSE-ACC returned (6 5 4 3 2)
5: REVERSE-ACC returned (6 5 4 3 2)
4: REVERSE-ACC returned (6 5 4 3 2)
3: REVERSE-ACC returned (6 5 4 3 2)
2: REVERSE-ACC returned (6 5 4 3 2)
1: REVERSE-ACC returned (6 5 4 3 2)
0: REV returned (6 5 4 3 2)
(6 5 4 3 2)
The shape of the trace is typical of recursive functions for which tail-call elimination is possible. Indeed, the recursive invocation of REVERSE-ACC inside itself directly returns the result we want and thus no intermediate memory is required to store and process intermediate result. However, Common Lisp implementations are not required by the standard to eliminate recursive calls in tail position and the actual behavior of a specific implementation might even depend on optimization levels. A conforming program thus cannot assume the control stack won't ever grow linearly with the size of the list.
Recursivity is best used on certain kinds of problems which are recursive by nature and where the height of the stack doesn't grow so fast w.r.t. the input. For iteration, use control structures like DO, LOOP, etc. In the following example, I used DOLIST in order to PUSH elements inside a temporary RESULT list, which is return at the end of DOLIST:
(defun rev (list)
(let ((result '()))
(dolist (e list result)
(push e result))))
The trace is:
0: (REV (2 3 4 5 6))
0: REV returned (6 5 4 3 2)
(6 5 4 3 2)
1. 11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming Programs
You are not printing anything, so you are not seeing anything.
Replace (rev '(2 3 4 5 6)) with (print (rev '(2 3 4 5 6))) and you will see (6 5 4 3 2) on the screen.
I want to sum the numbers in a list without using recursion. I know you can sum a list of numbers like this
(+ num1 num2 ... numN)
but what if you have a list L which equals to '(num1 num2 ... numN)
is there a way to make + take the numbers in this list as arguments. I need to do this without recursion or helper functions.
Sure, just use apply:
(apply + '(1 2 3 4 5 6)) ; same as (+ 1 2 3 4 5 6)
(apply + 1 2 3 '(4 5 6)) ; ditto
(apply + 1 2 3 4 5 '(6)) ; ditto
(apply + 1 2 3 4 5 6 '()) ; ditto
The general answer to the question you seem to be asking -- how to take a list and use it as the arguments -- is apply, as Chris Jester-Young answered.
However, for this particular question, there might some other considerations. You may want to sum lists of arbitrary size. However, implementations often have some limit of the number of arguments you can call a function with. A more reliable solution may be to use some kind of fold function (various implementations have different fold functions) to fold + over the list.