LISP how to write this function without using LOOP - loops

i wrote this function but i have been told i can't use the loop inside of it, i have no idea how to modify it in order to remove the loop.
any suggestion?
(defun function (P VariableValues)
(let* ((M (mono P))
(VariableNames (variables P))
(VariableDict (loop for x in VariableNames for y in VariableValues collect (cons x y)))
(Valorizzati (mapcar (lambda (x) (applica-valori VariableDict x)) M))
)
(if Valorizzati
(+ (car Valorizzati) (recursive-sum (cdr Valorizzati)))
0)))

You can use mapcar for that:
(mapcar #'cons '(a b c) '(1 2 3))
;; ==> ((a . 1) (b . 2) (c . 3))

Related

Lisp loop macro, pop macro and memory

I'm learning lisp and and implemented a nested array parses, so that:
"[1,[2,[3,[4,[5,6,7]]]],8,9]" -> '(1 (2 (3 (4 (5 6 7)))) 8 9)
Online Code snippet here
This was my first implementation of parse-line
(defun parse-line (string)
(loop
:for i = 0 :then (1+ j)
:for stack = (list nil)
:as j = (position-if (lambda (c) (member c '(#\[ #\] #\,))) string :start i)
:as n = (parse-integer string :start i :end j :junk-allowed t)
:when n :do (push n (car stack))
:while j
:do (cond
((eql #\[ (aref string j)) (push nil stack))
((eql #\] (aref string j)) (push (nreverse (pop stack)) (car stack))))
:finally (return (car (pop stack))))
))
But it crashes on the stack pop.
;test-case
(print (equal '(1 (2 (3 (4 (5 6 7)))) 8 9) (parse-line "[1,[2,[3,[4,[5,6,7]]]],8,9]")))
The value
NIL
is not of type
CONS
I then brute-forced my way into a solution declaring stack with let outside the loop macro
(defun parse-line (string)
(let ((stack (list nil)))
(loop
:for i = 0 :then (1+ j)
:as j = (position-if (lambda (c) (member c '(#\[ #\] #\,))) string :start i)
:as n = (parse-integer string :start i :end j :junk-allowed t)
:when n :do (push n (car stack))
:while j
:do (cond
((eql #\[ (aref string j)) (push nil stack))
((eql #\] (aref string j)) (push (nreverse (pop stack)) (car stack))))
:finally (return (car (pop stack))))
))
But I can't see why the second implementation works.
I also can't see why I need to initialize stack with (list nil). I thought that initializing stack to nil and removing the final car should be equivalent but it crashes with the same error at the same place, ie:
(defun parse-line (string)
(let (stack)
(loop
:for i = 0 :then (1+ j)
:as j = (position-if (lambda (c) (member c '(#\[ #\] #\,))) string :start i)
:as n = (parse-integer string :start i :end j :junk-allowed t)
:when n :do (push n (car stack))
:while j
:do (cond
((eql #\[ (aref string j)) (push nil stack))
((eql #\] (aref string j)) (push (nreverse (pop stack)) (car stack))))
:finally (return (pop stack)))
))
Look at these two lines in your first implementation:
:for i = 0 :then (1+ j)
:for sack = (list nil)
There is a typo (sack -> stack), but even then it doesn't work, because with each new value of i, you will create a brand new stack, losing all previous values. Add some debug print to see, what's going on:
i:0 j:0 n:NIL stack:(NIL NIL)
i:1 j:2 n:1 stack:((1))
i:3 j:3 n:NIL stack:(NIL NIL)
i:4 j:5 n:2 stack:((2))
i:6 j:6 n:NIL stack:(NIL NIL)
i:7 j:8 n:3 stack:((3))
...
If you don't want to use let to initialize stack, you can use keyword :with:
(defun parse-line (string)
(loop
:with stack = (list nil)
:for i = 0 :then (1+ j)
:as j = (position-if (lambda (c) (member c '(#\[ #\] #\,))) string :start i)
:as n = (parse-integer string :start i :end j :junk-allowed t)
:when n :do (push n (car stack))
:while j
:do (cond
((eql #\[ (aref string j)) (push nil stack))
((eql #\] (aref string j)) (push (nreverse (pop stack)) (car stack))))
:finally (return (car (pop stack)))))
You can use a similar debug print to see, why your code crashes with stack initialized to nil. This error can be reproduced with:
> (let ((stack '((9 8 (2 (3 (4 (5 6 7)))) 1))))
(push (nreverse (pop stack)) (car stack)))
Error: NIL (of type NULL) is not of type CONS.
You can find some explanation for this behaviour here: Why I can't (push 3 '()) in Common Lisp's REPL?
I would recommend using a Lisp compiler and using its warnings. SBCL gives this warning on your first form:
; in: DEFUN PARSE-LINE
; (PUSH N (CAR STACK))
;
; caught WARNING:
; undefined variable: COMMON-LISP-USER::STACK
;
; compilation unit finished
; Undefined variable:
; STACK
; caught 1 WARNING condition
That would lead you to investigate why that is: why is STACK undefined?

Common Lisp Loop

In the following loop:
(let ((funs (loop for i upto 3 do (print i) collect #'(lambda () i))))
(loop for fun in funs collect (funcall fun)))
i would intuitively think i would get a list of four closures which return the numbers 0 1 2 and 3 upon being called, but this is what i get:
>> 0
>> 1
>> 2
>> 3
=> (4 4 4 4)
But rebinding the i locally to something else:
(let ((funs (loop for i upto 3 do (print i) collect (let ((x i))
#'(lambda () x)))))
(loop for fun in funs collect (funcall fun)))
works as expected:
>> 0
>> 1
>> 2
>> 3
=> (0 1 2 3)
So each of the functions return 4, why are all return values the same, and why 4?
update
This seems to be a question about lambda actually. See below:
(setq dynamic-var 8
funs ())
(push (lambda () dynamic-var) funs)
(incf dynamic-var)
(push (lambda () dynamic-var) funs)
(mapcar #'funcall funs) ;(9 9)
What does
(let (i ; a counter variable
f) ; a list of functions
(setf i 1)
(push (lambda () i) f)
(setf i 2)
(push (lambda () i) f)
(mapcar #'funcall f))
return?
How about:
(let (i
f)
(setf i 1)
(push (lambda () i) f)
(let (i)
(setf i 2)
(push (lambda () i) f))
(mapcar #'funcall f))
Which is the LOOP model?
See also:
CL-USER 42 > (let (f)
(dotimes (i 10 (mapcar #'funcall (reverse f)))
(push (lambda () i) f)))
(10 10 10 10 10 10 10 10 10 10)
CL-USER 43 > (let (f)
(dotimes (i 10 (mapcar #'funcall (reverse f)))
(push (let ((i i))
(lambda () i))
f)))
(0 1 2 3 4 5 6 7 8 9)
The Common Lisp standard says for DOTIMES:
It is implementation-dependent whether dotimes establishes a new binding of var on each iteration or whether it establishes a binding for var once at the beginning and then assigns it on any subsequent iterations.
you write:
i would intuitively think i would get a list of four closures which return the numbers 0 1 2 and 3 upon being called
This intuition is only partly correct. You get four closures, but in this case they all share one variable binding. Thus they can only see the current binding of this one variable. In Common Lisp this binding is mutable and closures see the current binding, not the one of the initial binding of closure creation time.
Your intuition would be right, when each closure had its own variable binding.
Additional answer: why is this Lisp returning 10 ?
(PROGN
(SETQ I (THE INTEGER (1+ (THE INTEGER I))))
(WHEN (>= (THE INTEGER I)
(THE INTEGER #:|dotimes-count-1075|))
(GO #:|dotimes-end-tag1080|)))
Above is a part of the macro expansion of the dotimes construct. As you can see it first increments the variable and then tests for >=. Thus it exits when I is >= 10. Thus the last value of I is 10. Later after exiting the dotimes you are retrieving the value of I and then it's 10.

Strange behavior of log4cl and iterate

I am starting to use log4cl and am facing a weird issue when using it inside an iterate loop. While working does show the name of the method it is empty for not-working.
Do I miss something obvious here? Or is there a bug in the combination of iterate and log4cl?
(ql:quickload "iterate")
(ql:quickload "log4cl")
(defpackage :minimal
(:use #:cl #:iterate))
(in-package :minimal)
(defclass test ()
((a :documentation "test-a"
:initform (make-array '(3 3)
:element-type 'integer
:initial-element 0)
:initarg :a)))
(defvar *a* (make-instance 'test))
(defmethod not-working ((test test))
(with-slots (a) test
(iter
(for i below 3)
(iter
(for j below 3)
(unless (= 10 (aref a i j))
(log:info "R: ~D C: ~D" i j))))))
(defmethod working ((test test))
(with-slots (a) test
(loop
for i below 3
do (loop
for j below 3
unless (= 10 (aref a i j))
do (log:info "I: ~D J: ~D" i j)))))
(not-working *a*)
(working *a*)
EDIT
I see the issue only on sbcl. Using cclthe method name is displayed correctly. Furthermore, omitting the (are...) statement inside unless leads to a working version:
(defmethod also-working ((test test))
(with-slots (a) test
(iter
(for i below 3)
(iter
(for j below 3)
(unless (= 10 j)
(log:info "R: ~D C: ~D" i j))))))

Writing a While Loop in Scheme

I am trying to implement a while loop using recursion with lambda, but I just don't understand how to do it.
I am supposed to start with this lambda expression:
((lambda (x) (x x)) (lambda (x) (x x))
My first question is why does this cause 'eternal' recursion? I try to understand how it works, but I just can't grasp it.
I also have this code to go after:
((lambda (x) (x x))
(lambda (x)
(if (not (= i 0))
(begin
(display i)
(set! i (- i 1))
(x x))
)))
This code causes a loop that prints from i = n to i = 0, but I don't understand this either. If someone would care to explain the use of lambda here I would be grateful :)
Edit: I have to use this lambda expression as my 'starting point', and I don't want to use macros (it's a voluntary excercise which I try to understand, so I want to follow the guidelines :))
To see what happens when ((lambda (x) (x x)) (lambda (x) (x x)) is evaluated use the stepper in DrRacket. It can show you the steps an evaluation takes.
Write your expression in the definition window of DrRacket.
Then choose the teaching language "Intermediate Student with lambda". Then click the stepper button (the green triangle followed by a bar).
You will see something that looks like the image (which uses a different program):
Update:
Try this program:
(define i 5)
((lambda (x) (x x))
(lambda (x)
(if (not (= i 0))
(x x)
'ignore)))
Update:
(define i 5)
(define f
(lambda (x)
(if (not (= i 0))
(begin
(display i)
(set! i (- i 1))
(x x))
'done)))
(f f)
Or without any defines at all:
((lambda (f) (f f))
(lambda (x)
(if (not (= i 0))
(begin
(display i)
(set! i (- i 1))
(x x))
'done)))
And here without an external variable:
((lambda (f i) (f f i))
(lambda (x i)
(if (not (= i 0))
(begin
(display i)
(x x (- i 1)))
'done))
5)
Using a while function:
(define (while body . args)
(apply body body args))
(while (lambda (loop i)
(if (not (= i 0))
(begin
(display i)
(loop loop (- i 1)))
'done))
5)

value not of type array

I have created a function that is supposed to have lexical variables of type ARRAY:
(defun give-rank-vec (dir-1 dir-2 file-1 file-2)
(let* ((cm-size (array-dimension (Swc (make-ff-array dir-1 file-1)
(make-ff-array dir-2 file-2))
0))
(rank-dump-vec (make-array `(,cm-size)))
(Swc' (Swc (make-ff-array dir-1 file-1)
(make-ff-array dir-2 file-2)))
(Sbc' (Sbc (make-ff-array dir-1 file-1)
(make-ff-array dir-2 file-2))))
(dotimes (j cm-size)
(setf (svref rank-dump-vec j)
(/ (get-element Sbc' j j)
(get-element Swc' j j))))
rank-dump-vec))
(defun Sbc (cmatrix1 cmatrix2)
(add-matrices (Si cmatrix1)
(Si cmatrix2)))
(defun add-matrices (A B)
(let ((C (make-array (array-dimensions A))))
(dotimes (i (array-dimension A 0))
(dotimes (j (array-dimension A 1))
(setf (aref C i j) (+ (aref A i j) (aref B i j)))))
C))
However when I SLIME this function I get the error:
The value
(SBC (MAKE-FF-ARRAY DIR-1 FILE-1)
(MAKE-FF-ARRAY DIR-2 FILE-2))
is not of type
ARRAY.
[Condition of type TYPE-ERROR]
Swc works fine, in that seems to return an array- however Sbc doesn't- I tested Sbc with small and huge (wc 13000 65000 627677) flat files and it returned an array when called in SLIME, however it isn't working in this case. The let* expression seems to be written right- I'm not sure what I'm doing wrong here.
The single quote character ' is a terminating macro character in Common Lisp. See the Figure 2-7 in the Hyperspec.
If you want to use this character in a symbol you have to quote it with a backslash or a pair of vertical bars:
CL-USER 65 > '(quote-at-the-end-\' |QUOTE-AT-THE-END-'| quote-at-the-end-|'|)
(QUOTE-AT-THE-END-\' QUOTE-AT-THE-END-\' QUOTE-AT-THE-END-\')

Resources