Scheme - Replacing elements in a list with its index - scheme

I am trying to replace the elements in a scheme list with its position.
For example, calling:
(position '((a b) c))
should return:
'((0 1) 2)
So far, my code keeps the list format, but the index is not updating.
(define (position term1)
(define index 0)
(cond [(null? term1) '()]
[(list? term1) (cons (position (car term1)) (position(cdr term1)))]
[else (+ 1 index) index]))
When (position '((a b) c)) is called, it returns
'((0 0) 0)
Can anybody explain why the index isn't updating?

There are a couple things wrong: first notice that every time you recursively call position, index is bound to zero.
Second, look at your else branch. (+ 1 index) evaluates to 1 (it does not change any variables) and index evaluates to 0. This branch can only evaluate to one thing, so what happens is the last one is returned and the rest are discarded. This is where your zeroes come from.
It seems like within your function you are trying to keep a global state (the current index) and modify it each time you label a leaf. The "modifying state" part is not good functional style, but if you are okay with that then take a look at set!.

Here is one solution using CPS:
#lang racket
(define (index xs [i 0] [continue (λ (xs i) xs)])
(match xs
[(cons x xs) (index x i
(λ (js j)
(index xs j
(λ (ks k)
(continue (cons js ks) k)))))]
['() (continue '() i)]
[x (continue i (+ i 1))]))
; Example
;(index '((a b) (c d) x (e (f g) h)))
; '((0 1) (2 3) 4 (5 (6 7) 8))
Here (index xs i continue) replaces the elements in xs with their indices, the count starts from i. Let's say the result of indexing xs is js, then continue is called with the indexing result and the next index to be used: (continue js j).

Daenerys Naharis already pointed out what's wrong, so let me point out some features of Scheme and Racket you may be unaware of that you could use in a solution that maintains functional style.
This is called a named let:
(let loop ((index 0)
(result '()))
(if (= index 10)
(reverse result)
(loop (+ 1 index) (cons index result)))
Within the let form, loop is bound as a function that takes all the local variables as arguments. Calling it recursively calls the let form itself. This way you can make index an argument without making it an argument of position. You can also put the result in an argument, which allows you to make the call to loop a tail call.
The other feature is less widespread among existing Scheme implementations: Optional arguments. In Racket, they're defined like this:
(define (position term1 (index 0)) ...)
Then position can be called with or without the index argument.

An example using mutation that maintains it's own state so that each item of each list has a unique id.
Example Usage:
> (position '((a b) c))
'((0 1) 2)
> (position '((a b) c (d (e))))
'((3 4) 5 (6 (7)))
Example Implementation:
#lang racket
(provide position)
(define base -1)
(define (indexer)
(set! base (add1 base))
base)
(define (position list-of-x)
(cond [(null? list-of-x) null]
[else
(define head (first list-of-x))
(cond [(list? head)
(cons (position head)
(position (rest list-of-x)))]
[else (cons (indexer)
(position (rest list-of-x)))])]))

Related

Understanding how a sequence works

I have the following accumulate function:
; accumulate
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence) (accumulate op initial (cdr sequence)))))
I'm trying to write a length function to get the length of a sequence using the accumulate function.
For the function to plug into accumulate, why is it (+ y 1) instead of (+ x 1) ? That's the part I can't figure out:
(define (length sequence)
(accumulate (lambda (x y) (+ x 1)) ; wrong
0
sequence))
(define (length sequence)
(accumulate (lambda (x y) (+ y 1)) ; correct
0
sequence))
Your problem is that x and y doesn't tell you anything what it is. However if you look at accumulate you can see how op is called:
(op (car sequence) ; first argument is the element
(accumulate op initial (cdr sequence))) ; second argument is the accumulated value
While it doesn't really look that way Imagine that the second argument is calling accumulate on the empty sequence. Then you get this:
(op (car sequence)
initial)
So lets make length:
(define (length sequence)
(accumulate (lambda (element initial)
;; initial is often also called acc / accumulator
(+ 1 initial))
0
sequence))
So the answer is that the first argument is the individual element while the second is either the initial value (0) or the previous calculated value which is 0 with as many 1 added as the tail of the sequence had. Thus a number. WHy you don't use the first argument is that you can't really use "a" or whatever the list contains to count elements since you need to just count them not use them as values. If you use the first argument and it happens to be strings what is (+ "a" 0) supposed to help in finding out that the list has length 1?
If you use (lambda (x y) (+ x 1)) as op, then your length (or to be precise, the accumulate) function will not use the result of the recursive calls to the accumulate function. It will essentially only do one computation, (+ x 1) ,where x is (car sequence), the first element of sequence -- and this one computation may or may not even make sense, depending on whether or not x is a number, and even if it did the answer would be wrong.
On the other hand, if op is (lambda (x y) (+ y 1)), then your function will replace
(op (car sequence) (accumulate op initial (cdr sequence)))
with
(+ (accumulate op initial (cdr sequence)) 1)
The recursion bottoms out with the computation (+ 0 1), so you ultimately get the length of the list, when each of the nested recursive calls to accumulate return the length of the sub-lists to their calling functions.

Set operation A\B in Common Lisp

I just started learning Common Lisp 2 days ago, so please excuse spaghetti code and non-understanding.
My problem is the following: I want to write a function that performs the set-
operation A\B, where A and B sets that are not empty. They are represented by two lists.
So far I came up with this:
(defun myDifference (a b)
(if (null a)
(return-from myDifference) ;when a hits NIL, get outta the whole function
)
(if (not(member (car a) b)) ; if the first element of A ist not in B, add it to a list (which later should be the return)
(cons (car a) '())
)
(myDifference (cdr a) b) ; proceed with the remaining elements of A, until (null a) hits
)
I tried it with:
(myDifference '( 1 2 3) '(1 5 6))
But the output is NIL, whichever lists I try it on.
I suspect the problem occurs in quitting the function.
You have 3 expressions in your my-difference body. The first returns nil if (null a)
The second computes either (list a) or (list), then discards that value.
The third recurses with a changed to (cdr a).
It's clear that this has to return nil since the last one eventuelly recurses with a becoming nil and the recursion then returns nil since that is the default value when you don't supply a value. A better approach would be to make it one expression like this:
(defun my-difference (a b)
(if (null a)
a
(if (not (member (car a) b))
(cons (car a) (my-difference (cdr a) b))
(my-difference (cdr a) b))))
The third part of if is the else part and as you see we nest to get somthing similar to if-elseif-else of other languages. This can be written flatter with cond:
(defun my-difference (a b)
(cond ((null a) a)
((not (member (car a) b))
(cons (car a) (my-difference (cdr a) b)))
(t (my-difference (cdr a) b))))

Implementing sublist? using accumulate in Racket

I need to implement sublist? as a one-liner function that uses accumulate.
It is suppose to return true if set1 is in set2.
Something like this:
(define subset?
(lambda (set1 set2)
(accumulate member? (car set1) (lambda (x) x) set2)))
Honestly I think I'm just confused on how accumulate is suppose to work with member, or if member is even the right choice for the operator.
My accumulate function is:
(define accumulate
(lambda (op base func ls)
(if (null? ls)
base
(op (func (car ls))
(accumulate op base func (cdr ls))))))
and member?:
(define member?
(lambda (item ls)
(cond ((null? ls) #f)
((equal? item (car ls)) #t)
(else (member? item (cdr ls))))))
To give the correct definition of subset? first we must understand how the function accumulate works and the meaning of its parameters.
If we “unfold” the recursive definition, we can see that accumulate applies the binary operator op to all the results of applying func to the elements of list ls. And since the list can be empty, in these cases the function is defined to give back the value base.
So, for instance, assuming the recursive execution of the function, the following expression
(accumulate + 0 sqr '(1 2 3))
produces 14, since it is equivalent to:
(+ (sqr 1) (+ (sqr 2) (+ (sqr 3) 0)))
that is 1 + 4 + 9 + 0.
To solve your problem, you have to define a call to accumulate that applies the same operator to a list of elements and then combine the results. In you case, the operation to be applied is a test if an element is member of a list (member?), and you can apply it to all the elements of set1. And you should know, from the definition of the subset, that a set s1 is subset of another set s2 if and only if all the elements of s1 are contained in s2. So the operator that must be applied to combine all the results of the test is just the and boolean operator, so that it will be true if all the elements of s1 are member of s2 and false otherwise. The last thing to decide is the base value: this should be true, since an empty set is always contained in another set.
So this is a possible definition of subset?:
(define (subset? set1 set2)
(accumulate
(lambda (x y) (and x y)) ;; the combination operator
#t ;; the value for the empty list
(lambda(x) (member x set2)) ;; the function to be applied to all the elements of
set1)) ;; the set set1

Scheme: The object () is not applicable

It's a beginner question. However it's more than 2 hours that I'm trying to find out the error (I've also made searches) but without success.
(define a (lambda (l i) (
(cond ((null? l) l)
(else (cons (cons (car l) i) (a (cdr l) i))))
)))
The function a should pair the atom i with each item of l. For example:
(a '(1 2 3) 4) should return ((1 4) (2 4) (3 4))
However when I try to use invoke the function I get:
The object () is not applicable
What's the error in my function?
I am using mit-scheme --load a.lisp to load the file. Then I invoke the function a by typing in interactive mode.
The error, as usually happens in lisp languages, depends on the wrong use of the parentheses, in this case the extra parentheses that enclose the body of the function.
Remove it and the function should work:
(define a (lambda (l i)
(cond ((null? l) l)
(else (cons (cons (car l) i) (a (cdr l) i))))))
Rember that in lisp parentheses are not a way of enclosing expressions, but are an important part of the syntax: ((+ 2 3)) is completely different from (+ 2 3). The latter expression means: sum the value of the numbers 2 and 3 and return the result. The former means: sum the value of the numbers 2 and 3, get the result (the number 5), and call it as a function with zero parameters. This obviously will cause an error since 5 is not a function...

Scheme How To Return Multiple Values?

I notice that almost all scheme functions can only return one list as output.
In the following, I would like to return multiple values of all the adjacent nodes of neighbors.
(define (neighbors l w)
(if (and (= 1 l) (= 1 w))
(list (and (l (+ 1 w))) (and (+ 1 l) w)))) ; how to output 2 or more values?
In this case I'm first testing if the node is at corner, if so, return 2 values of the coordinates where (l and w+1), (l+1 and w) basically if I'm at (1,1) return me (1,2) and (2,1)
Same applies when the node has only 1 neighbor near the edge, in this case I will have 3 values.
When no edge is nearby I will have 4 return values.
I tried to use cons, append, list, display, write none of them seems working with additional values. I need this as a sub-function of this question. How should I implement it so I could pass on the return value and use it recursively to return me all the adjacent nodes?
Edit: I found the answer: use the keyword "values" to return multiple values. Example:
(define (store l w)
(values (write l)
(write w)
(newline)
(list (+ 1 w) l)
(list w (+ 1 l))))
values, continuation passing style, and list are at least three ways of returning multiple values:
(import (rnrs))
; let-values + values
(define (foo1)
(values 1 2 3))
(let-values (((a b c) (foo1)))
(display (list a b c))
(newline))
; cps
(define (foo2 k)
(k 1 2 3))
(foo2 (lambda (a b c)
(display (list a b c))
(newline)))
; list
(define (foo3)
(list 1 2 3))
(let ((result (foo3)))
(display result)
(newline))
The Guile implementation of Scheme has a receive syntax, which it says is "much more convenient" than values. I haven't used it yet, however, but this may be useful:
http://www.gnu.org/software/guile/manual/html_node/Multiple-Values.html
You can return a pair of values in a cons cell:
(define (foo)
(cons 'a 5))
(let* ((r (foo))
(x (car r))
(y (cdr r)))
(display x) (display y) (newline))
You can generalise this to return multiple values in a list, too.

Resources