Why defining a recursive-display procedure in Guile causes infinite loop? - scheme

The following procedure causes an infinite loop:
(define (recursive-display . args)
(if (null? args)
#t
(begin
(display (car args))
(recursive-display (cdr args)))))
I'm still learning about Guile so I'm a bit confused why that's the case.

Use display to print the value of args and look at the output:
(define (recursive-display . args)
(if (null? args)
#t
(begin
(display args)
(recursive-display (cdr args)))))
> (recursive-display 1 2 3)
(1 2 3)
((2 3))
(())
(())
(())
...
Your function recursive-display has a variable number of arguments. When you call something like (recursive-display 1 2 3), all arguments passed to this function are wrapped in the list, so variable args has a value '(1 2 3).
Next, you call (recursive-display (cdr args)). The same rule applies again- all arguments are wrapped in the list, so args has now value '((2 3)).
In all following iterations, args has a value '(()).
When you add apply, it will work as expected:
(define (recursive-display . args)
(if (null? args)
#t
(begin
(display (car args))
(apply recursive-display (cdr args)))))
> (recursive-display 1 2 3)
123#t

Related

Scheme returns #<procedure>, not a value

I am trying to use the unrestricted lambda in order to apply an arbitrary number of procedures on one argument. My code returns '#procedure' rather than a value (I was expecting ((compose-many add1 add1 add1) 3) => 6). Please clarify my mistake. Thank you.
(define compose-many
(lambda args
(lambda (x)
(cond
((null? args)
x)
((null? (cdr args))
(car args) x)
(else (car args) (compose-many (cdr args)))))))
((compose-many add1 add1 add1) 3)
In your code, when you call the recursion you're expected to again pass values to the parameters in (lambda args (lambda (x) ...)), when the correct would be to just iterate over the args. Also, you forgot to actually apply the procedures! An expression like this: ((null? (cdr args)) (car args) x) ignores the result of (car args) and just returns x.
To see this more clearly, let's see how the solution should look for a case in particular, say - we only have to compose three procedures. Notice that we return a single lambda and how the procedures are applied:
(define (compose f g h)
(lambda (x)
(f (g (h x)))))
We should approach the problem differently: we must return the (lambda (x) ...) only once, and a "loop" should process the args list before returning it. Something like this, perhaps?
(define compose-many
(lambda args
; we return (lambda (x) ...) only once, is not part of the recursion
(lambda (x)
; here we loop over the args list
(define (helper args)
(if (null? args)
x
; notice the "((" here we apply the procedure!
((car args) (helper (cdr args)))))
; call the helper a single time and we're done!
(helper args))))
((compose-many add1 add1 add1) 3)
=> 6

scheme- writing a foldl /fold-left like function that works on first 3 items of the given list

