Understanding objects with local state -- Scheme - lisp

i'm studying for my scheme final and objects with local state has always been a tough subject.
Here is a question from my final exam that i need help on.
(define (make-incrementer n)
(let ((old 0)
(new 0))
(lambda ()
(cond ((< new n)
(set! old new)
(set! new (+ new 1))
old)
(else
(set! old 0)
(set! new 1)
old)))))
(define a (make-incrementer 3))
(define b (make-incrementer 3))
(define c a)
; 1) (a)
; 2) (a)
why when a is called the second time it returns 1? I'm looking at the code and the n we give it is always 3. So wouldn't it always do the else case?

Welcome to the wonderful world of closures! This is a textbook example of how closures in Scheme work.
So make-counter returns a function that has 3 variables that it captures from it's enclosing environment: n, old, new. In this case, the starting environment looks something like
_name_|_value_
n | 3
old | 0
new | 1
On each invocation, it increments old and new and wraps them around if they're greater than n. Because it's using set!, this incrementing is mutating the variables in the lambda's environment, but since these variables are captured from the surrounding environment, they are changed for all future calls as well.
That's why you get different returns even with the same input.
If this seems like witchcraft, you can think of it like objects in more common languages:
Eg Python:
class Foo():
def __init__(self, n, m):
self.n = n
self.m = m
def count(self):
self.n += 1
if self.n == self.m:
self.n = 1
return self.n-1
f = Foo(0, 2)
f.count() # 1
f.count() # 0
This is the same basic idea except here we're being a bit more explicit about where the environment is coming from, self. In Scheme, we mimic this with the lambda capturing the surrounding variables.
For more, check out SICP

