Racket, Error: Cannot reference an identifier before its definition - racket

The function should return (set 'n0 'n1) when (get-backlinks '((n0 n1) (n1 n2) (n0 n2)) n2) as input. But I got an error :
n2: undefined;
cannot reference an identifier before its definition**
Here is the code:
(define (get-backlinks graph page)
(define (helper graph sets)
(match graph
['() (list->set graph)]
[`((,a ,b) . ,rst)
(if (equal? b page)
(helper rst (cons a sets))
(helper rst sets))]))
(helper graph '()))
I don't really understand where went wrong

Related

Repeating elements in scheme [duplicate]

This code in Scheme is used to output a list in which the element of the input lists are repeated n times. I do not understand what is happening in the code.
(define (echo-lots lst n)
(define (helper lst1 n1)
(if (= n1 0)
'()
(cons lst1 (helper lst1 (- n1 1)))))
(if (null? lst)
'()
(append (helper (car lst) n) (echo-lots (cdr lst) n)))
First, note that helper does not use any of the parameters of echo-lots.
That means that you can move the definition outside and figure it out in isolation:
(define (helper lst1 n1)
(if (= n1 0)
'()
(cons lst1 (helper lst1 (- n1 1)))))
> (helper 1 3)
'(1 1 1)
> (helper #f 4)
'(#f #f #f #f)
> (helper '(a b c) 2)
'((a b c) (a b c))
It makes a list whose elements are the first parameter repeated the number of times given by the second parameter.
(It's not difficult to prove this formally, if you're in the mood for that.)
Note also that the first parameter's name is misleading - it does not have to be a list.
Let's improve the naming:
(define (repeat item n)
(if (= n 0)
'()
(cons item (repeat item (- n 1)))))
Now echo-lots is clearer:
(define (echo-lots lst n)
(if (null? lst)
'()
(append (repeat (car lst) n)
(echo-lots (cdr lst) n))))
and it's easier to see that it makes a list of n copies of the first element of lst - (repeat (car lst) n) - and appends that to a list consisting of n copies of each of the remaining elements - (echo-lots (cdr lst) n).

Racket - Find lists that has the same element in a 2D list

Can someone please show me how to do this problem/give me a template? I'm not allowed to use map or lambda or any other advanced built-in functions, only list
First extract the country associated with the input string:
(define (get-country l s)
(cond [(empty? (rest l)) (second (second (first l)))]
[else (if (equal? s (first (first l)))
(second (second (first l)))
(get-country (rest l) s))]))
Then extract all strings that have that country associated with it:
(define (get-countries l s)
(cond [(empty? l) '()]
[else (if (equal? s (second (second (first l))))
(cons (first (first l)) (get-countries (rest l) s))
(get-countries (rest l) s))]))
Then put them together:
(define (same-country l s)
(get-countries l (get-country l s)))
When we evaluate we get a result different from (list "YUL" "YVR" "YWG" "YYZ"):
> (same-country alist "YUL")
(list "YYZ" "YWG" "YUL" "YVR")
So we check if the result is a permutation of the desired list. First we make is-permutation:
(define (is-permutation l1 l2)
(and (not (and (cons? l1) (empty? l2)))
(not (and (empty? l1) (cons? l2)))
(or (and (empty? l1) (empty? l2))
(and (is-member (first l1) l2)
(is-permutation (rest l1)
(remove-one (first l1) l2))))))
(define (is-member e l)
(and (not (empty? l))
(or (equal? (first l) e)
(is-member e (rest l)))))
(define (remove-one e nel)
(cond [(empty? (rest nel)) '()]
[else (if (equal? (first nel) e)
(rest nel)
(cons (first nel) (remove-one e (rest nel))))]))
Then we can test:
> (is-permutation (same-country alist "YUL")
(list "YUL" "YVR" "YWG" "YYZ"))
#true

Count of atoms on the each level, Scheme

Please, help me with one simple exercise on the Scheme.
Write function, that return count of atoms on the each level in the
list. For example:
(a (b (c (d e (f) k 1 5) e))) –> ((1 1) (2 1) (3 2) (4 5) (5 1))
My Solution:
(define (atom? x)
(and (not (pair? x)) (not (null? x))))
(define (count L)
(cond ((null? L) 0)
((pair? (car L))
(count (cdr L)))
(else
(+ 1 (count (cdr L))))))
(define (fun L level)
(cons
(list level (count L))
(ololo L level)))
(define (ololo L level)
(if (null? L)
'()
(if (atom? (car L))
(ololo (cdr L) level)
(fun (car L) (+ level 1)))))
(fun '(a (b (c (d e (f) k 1 5) e))) 1)
It's work fine, but give not correctly answer for this list:
(a (b (c (d e (f) (k) 1 5) e)))
is:
((1 1) (2 1) (3 2) (4 4) (5 1))
But we assume that 'f' and 'k' on the one level, and answer must be:
((1 1) (2 1) (3 2) (4 4) (5 2))
How should I edit the code to make it work right?
UPD (29.10.12):
My final solution:
(define A '(a (b (c (d e (f) k 1 5) e))))
(define (atom? x)
(and (not (pair? x)) (not (null? x))))
(define (unite L res)
(if (null? L) (reverse res)
(unite (cdr L) (cons (car L) res))))
(define (count-atoms L answ)
(cond ((null? L) answ)
((pair? (car L))
(count-atoms (cdr L) answ))
(else
(count-atoms (cdr L) (+ answ 1)))))
(define (del-atoms L answ)
(cond ((null? L) answ)
((list? (car L))
(begin
(del-atoms (cdr L) (unite (car L) answ))))
(else
(del-atoms (cdr L) answ))))
(define (count L)
(define (countme L level answ)
(if (null? L) (reverse answ)
(countme (del-atoms L '()) (+ level 1) (cons (cons level (cons (count-atoms L 0) '())) answ))))
(countme L 1 '()))
(count A)
What can you say about this?
Do you know what you get if you run this?
(fun '(a (b (c (d e (f) k 1 5) e)) (a (b (c)))) 1)
You get this:
((1 1) (2 1) (3 2) (4 5) (5 1))
The whole extra nested structure that I added on the right has been ignored. Here is why...
Each recursion of your function does two things:
Count all the atoms at the current "level"
Move down the level till you find an s-expression that is a pair (well, not an atom)
Once it finds a nested pair, it calls itself on that. And so on
What happens in oLoLo when fun returns from the first nested pair? Why, it returns! It does not keep going down the list to find another.
Your function will never find more than the first list at any level. And if it did, what would you to do add the count from the first list at that level to the second? You need to think carefully about how you recur completely through a list containing multiple nested lists and about how you could preserve information at each level. There's more than one way to do it, but you haven't hit on any of them yet.
Note that depending on your implementation, the library used here may need to be imported in some other way. It might be painstakingly difficult to find the way it has to be imported and what are the exact names of the functions you want to use. Some would have it as filter and reduce-left instead. require-extension may or may not be Guile-specific, I don't really know.
(require-extension (srfi 1))
(define (count-atoms source-list)
(define (%atom? x) (not (or (pair? x) (null? x))))
(define (%count-atoms source-list level)
(if (not (null? source-list))
(cons (list level (count %atom? source-list))
(%count-atoms (reduce append '()
(filter-map
(lambda (x) (if (%atom? x) '() x))
source-list)) (1+ level))) '()))
(%count-atoms source-list 1))
And, of course, as I mentioned before, it would be best to do this with hash-tables. Doing it with lists may have some didactic effect. But I have a very strong opposition to didactic effects that make you write essentially bad code.

Evaluation of {with {x 3} {+ x x}} from page 76 in PLAI

I am studying PLAI's Chapter8 "Implementing Laziness", and finished the following CFAE/L:
(define-type CFAE/L
[num (n number?)]
[add (lhs CFAE/L?)(rhs CFAE/L?)]
[id (name symbol?)]
[fun (param symbol?)(body CFAE/L?)]
[app (fun-expr CFAE/L?)(arg-expr CFAE/L?)])
(define-type CFAE/L-Value
[numV (n number?)]
[closureV (param symbol?)
(body CFAE/L?)
(env Env?)]
[exprV (expr CFAE/L?)
(env Env?)])
(define-type Env
[mtSub]
[aSub (name symbol?)(value CFAE/L-Value?)(env Env?)])
(define (num+ x y) ;; need this because we can't just use Scheme + to add FAE-values
(numV (+ (numV-n x) (numV-n y))))
(define (parse sexp)
(cond [(number? sexp) (num sexp)]
[(symbol? sexp) (id sexp)]
[(list? sexp)
(case (first sexp)
((+)
(add (parse (second sexp))
(parse (third sexp))))
((with)
(app (fun (first (second sexp))
(parse (third sexp)))
(parse (second (second sexp)))))
((fun)
(fun (first (second sexp))
(parse (third sexp))))
(else
(app (parse (first sexp))
(parse (second sexp)))))]))
(define (lookup name env)
(type-case Env env
[mtSub() (error 'lookup "no binding for identifier")]
[aSub (bound-name bound-value rest-ds)
(if (symbol=? bound-name name)
bound-value
(lookup name rest-ds))]))
(define (interp expr env)
(type-case CFAE/L expr
[num (n) (numV n)]
[add (l r)(num+ (interp l env)(interp r env))]
[id (v) (lookup v env)]
[fun (bound-id bound-body)
(closureV bound-id bound-body env)]
[app (fun-expr arg-expr)
(local ([define fun-val (interp fun-expr env)]
[define arg-val (exprV arg-expr env)])
(interp (closureV-body fun-val)
(aSub (closureV-param fun-val)
arg-val
(closureV-env fun-val))))]))
According to this interpreter, I want to evaluate the page76's
{with {x 3} {+ x x}}
(1) when typing:
(interp (parse '{with {x 3} {+ x x}}) {mtSub})
I got errors as below:
numV-n: contract violation, expected: numV?, given: (exprV (num 3) (mtSub))
contract from: numV-n, blaming: use
contract: (-> numV? number?)
at: /study/lisp/plai/chapter8.scm:10.9
(2) I wanted to write down the steps by hand for understanding page76's description as below:
"The interpreter evaluates each x in the body to an expression closure (because that’s what is bound to x in the environment), but the addition procedure cannot handle these: it (and similarly any other arithmetic primitive) needs to know exactly which number the expression closure corresponds to.", but I am still not clear about this description after finishing the steps. there are my steps : (interp (parse '(with (x 3) (+ x x))) (mtSub))
step1: (parse '(with (x 3) (+ x x))) => (app (fun 'x (add (id 'x) (id 'x))) (num 3))
NOTE: fun-exp is (fun 'x (add (id 'x), arg-expr is (num 3)
step2: (cloSureV 'x (add (id 'x) (id 'x)) (mtSub)) (as fun-val)
and (experV (num 3) (mtSub)) (as arg-val)
step3: (interp (add (id 'x) (id 'x)) (aSub 'x (num 3) (mtSub)))
Thanks in advance!
Ad 1)
This is the expected behaviour. The error message you got was:
numV-n: contract violation,
expected: numV?,
given: (exprV (num 3) (mtSub))
...
This numV-n was the one in num+. This es explained in the last
paragraph of page 75. The primitives such as num+ expected non-closure
values, but the value (exprV (num 3) (mtSub)) is the number 3 closed
over the empty environment.
Therefore the primitives such as num+ must force the arguments.
From page 76:
(define (num+ n1 n2)
(numV (+ (numV-n (strict n1) ) (numV-n (strict n2) ))))
Ad 2)
Do the explanation of 1) help with 2) ?
ADDED
Why not let the interpreter write out the steps for you?
The quick fix:
(define (interp expr env)
(displayln (list 'expr expr 'env env))
(type-case CFAE/L expr
To get more readable output, first write unparse that converts
a CFAE/L to a (readable) string.

unfold function in scheme

Goal: implement unfold function using only two arguments.
The arguments:
the first argument is f which takes an initial value of some type I and returns nil or a cons pair of two elements (the first of these two is the next element that goes in the list of some type A and the next initial value again of some type I).
The second argument is an initial value of some type I and the return is a list of items of type A.
This is what I have so far and I am not sure why it is not working:
(define (descending i)
(if (= i 0)
(list)
(cons i (- i 1))))
(define nil (list))
(define (unfold f init)
(if (eq? (f init) '())
(list)
(cons init (unfold f (f init)))))
(unfold (descending 5))
should evaluate to
'(5 4 3 2 1)
This should be the result but isn't. What am I doing wrong?
First, it should be (unfold descending 5). Then f would produce a pair and you would use both components of it,
(define (unfold f init)
(if (eq? (f init) '())
(list)
(cons (car (f init)) (unfold f (cdr (f init))))))
But this has awful computational complexity as it calls (f init) three times per iteration. A humble let binding remedies this.
(define (unfold f init)
(let ((r (f init)))
(if (empty? r) ;; instead of (eq? r '())
(list)
(cons (car r) (unfold f (cdr r))))))
And a tail recursive form using named let
(define (unfold f init)
(let loop ((acc empty)
(state (f init)))
(if (empty? state)
(reverse acc)
(loop (cons (car state) acc)
(f (cdr state))))))
And using match.
(define (unfold f init)
(let loop ((acc empty)
(state (f init)))
(match state
((cons x next)
(loop (cons x acc)
(f next)))
(empty
(reverse acc)))))