I would like to write a function that gets and infix expression and changes it to prefix.
at first let's assume we only deal with + operator, so I want to change the expression 1+1+1 into: (+ (+ 1 1) 1)
I want to do it using foldl or foldl-like matter:
taking the second item in the list (which is always the operand) appending it with the first and the third (in that order) then I would like the expression we've just appended to become the first item in the list so I would do the same on the rest of the list recursively.
Iv'e tried the following:
(lambda (lst)
(fold-left (lambda (pmLst)
`(,((cadr pmLst) ,(car pmLst) (caddr pmLst)) ,(cddr pmLst)))
'()
lst))
but then I realized that the lambda given to the fold-left has to have 2 arguments but I would like to deal with the first 3 items of the list.
I hope I've made myself clear cause it got a bit tricky..
A fold wont do what you want. If you imagine the expression (5 + 3 + 2) then using a fold with proc as the procedure do this:
(proc 2 (proc '+ (proc 3 (proc '+ (proc 5 '())))))
A way would be to make a function that returns the odd and even elements in their own list so that '(+ 2 - 3) becomes (+ -) and (2 3) and then you could do it like this:
(define (infix->prefix expr)
(if (pair? expr)
(let-values ([(ops args) (split (cdr expr))])
(fold (lambda (op arg acc)
(list op acc (infix->prefix arg)))
(car expr)
ops
args))
expr))
However the size of both is much greater than just rolling your own recursion:
(define (infix->prefix expr)
(define (aux lst acc)
(if (pair? lst)
(aux (cddr lst)
(list (car lst)
acc
(infix->prefix (cadr lst))))
acc))
(if (pair? expr)
(aux (cdr expr) (infix->prefix (car expr)))
expr))
(infix->prefix '(1 + 2 - 3))
; ==> (- (+ 1 2) 3)
There is no operator precedence here. Everything is strictly left to right.

General memoization procedure in Scheme

I am trying to create a general memoization procedure in Scheme. This is what I have so far (it's almost completely the same as excercise 3.27 in the SICP book):
(define (memo proc)
(let ((table (make-table)))
(lambda (args)
(let ((prev (lookup args table)))
(or prev
(let ((result (proc args)))
(insert! args result table)
result))))))
(The 'make-table', 'insert!' and 'lookup' procedures are defined in the SICP book)
If i call this method with a procedure that only takes one argument, it works just fine. What I can't figure out how to do is get it to work with a procedure that takes 0 or several arguments.
I found this link: http://community.schemewiki.org/?memoization , but I still can't get it to work. The procedure in the link uses apply values and call-with-values, and even though I got a rough idea on how they work, I can't seem to integrate it with my procedure.
(define (mem2 proc)
(let ((table (make-table)))
(lambda args
(let ((prev (lookup args table)))
(or prev
(call-with-values
(lambda () (apply proc args))
(lambda (result)
(insert! args result table)
result)))))))
This is my try on the procedure from the link, using a list. It's almost working, but if I have a procedure that takes several arguments, it will compute it several times. Let's say I pass a random procedure the arguments 1 2 3 4. It will save 1 2 3 4 in the table, but not the given results for 1, 2, 3 and 4 seperately. I guess my error is where I do the lookup, since I pass the whole list at once.
EDIT: added testprocedure that mem2 does not work correctly with.
(define (add . args)
(display "computing add of ")
(display args) (newline)
(if (null? args)
0
(+ (car args) (apply add (cdr args)))))
It will save in the lookup table the whole 'args'. So if I have:
(define add (mem2 add))
(add 2 3 4)
computing add of (2 3 4)
computing add of (3 4)
computing add of (4)
9
(add 3)
computing add of (3)
(define (make-table)
(vector '()))
(define (insert! key val t)
(vector-set! t 0 (cons (cons key val) (vector-ref t 0))))
(define (lookup key t)
(let ([result (assoc key (vector-ref t 0))])
(and result (cdr result))))
(define (mem2 proc)
(let ((table (make-table)))
(lambda args
(let ((prev (lookup args table)))
(or prev
(let ([result (apply proc args)])
(insert! args result table)
result))))))
(define (plus x y)
(display (list "Computing sum of: " x y))
(newline)
(+ 1 2))
(define memo-plus (mem2 plus))
(memo-plus 1 2)
(memo-plus 1 2)
Output:
(Computing sum of: 1 2)
3
3
Adding:
(define (add . args)
(display "computing add of ")
(display args) (newline)
(if (null? args)
0
(+ (car args) (apply add (cdr args)))))
(define memo-add (mem2 add))
(memo-add 1 2 3 4)
(memo-add 1 2 3 4)
Gives the output:
computing add of (1 2 3 4)
computing add of (2 3 4)
computing add of (3 4)
computing add of (4)
computing add of ()
10
10
Since nothing was printed before the last 10, the example
show that the result was memoized.

Scheme Argument Checker Error-handling

I'm fairly new to Scheme programming and was wondering how I can add some error checkers in this program. I would like it to check if the user types in more than one parameter and if the user does I would like it to say that its an error.
(define (thirds lst)
(cond ((or (null? lst) (null? (cdr lst))) lst)
((null? (cddr lst)) (list (car lst)))
(else (cons (car lst)
(thirds (cdddr lst))))))
The Scheme interpreter should check this automatically. You only need to do your own checking of the number of arguments if you define the procedure to take spread arguments, i.e.
(define (thirds . args)
...)
You would normally only do this if the procedure takes a variable number of arguments. For procedures with static arguments, just list them in the definition and let the interpreter do the checking for you.
If you really want to detect this yourself, you can do:
(define (thirds . args)
(if (= (length args) 1)
(let ((lst (car args)))
(cond ... ; all the rest of your code
))
(display "Oh that's an error")))
So, using your definition of thirds in #!racket (the language) and trying to use it like this:
(thirds '(a b c) '(d e f))
thirds: arity mismatch;
the expected number of arguments does not match the given number
expected: 1
given: 2
arguments...:
'(a b c)
'(d e f)
context...:
/usr/share/racket/collects/racket/private/misc.rkt:87:7
As you can see all computation stops since I have given a one argument procedure two arguments. It's a contract violation and it throws an exception.
It's perfectly possible to make handlers:
(with-handlers ([exn:fail:contract?
(λ (e) (displayln "got a contract error"))])
(thirds '(1 2 3) '(4 5 6)))
; prints "got a contract error"

Improperly placed closed parenthesis in scheme function

I have the following scheme function:
(define get-ivars
(λ (ivars num)
(cond ((null? ivars) '())
(else
(append (list (car ivars) `(nth args ,num)) (list (get-ivars (cdr ivars) (+ num 1))))))))
That returns the following in a specific instance:
(x (nth args 1) (y (nth args 2) ()))
The problem is, I need it to return:
((x (nth args1)) (y (nth args 2)) ())
-the two closing parenthesis at the end should be after the (nth statements.
How would I go about getting this to work properly?
get-ivars caller:
(define gen-classes
(λ (classes)
(cond ((null? classes) '())
(else
(let* ((class (car classes)))
(eval
`(define ,(cadr class)
(λ (args)
(let (
,(get-ivars (cdr (cadddr class)) 1)
)
(eval
(let* ,(cdar (cddddr class))
(λ (method . args)
,(get-methods (cdadr (cddddr class)))
))))))))))))
That second (list ...) in your else clause is what's screwing you up. It's nesting each successive call deeper and deeper. The recursion will naturally create the list; you don't need to wrap it again.
Try:
(define get-ivars
(λ (ivars num)
(if (null? ivars) '()
(cons (list (car ivars) `(nth args ,num))
(get-ivars (cdr ivars) (+ num 1))))))
Regarding the get-ivars caller code, the parentheses surrounding the unquoted call to get-ivars are what's giving you the trouble you mention in the comments. With them, this code:
`(define ClassName
(lambda (args)
(let (,(get-ivars '(iVar1 iVar2 iVar3) 1))
;; your method-getting code
)))
Gives you this:
(define ClassName
(lambda (args)
(let (((iVar1 (nth args 1))
(iVar2 (nth args 2))
(iVar3 (nth args 3))))
;; method-getting code
)))
Which, as you can see, gives you an extra set of parentheses around the assignments in the let.
So you want to do this:
`(define ClassName
(lambda (args)
(let ,(get-ivars '(iVar1 iVar2 iVar3) 1)
;; your method-getting code
)))
get-ivars is returning a list of lists, which is exactly what you want for the assignments in the let, so you don't need to wrap or (as I had it earlier) splice it. Just use the unquote on its own, and the result is:
(define ClassName
(lambda (args)
(let ((iVar1 (nth args 1))
(iVar2 (nth args 2))
(iVar3 (nth args 3)))
;; method-getting code
)))
Which should do the trick.
Incidentally, I found it helpful to leave off the eval when I was playing around with this; one can then visually inspect the result to make sure its syntax is okay.
I haven't tried this, but I think this would work:
(define (get-ivars ivars num)
(if (null? ivars)
'()
(list (list (car ivars) `(nth args ,num))
(get-ivars (cdr ivars) (1+ num)))))

Resources