Here are some examples, that might help with the concept of capturing state:
(define (always x)
(lambda rest x))
(define always-true (always #t))
(always-true #f)
-> #t
(define (add-n n)
(lambda (m)
(+ n m)))
(define add-1 (add-n 1))
(add-1 10)
-> 11
(define (complement predicate)
(lambda (x)
(not (predicate x)))
(define not-positive? (complement positive?))
(not-positive? -1)
-> #t
Next is an example where the captured state, in this case l, is mutated. This is similar to your case where new and old are captures and modified.
(define (nexting l)
(lambda ()
(if (null? l)
'()
(let ((answer (car l)))
(set! l (cdr l))
answer))))
(define next-user (nexting '(Alice Bob David)))
(next-user)
-> Alice
(next-user)
-> Bob
(next-user)
-> David
(next-user)
'()

Related

Difference between '(()) and (cons null null)

I am confused about the difference between '(()) and (cons null null) in scheme.
The code below show that b and c are completely the same thing.
(define (dup2 x)
(let ((d '(())))
(set-car! d (car x))
(set-cdr! d (cdr x))
d))
(define a '(1 2))
(define b (dup2 a))
(define c (dup2 a))
(set-car! b 2)
> c ;; --> (2 2)
However, when I used dup instead of dup2:
(define (dup x)
(let ((d (cons null null)))
(set-car! d (car x))
(set-cdr! d (cdr x))
d))
(define a '(1 2))
(define b (dup a))
(define c (dup a))
(set-car! b 2)
> c ;; --> (1 2)
Variable b and c are different. I have done some experiments, but I haven't understand yet.
The value of d in the first implementation is literal data, and is modified with undefined consequences. To highlight what's happening, consider the following code:
(define (incorrect-list-null-and-x x)
(let ((l '(()))) ; a list of the form (() . ())
(set-cdr! l (cons x (cdr l))) ; (cdr l) is (), so (cons x (cdr l)) should be (x . ()) == (x), right?
; and now l should be (() . (x . ())) == (() x), right?
l))
The expected result is that (incorrect-list-null-and-x n) should return a list of the form (() n), and it does the first time, but successive calls are still accessing the same data:
(incorrect-list-null-and-x 1) ;=> (() 1)
(incorrect-list-null-and-x 2) ;=> (() 2 1)
(incorrect-list-null-and-x 3) ;=> (() 3 2 1)
(incorrect-list-null-and-x 4) ;=> (() 4 3 2 1)
The same problem manifests itself a bit differently in your dup2. Every value returned from dup2 is actually the same pair:
(let* ((x (dup2 (cons 1 2)))
(y (dup2 (cons 3 4))))
(display x)
(display y))
outputs:
(3 . 4)(3 . 4)
because the call (dup2 (cons 3 4)) modifies the same structure that was previously returned by (dup2 (cons 1 2)).
Data literals, like '(()), are meant to be read-only, and modifying it using set-car! or set-cdr! has undefined behaviour. For predictable behaviour, use the (cons '() '()) version if you want to use set-car! or set-cdr! on it.
In particular, cons creates a new cons cell, whereas a data literal usually won't.
Still, for the purposes of implementing dup, why are you using set-car! and set-cdr! anyway? Just use cons directly:
(define (dup x)
(cons (car x) (cdr x)))
In your first code snippet you use (d '(())) which ends up binding a literal to d. You then modify the literal which is generally undefined. In your second code snippet you use (d (cons null null)) which binds d to a newly created 'cons cell' which you then modify. There is no problem modifying that.
Note: you've not defined null. Perhaps you meant '()?

How do I find the index of an element in a list in Racket?

This is trivial implement of course, but I feel there is certainly something built in to Racket that does this. Am I correct in that intuition, and if so, what is the function?
Strangely, there isn't a built-in procedure in Racket for finding the 0-based index of an element in a list (the opposite procedure does exist, it's called list-ref). However, it's not hard to implement efficiently:
(define (index-of lst ele)
(let loop ((lst lst)
(idx 0))
(cond ((empty? lst) #f)
((equal? (first lst) ele) idx)
(else (loop (rest lst) (add1 idx))))))
But there is a similar procedure in srfi/1, it's called list-index and you can get the desired effect by passing the right parameters:
(require srfi/1)
(list-index (curry equal? 3) '(1 2 3 4 5))
=> 2
(list-index (curry equal? 6) '(1 2 3 4 5))
=> #f
UPDATE
As of Racket 6.7, index-of is now part of the standard library. Enjoy!
Here's a very simple implementation:
(define (index-of l x)
(for/or ([y l] [i (in-naturals)] #:when (equal? x y)) i))
And yes, something like this should be added to the standard library, but it's just a little tricky to do so nobody got there yet.
Note, however, that it's a feature that is very rarely useful -- since lists are usually taken as a sequence that is deconstructed using only the first/rest idiom rather than directly accessing elements. More than that, if you have a use for it and you're a newbie, then my first guess will be that you're misusing lists. Given that, the addition of such a function is likely to trip such newbies by making it more accessible. (But it will still be added, eventually.)
One can also use a built-in function 'member' which gives a sublist starting with the required item or #f if item does not exist in the list. Following compares the lengths of original list and the sublist returned by member:
(define (indexof n l)
(define sl (member n l))
(if sl
(- (length l)
(length sl))
#f))
For many situations, one may want indexes of all occurrences of item in the list. One can get a list of all indexes as follows:
(define (indexes_of1 x l)
(let loop ((l l)
(ol '())
(idx 0))
(cond
[(empty? l) (reverse ol)]
[(equal? (first l) x)
(loop (rest l)
(cons idx ol)
(add1 idx))]
[else
(loop (rest l)
ol
(add1 idx))])))
For/list can also be used for this:
(define (indexes_of2 x l)
(for/list ((i l)
(n (in-naturals))
#:when (equal? i x))
n))
Testing:
(indexes_of1 'a '(a b c a d e a f g))
(indexes_of2 'a '(a b c a d e a f g))
Output:
'(0 3 6)
'(0 3 6)

LISP - count occurences of every value in a list

I apologize for the bad English..
I have a task to write a function called "make-bag" that counts occurences of every value in a list
and returns a list of dotted pairs like this: '((value1 . num-occurences1) (value2 . num-occurences2) ...)
For example:
(make-bag '(d c a b b c a))
((d . 1) (c . 2) (a . 2) (b . 2))
(the list doesn't have to be sorted)
Our lecturer allows us to us functions MAPCAR and also FILTER (suppose it is implemented),
but we are not allowed to use REMOVE-DUPLICATES and COUNT-IF.
He also demands that we will use recursion.
Is there a way to count every value only once without removing duplicates?
And if there is a way, can it be done by recursion?
First of, I agree with Mr. Joswig - Stackoverflow isn't a place to ask for answers to homework. But, I will answer your question in a way that you may not be able to use it directly without some extra digging and being able to understand how hash-tables and lexical closures work. Which in it's turn will be a good exercise for your advancement.
Is there a way to count every value only once without removing duplicates? And if there is a way, can it be done by recursion?
Yes, it's straight forward with hash-tables, here are two examples:
;; no state stored
(defun make-bag (lst)
(let ((hs (make-hash-table)))
(labels ((%make-bag (lst)
(if lst
(multiple-value-bind (val exists)
(gethash (car lst) hs)
(if exists
(setf (gethash (car lst) hs) (1+ val))
(setf (gethash (car lst) hs) 1))
(%make-bag (cdr lst)))
hs)))
(%make-bag lst))))
Now, if you try evaluate this form twice, you will get the same answer each time:
(gethash 'a (make-bag '(a a a a b b b c c b a 1 2 2 1 3 3 4 5 55)))
> 5
> T
(gethash 'a (make-bag '(a a a a b b b c c b a 1 2 2 1 3 3 4 5 55)))
> 5
> T
And this is a second example:
;; state is stored....
(let ((hs (make-hash-table)))
(defun make-bag (lst)
(if lst
(multiple-value-bind (val exists)
(gethash (car lst) hs)
(if exists
(setf (gethash (car lst) hs) (1+ val))
(setf (gethash (car lst) hs) 1))
(make-bag (cdr lst)))
hs)))
Now, if you try to evaluate this form twice, you will get answer doubled the second time:
(gethash 'x (make-bag '(x x x y y x z z z z x)))
> 5
> T
(gethash 'x (make-bag '(x x x y y x z z z z x)))
> 10
> T
Why did the answer doubled?
How to convert contents of a hash table to an assoc list?
Also note that recursive functions usually "eat" lists, and sometimes have an accumulator that accumulates the results of each step, which is returned at the end. Without hash-tables and ability of using remove-duplicates/count-if, logic gets a bit convoluted since you are forced to use basic functions.
Well, here's the answer, but to make it a little bit more useful as a learning exercise, I'm going to leave some blanks, you'll have to fill.
Also note that using a hash table for this task would be more advantageous because the access time to an element stored in a hash table is fixed (and usually very small), while the access time to an element stored in a list has linear complexity, so would grow with longer lists.
(defun make-bag (list)
(let (result)
(labels ((%make-bag (list)
(when list
(let ((key (assoc (car <??>) <??>)))
(if key (incf (cdr key))
(setq <??>
(cons (cons (car <??>) 1) <??>)))
(%make-bag (cdr <??>))))))
(%make-bag list))
result))
There may be variations of this function, but they would be roughly based on the same principle.

Can set-car! and set-cdr! be implemented as macros?

Is it possible to implement set-car! and set-cdr! portably as macros using set! in Scheme? Or would this require special access to the underlying storage system?
I'm asking because I'm implementing my own Scheme interpreter, and I'd like to have as much as possible out in scheme code.
My first attempt on set-cdr! was:
(define-syntax set-cdr!
(syntax-rules ()
((set-cdr! location value)
(set! location (cons (car location) value)))))
This mostly works, but not for circular lists:
#; mickey> (define x (list 1 2))
#; mickey> x
(1 2)
#; mickey> (set-cdr! x x)
#; mickey> x
(1 1 2)
Wrapping the macro body in let did not help me either, because when I do (set! (cons (car location) value), then value has already been evaluated to be '(1 2).
In
(set! location (cons (car location) value))
the expression (cons (car location) value) allocates a new pair.
The purpose of set-cdr! is to mutate an existing pair.
So implementing set-cdr! does require "special" access to the underlying storage.
Here is an example of implementing Cons, Car, Cdr, Set-car! and Set-cdr! using closures.
(define (Cons x y)
(lambda (message . val)
(cond
[(eq? message 'car) x]
[(eq? message 'cdr) y]
[(eq? message 'set-car!)
(set! x (car val))]
[(eq? message 'set-cdr!)
(set! y (car val))]
[else 'unknown-message])))
(define (Car pair)
(pair 'car))
(define (Cdr pair)
(pair 'cdr))
(define (Set-cdr! pair val)
(pair 'set-cdr! val))
(define (Set-car! pair val)
(pair 'set-car! val))
(define p (Cons 1 2))
(Car p)
(Cdr p)
(Set-car! p 3)
(Car p)
(Set-cdr! p 4)
(Cdr p)
Basically you can implement set! without set!, but I don't think you can implement set-car!/set-cdr! without either mutating pairs or simulating pairs (like soegaard's example)
Since it seems you're making your Scheme implementation in Scheme I would have used set-car!/set-cdr! to implement it in the interpreter or just not implemented them at all. I would have started with define, if, quote, pair?, eq?, cons, car and cdr (similar to The roots of LISP, but more schemish) to have a base minimum implementation to start with and then enhanced it further.
Anyway.. Your implementation, if you do implement it should be able to do this:
(define odds (list 1 3 5 7 9 11))
(set-car! (cddr odds) #f)
odds
===> (1 3 #f 7 9 11)

create racket accumulator "variable"

Im really having problems understanding how I can create variable that would act as an accumulator in racket. This is definitely a really stupid question....but racket's documentation is pretty difficult for me to read.
I know I will use some kind of define statement or let statement.
I want to be able to pass a number to a variable or function and it adds the current value with the new value keeps the sum...How would I do this....?? Thank you..
(define (accumulator newvalue) "current=current+newvalue"
something like this..
An accumulator is generally just a function parameter. There are a few chapters in How to Design Programs (online, starting here) that cover accumulators. Have you read them?
For example, the reverse function is implemented using an accumulator that remembers the prefix of the list, reversed:
;; reverse : list -> list
(define (reverse elems0)
;; reverse/accum : list list -> list
(define (reverse/accum elems reversed-prefix)
(cond [(null? elems)
reversed-prefix]
[else
(reverse/accum (cdr elems)
(cons (car elems) reversed-prefix))]))
(reverse/accum elems null))
Note that the scope of the accumulator reversed-prefix is limited to the function. It is updated by calling the function with a new value for that parameter. Different calls to reverse have different accumulators, and reverse remembers nothing from one call to the next.
Perhaps you mean state variable instead. In that case, you define it (or bind it with let or lambda) at the appropriate scope and update it using set!. Here's a global state variable:
;; total : number
(define total 0)
;; add-to-total! : number -> number
(define (add-to-total! n)
(set! total (+ total n))
total)
(add-to-total! 5) ;; => 5
(add-to-total! 31) ;; => 36
Here's a variation that creates local state variables, so you can have multiple counters:
;; make-counter : -> number -> number
(define (make-counter)
(let ([total 0])
(lambda (n)
(set! total (+ total n))
total)))
(define counterA (make-counter))
(define counterB (make-counter))
(counterA 5) ;; => 5
(counterB 10) ;; => 10
(counterA 15) ;; => 20
(counterB 20) ;; => 30
But don't call state variables accumulators; it will confuse people.
Do you mean something like this?
(define (accumulator current newvalue)
(let ((current (+ current newvalue)))
...)
You can close over the accumulator variable:
(define accumulate
(let ((acc 0))
(λ (new-val)
(set! acc (+ acc new-val))
acc)))
(accumulate 10) ;=> 10
(accumulate 4) ;=> 14