Detecting the caller of a function in Scheme or Racket - scheme

In Scheme or Racket is it possible to detect the caller of a function?
For example, I can write a function to test if a list is a list of atoms as follows:
(define atom? (lambda (x) (and (not (pair? x)) (not (empty? x)))))
(define lat? (lambda (l)
(define latt?
(lambda (l)
(cond
((null? l) #t)
((atom? (car l)) (latt? (cdr l)))
(else #f))))
(if (null? l) #f (latt? l))))
but instead of the above, is there a function like "called-by" to do something like this:
(define lat?
(lambda (l)
(cond
((and (null? l) (called-by "lat?")) #t)
((atom? (car l)) (lat? (cdr l)))
(else #f))))

The usual way to do this is to add some argument to the function, or make a loop via an internal definition as you did. Other than that, there is no reliable way to find out the caller of a function.
But in your case, it seems like a good lack of feature -- using it for the above problem is pretty bad. There's nothing wrong with the internal helper version. (It's also quite similar to any other language.)
Finally, I'd expect (lat? null) to return #t since it is a list that has only atoms as elements.

Related

Issue unbound variable in chez scheme

I am defining a function replaceOccurrence that replaces the first occurrence of either of two symbols. I don't understand why list variable is not bound
Chez Scheme Version 9.5
(define replaceOcurrence
(λ (new ocurrence1 ocurrence2 lista)
(cond
((null? lista) '())
(else (cond
((eq? ocurrence1 (car lista))
(cons new (cdr (lista))))
((eq? ocurrence2 (car lista))
(cons new (cdr (lista))))
(else (cons (car lista)
(replaceOcurrence new ocurrence1 ocurrence2 (cdr lista)))))))))
Exception: variable lista is not bound
Chez Scheme does not support λ as a replacement for lambda. Racket does, and says so explicitly in the documentation. Guile appears to support λ too, but I don't see that documented. Since λ is not recognized as a special form in Chez Scheme, the arguments to λ are evaluated first, and since they have not yet been bound, the reported error is issued.
There is another problem in the OP code: lista is alone in parentheses twice; this attempts to call lista as a procedure each time. Also, occurrence is spelled with two Cs; and prefer kebab-case to camelCase in Scheme. Here is the fixed code:
(define replace-occurrence
(lambda (new occurrence1 occurrence2 lista)
(cond
((null? lista) '())
(else
(cond
((eq? occurrence1 (car lista))
(cons new (cdr lista)))
((eq? occurrence2 (car lista))
(cons new (cdr lista)))
(else
(cons (car lista)
(replace-occurrence new occurrence1 occurrence2 (cdr lista)))))))))
The best, and most portable, way to solve OP problem is to simply use lambda. But, if one really wants to use λ, a macro can be used to provide the necessary syntax:
(define-syntax λ
(syntax-rules ()
[(_ formals . body)
(lambda formals . body)]))
With the inclusion of the above macro (and the other necessary changes mentioned in the first part of the answer), OP code can use λ in place of lambda.

How to check if first and last element in a list are identical (Language: Scheme)

I am writing a program in Scheme and having difficulty with this one part. Below is an example to make my question clear
(endsmatch lst) should return #t if the first element in the list is the same as the last element in the list and return #f otherwise.
For example:
(endsmatch '(s t u v w x y z)) should return: #f
and
(endsmatch (LIST 'j 'k 'l 'm 'n 'o 'j)) should return: #t
Here is what I have so far (just error handling). The main issue I am having is solving this recursively. I understand there are easier solutions that are not recursive but I need to solve this using recursion.
My code so far:
(define (endsmatch lst)
(if (not(list? lst))
"USAGE: (endsmatch [list])"
(if (or (null? lst)
(= (length lst) 1))
#t
(equal? ((car lst)) (endsmatch(car lst)))
)))
I believe my code starting at "(equal? " is where it is broken and doesn't work. This is also where I believe recursion will take place. Any help is appreciated!
Easiest way is to use a (recursive) helper function to do the looping:
(define (endsmatch lst)
(define (helper no1 lst)
(if (null? (cdr lst))
(equal? no1 (car lst))
(helper no1 (cdr lst))))
(if (or (not (list? lst)) (null? lst))
"USAGE: (endsmatch [list])"
(helper (car lst) lst)))
The reason I pass lst and not (cdr lst) as the second argument in the last line is so that it also works for 1-element lists.
I tend to use KISS when programming. aka. "Keep it simple, stupid!"
With that regard I would have oped for:
(define (ends-match? lst)
(or (null? lst)
(equal? (car lst)
(last lst))))
Now last we can define like this:
(define (last lst)
(foldl (lambda (e a) e) last lst))
It's not perfect. It should signal an error if you pass an empty list, but in the ends-match? you check for this and thus it's not a problem.

Scheme if-statement

I'm currently studying Scheme with The Little Schemer and ran into an odd trouble.
Here is my code:
(define rember
(lambda (a lat)
((if (null? lat)
'()
(cond
((eq? a (car lat)) (cdr lat))
(else (rember a (cdr lat))))))))
(rember 'aaa '(bbb aaa))
I used an "if" instead of "cond" in the textbook. When returning from the tail-recursion, it shows this error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: '()
arguments...: [none]
I guess this is because it treats '() in the if-statement as a function and the return value of the tail-recursion as its argument. But since the book doesn't give me so many details about the language, could you explain this a bit for me? (e.g. Is this in fact some kind of language feature? Is there any way that I can stick to "if" in this piece of code? And when can I use "if" safely?)
Thanks.
You have an extra set of parentheses around your if. This
((if (null? lat)
'()
(cond
((eq? a (car lat)) (cdr lat))
(else (rember a (cdr lat))))))
should be this:
(if (null? lat)
'()
(cond
((eq? a (car lat)) (cdr lat))
(else (rember a (cdr lat)))))
Those extra parentheses tell Scheme that you want to call the result of the if like a function, so you get the error saying that '() isn't a function.

Scheme evaluation order standard

I've got a program I'm writing for a class to substitute the left-most occurrence of a variable with a new variable. (It actually allows you to provide an equivalence relation yourself, as well). The thing is, in Chez Scheme 8.2, this substitutes the right-most occurrence, if the left most is inside a list. We use a server running some version of scheme (I'm not sure which version), and on the server it substitutes, correctly, the left-most occurrence. Below is the code:
(define subst-leftmost
(lambda (new old ls proc)
(let ([keep-going? #t])
(letrec ([helper
(lambda (ls)
(cond [(null? ls) ls]
[(or (pair? (car ls)) (null? (car ls)))
(cons (helper (car ls)) (helper (cdr ls)))]
[(and keep-going? (proc old (car ls)))
(set! keep-going? #f) (cons new (cdr ls))]
[else (cons (car ls) (helper (cdr ls)))]))]) (helper ls))))
This is called like so: (subst-leftmost 'x 'a '(d b c (a) b a) eq?) which should produce the output (d b c (x) b a), and does on the server. In Chez scheme, however, it produces (d b c (a) b x). I think the difference is due to the line
[(or (pair? (car ls)) (null? (car ls)))
(cons (helper (car ls)) (helper (cdr ls)))]
evaluating the helper of the car and the helper of the cdr in a not-set order.
My question is this: Which version of scheme is following the standard, and how can I modify my code so that it works correctly in both versions?
(I've already talked to my professor about this. He's going to address the class about it on Monday, once he can think about it some, but I'm curious. I also already got the full points for the assignment, so don't worry about the ethics of helping me, in that regard.)
There isn't any, sorry. Here's the relevant legalese. Use LETs or LET* if you need to evaluate sub-expressions in a particular order.
Scheme guarantees no specific order (as Cirno has said). If your code has no side-effects, this doesn't matter.
However, your code is side-effecting (because of the set! to an outside variable), so, you have some choices:
Use Racket (which is committed to using left-to-right order, last time I talked to a Racket dev)
Structure your code to remove side-effects, so that your helper function doesn't change any variable or state outside it
Use appropriate lets to ensure the ordering you need (as Cirno suggested); in particular, change (cons (helper (car ls)) (helper (cdr ls))) to:
(let ((depth-first (helper (car ls))))
(cons depth-first (helper (cdr ls))))

Scheme Deep reverse function

I am doing a scheme program which takes in a list and then reverse it. So far it works for simple list, which does not contain any sublist, but when I test it for a list contains sublist, it fails. Please help me where is wrong with it.
Here is the code:
(define deep-reverse
(lambda (L)
(cond
((empty? L) '())
(else (append (deep-reverse (rest L)) (list (first L)))))))
(define (deeprev L)
(if (null? L) '()
(if (list? (car L))
(if (chek (car L)) (append (deeprev (cdr L)) (list (reverse (car L))))
(append (deeprev (cdr L)) (list (deeprev (car L)))))
(append (deeprev (cdr L)) (list (car L))))))
First of all, you are using undefined Scheme functions. I am going to work off the following assumptions:
empty? is null?
rest is cdr
first is car
Your code works by taking the first element in a list and adding it to another list. However, that first element of a list can be a list itself. You need to test to see if the element that you're working on is atomic or a list. If it's a list, then you call deep-reverse recursively.
If you would like to see code appended to this, leave a comment.

Resources