Cond inside let doesn't work properly - conditional-statements

I'm having a trouble with some Common Lisp code. I have two functions similars to the functions below:
(defun recursive-func (func lst num)
(let ((test
(some-func func
(first lst)
(first (rest lst))
num))
(next
(recursive-func func
(rest lst)
num)))
(cond ((null (rest lst)) nil)
((null test) next)
(t (cons test next)))))
(defun some-func (func a b num)
(if (> a b)
nil
(funcall func a b num)))
When the list has only one element I want recursive-func return nil, but it doesn't and calls some-func generating a evaluation abort because b is nil. Here is a trace of execution:
CL-USER> (recursive-func #'(lambda(x y z) (+ x y z)) '(1 2 3 4 5) 5)
0: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (1 2 3 4 5) 5)
1: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 1 2 5)
1: SOME-FUNC returned 8
1: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (2 3 4 5) 5)
2: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 2 3 5)
2: SOME-FUNC returned 10
2: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (3 4 5) 5)
3: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 3 4 5)
3: SOME-FUNC returned 12
3: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (4 5) 5)
4: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 4 5 5)
4: SOME-FUNC returned 14
4: (RECURSIVE-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> (5) 5)
5: (SOME-FUNC #<FUNCTION (LAMBDA (X Y Z)) {10035F6ABB}> 5 NIL 5)
; Evaluation aborted on #<TYPE-ERROR expected-type: NUMBER datum: NIL>.
I hope someone would can help me, thanks.

The bindings in let are evaluated first, and only then you perform the tests in the cond.
You need only change a bit:
(defun recursive-func (func list num)
(if (null (rest list))
nil
(let ((test (some-func func
(first list)
(first (rest list))
num))
(next (recursive-func func
(rest list)
num)))
(cond ((null test) next)
(t (cons test next))))))
Note that the cond could also be written:
(if test (cons test next) next)
With your example:
(recursive-func (lambda (x y z) (+ x y z))
'(1 2 3 4 5)
5)
=> (8 10 12 14)
Alternatively, here is how you could decompose the task (in the REPL):
> (maplist (lambda (list)
(list
(first list)
(second list)))
'(1 2 3 4 5))
=> ((1 2) (2 3) (3 4) (4 5) (5 NIL))
Prefer SECOND instead of (first (rest ...)).
The last result is bound in the REPL to the variable *. Remove the last (useless) pair with BUTLAST:
(butlast *)
=> ((1 2) (2 3) (3 4) (4 5))
Then, for each couple in this list, call your function -- here it is just +. Notice the use of DESTRUCTURING-BIND:
(mapcar (lambda (list)
(destructuring-bind (a b) list
(+ a b 5)))
*)
=> (8 10 12 14)
So, basically, your function can be written as:
(defun map-pair-funcall (function list number)
(mapcar (lambda (pair)
(destructuring-bind (a b) pair
(funcall function a b number)))
(butlast (maplist (lambda (list)
(list (first list) (second list)))
list))))
And thus:
(map-pair-funcall #'+ '(1 2 3 4 5) 5)
=> (8 10 12 14)
Edit:
I missed the case where the supplied function might return NIL. Wrap the form calling mapcar by (remove NIL (mapcar ...)) to filter that out.
You can perform all that in one iteration by using MAPCON. The function iterates over sublists, and concatenates the resulting lists. The function being called should thus return list, and when you return NIL, the result are simply discarded.
Let's define ensure-list (or use the one from Alexandria):
(defun ensure-list (expr)
(if (listp expr) expr (list expr)))
The function wraps the returned value in a list, except if it is already a list (in particular, NIL). And then, the function is defined as follows:
(defun map-pair-funcall (function list number)
(mapcon (lambda (list)
(and (second list)
(ensure-list (funcall function
(first list)
(second list)
number))))
list))
You could also LOOP:
(defun map-pair-funcall (function list number)
(loop
for (a b) on list
for result = (and b (funcall function a b number))
when result
collect result))

Related

Iterating through a nested list using filter or fold Racket

I need to iterate through a list with sublists in Racket using list iteration and filtering, one of the lists is a nested list, I tried using "list?" and "car" to iterate inside but of course that would only apply to the first value of the sublist.
Is there a way to iterate through the whole nested list using list iteration and filtering?
(define (count-evens lst)
(length
(filter
(lambda (x)
(cond
[(and (list? x)
(and (number? (car x))
(eq? (modulo (car x) 2) 0)))
#t]
[(and (number? x)
(eq? (modulo x 2) 0))
#t]
[else
#f]))
lst)))
(count-evens '(1 2 5 4 (8 4 (b (10 3 3))) 3))
=> 3
Should return => 5
I would use a recursive function to do this but the assignment doesn't allow it.
"...assignment doesn't allow [recursive functions]"
Not sure what is allowed for this assignment, but
in ye olden days we processed recursive data structures with stacks...
(define (count-evens lst)
(define (lst-at stack) ;; (car stack) = index in deepest sub-list
;; produce list cursor within lst indexed by stack
(do ([stack (reverse stack) (cdr stack)]
[cursor (list lst) (list-tail (car cursor) (car stack))])
((null? stack) cursor)))
(do ([stack (list 0)
(cond
[(null? (lst-at stack))
(cdr stack)] ;; pop stack
[(pair? (car (lst-at stack)))
(cons 0 stack)] ;; push stack
[else ;; step through current (sub)list
(cons (+ 1 (car stack)) (cdr stack))])]
[count 0
(let ([item (car (lst-at stack))])
(if (and (number? item) (even? item)) (+ 1 count) count))])
((null? (lst-at stack)) count)))
> (count-evens '(1 2 5 4 (8 4 (b (10 3 3))) 3)) ;=>
5

Symbol’s value as variable is void: false when run element-of-setp

Following SICP's instruction, I rewrite its intersection-set as:
(defun intersection-set (set1 set2)
(cond ((or (null set1) (null set2)) '())
((element-of-setp (car set1) set2)
(cons (car set1)
(intersection-set (cdr set1) set2)))
(t (intersection-set (cdr set1) set2))))
(defun element-of-setp(x set)
(cond ((null set) false)
((equal x (car set)) t)
(t (element-of-setp x (cdr set)))))
(intersection-set (list 1 2) (list 2 3 4))
Running it reports the following error:
element-of-setp: Symbol’s value as variable is void: false
However, element-of-setp on its own seems to work properly:
#+begin_src emacs-lisp :tangle yes
(defun element-of-setp(x set)
(cond ((null set) false)
((equal x (car set)) t)
(t (element-of-setp x (cdr set)))))
(element-of-setp 1 (list 1 2 3))
#+end_src
#+RESULTS:
: t
What's the problem?
However, element-of-setp on its own seems to work properly:
Unfortunately, the test you used did not cover all the possible cases.
If you try instead:
(element-of-setp 5 (list 1 2 3))
Then the function is going to reach the case where the list is empty, and in that it will evaluate false, which is most likely undefined; as stated in the comment, boolean values in Emacs-Lisp are represented by nil and non-nil values (atoms).

Custom Scheme indexing function returns list-external value

I'm a newbie to scheme programming and I was writing small codes when I encountered the following issue and couldn't reason about it satisfactorily.
(define (at_i lst i)
(if (eq? i 0)
(car lst)
(at_i (cdr lst)
(- i 1) )))
Evaluation of (at_i '(1 2 3 4) 0) returns 1.
Now lets define same procedure with a lambda syntax.
(define (at_i lst i)
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec)
(- x 1) )))
lst i)
But now Evaluation of (at_i '(1 2 3 4) 0) returns 0, which is not in the list and in general, it returns element at index-1.
I don't understand why this is happening.
Note: I just realized its not returning element at index - 1 but the index itself. The reason for this has been well explained below by #Renzo. Thanks!
First, you should indent properly the code if you intend to learn the language, since code indentation is very important to understand programs in Scheme and Lisp-like languages.
For instance, your function correctly indented is:
(define (at_i lst i)
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec) (- x 1))))
lst
i)
From this you can see that you are defining the function at_i exactly as before in terms of a function with two parameters (lst and i), and whose body is constitued by three expressions: the first lambda (vec x) ... (- x 1)))), which is an (anonymous) function (lambda) which is not called or applied, the second, which is the first parameter lst, and finally the third which is the second parameter i. So, when the function at_i is called with two arguments, the result is the evaluation of the three expressions in sequence, the first two values are discarded (the function and the value of lst), and the result is the value of the second parameter i. This is reason for which the result of (at_i '(1 2 3 4) 0) is 0, since it is the value of i.
A proper redefinition of the function in lambda form would be the following, for instance:
(define at_i
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec) (- x 1)))))
(at_i '(1 2 3 4) 0) ;; => 1
in which you can see that the name at_i, through the define, is associated to a two parameter function which calculates correctly the result.
eq? is memory object equality. Only some Scheme implementations interpret (eq? 5 5) as #t. Use = for numbers, eqv? for values, and equal? for collections.
(define (index i xs) ; `index` is a partial function,
(if (= i 0) ; `i` may go out of range
(car xs)
(index (- i 1) ; Tail recursion
(cdr xs) )))
Your second function returns the index because you missed parenthesis around the lambda's application. It should be
(define (index i xs)
((lambda (i' xs')
(if (= i' 0)
(car xs')
(index (- i' 1) ; Not tail-recursive
(cdr xs') )))
i xs))
But this is verbose and differs semantically from the first formulation.
You say you are defining the "same procedure with a lambda syntax", but you are not. That would be (define at_i (lambda lst i) ...). Instead, you are effectively saying (define (at_i lst i) 1 2 3), and that is 3, of course.
In your particular case, you defined the procedure at_i to return (lambda (vec x) ...), lst and i. Now, if you call (at_i '(1 2 3 4) 0), the procedure will return 0, since that is the value of i at this point.

Racket: Map with keys/iterating?

I've got some function func and want to apply it on a list lst, so I used map but I need to have the first and last element of the list evaluated with some other function func2.
So basically I want this:
(map (lambda (x)
(cond [(isBeginningOfList? lst) (func2 x)]
[(isEndOfList? lst) (func2 x)]
[else (func x)]))
lst)
Obviously this doesn't work.
How can I achieve this functionality?
Can I somehow get a key of each list entry? Like lambda(key,val) and then compare (equal? key 0) / (equal? key (length lst))?
There's for/list with in-indexed and that does what you describe:
(define (f lst f1 f2)
(define last (sub1 (length lst)))
(for/list (((e i) (in-indexed lst)))
(if (< 0 i last)
(f1 e)
(f2 e))))
then
> (f '(1 2 3 4 5) sub1 add1)
'(2 1 2 3 6)
You can use a map on all the elements except the first and the last one and treat those two separately. In this way you avoid those comparisons which you would do for every element.
(define special-map
(λ (lst f1 f2)
(append (list (f1 (car lst)))
(map f2 (drop-right (cdr lst) 1))
(list (f1 (last lst))))))
Example
Let's try to increment the first and the last elements and decrement all the others.
> (special-map '(1 2 3 4 5) add1 sub1)
'(2 1 2 3 6)
Later edit
I changed (take (cdr lst) (- (length lst) 2)) with (drop-right (cdr lst) 1).

Assigning variables (variable mutation) in racket

I have the following function that given an expression, executes it :
(define (foo exp0) exp0)
If I do the following:
(define x 5)
(foo (+ x 4))
(foo (* x 2))
display(x)
I would like for display(x) to display 18. Basically, how can I assign the value of the given expression back to the given variable?
First, the foo procedure is simply returning the parameter, it's not "executing" it. Answering your question, here's how you can reassign a value in Scheme:
(define x 5)
(set! x (+ x 4))
(set! x (* x 2))
(display x)
But to tell the truth, that style of programming (mutating variables) is frowned upon in Scheme. I believe this is more idiomatic:
(let* ((x 5)
(y (+ x 4))
(z (* y 2)))
(display z))
You can indeed write such a macro, if you can guarantee that the variable you're updating is always the first operand:
(define-syntax foo
(syntax-rules ()
((foo (op var arg ...))
(set! var (op var arg ...)))))