scheme - display won't print on screen in a recursive function - debugging

I have the function getBoundedVars which uses the function boundsInLambda. In the end of it all the box bBox should contain all bounded variables in the expression exp.
I'm trying to debug this function and in order to do so I want to print the parameters of boundsInLambda every time the function is being activated but for some reason the values won't show up on the screen.
If I put the display operation in getBoundedVars it will print it but those are just the values in the first iteration.
If I run the following :
(getBoundedVars (lambda-simple (x) (lambda-simple (y) (const x))) bx)
when bx is an empty box,
'1 will be printed but the print commands in boundsInLambda will not
here's the code:
(define getBoundedVars
(lambda (exp bBox)
(if (atom? exp)
0 ;; don't put in box
(if (lambda? (car exp))
(begin
(display 1)
(newline)
(let ((pBox (make-pBox exp))
(lBox (box '()))
(bodyExp (make-body exp))
)
(boundsInLambda bodyExp lBox pBox bBox)))
(begin
(getBoundedVars (car exp) bBox)
(getBoundedVars (cdr exp) bBox))))))
(define boundsInLambda
(lambda (bodyExp lastBox paramBox boundsBox)
(newline)
(display `(bodyExp: ,bodyExp))
(newline)
(display `(lastBox: ,lastBox))
(newline)
(display `(paramBox: ,paramBox))
(newline)
(display `(boundsBox: ,boundsBox))
(newline)
(if (and (not (null? bodyExp))
(list bodyExp)
(equal? (car bodyExp) 'seq)
)
(map boundsInLambda (cadr bodyExp))
(let* ( (lists* (filter (lambda (el) (and (not (null? el)) (list? el) (not (equal? (car el) 'const)))) bodyExp))
(lists (map (lambda (el) (if (equal? (car el) 'set) (cddr el) el)) lists*))
(bounds (filter (lambda (el) (and (member el (unbox lastBox)) (not (member el (unbox paramBox))))) bodyExp))
(listsLeft? (> (length lists) 0))
(anyBounds? (> (length bounds) 0))
)
(if anyBounds?
(begin
(set-box! boundsBox (append (unbox boundsBox) bounds))))
(if listsLeft?
(map
(lambda (lst)
(if (lambda? (car lst))
(let* ((newBodyExp (make-body lst))
(newParamBox (make-pBox exp))
(newLastBox (box (append (unbox lastBox) (unbox paramBox))))
)
(boundsInLambda newBodyExp newLastBox newParamBox boundsBox))
(boundsInLambda lst lastBox paramBox boundsBox)))
lists)
0))
)))
(define make-pBox
(lambda (lamExp)
(if (equal? (car lamExp) 'lambda-simple)
(box (cadr lamExp))
(if (equal? (car lamExp) 'lambda-opt)
(box (cadr lamExp))
(box '())))))
(define make-body
(lambda (lamExp)
(if (equal? (car lamExp) 'lambda-opt)
(cdddr lamExp)
(cddr lamExp))))
any help would be very much appreciated.

Related

Removing extra parentheses in Scheme

Using a Scheme-like language, I am converting
(quote (lambda (a b) (* a b) (+ a b))))
to:
(quote (lambda (a) (lambda (b) (+ a b) (* a b))))
but with my current implementation I am getting an extra pair of parenthesis around the expressions (+ a b) and (* a b):
(lambda (a) (lambda (b) ((+ a b) (* a b))))
I have spent a lot of time trying to fix this problem, but can't figure it out. I feel like the fix should be trivial.
Here is my code currently:
(define (conv lyst)
(define (helper args)
(cond
((null? args) (append (cddr lyst) args))
(else (cons (car lyst)
(cons (list (car args))
(list (helper (cdr args))))))))
(cond
((eq? 1 (length (car (cdr lyst)))) lyst)
(else (helper (car (cdr lyst))))))
I think your implementation can be simplified. This should work:
(define (conv lyst)
(define (helper args)
(if (null? (cdr args))
(cons 'lambda
(append (list (list (car args)))
(cddr lyst)))
(list 'lambda
(list (car args))
(helper (cdr args)))))
(helper (cadr lyst)))
Or even simpler, using quasiquoting and splicing:
(define (conv lyst)
(define (helper args)
(if (null? (cdr args))
`(lambda (,(car args)) ,#(cddr lyst))
`(lambda (,(car args)) ,(helper (cdr args)))))
(helper (cadr lyst)))
Either way, it works as expected:
(conv '(lambda (a b) (* a b) (+ a b)))
=> '(lambda (a) (lambda (b) (* a b) (+ a b)))

sicp pattern matching - compound?

I am watching the video lectures of SICP. Currently I am on 4A Pattern Matching and Rule Based Substitution.
So far, I found the Matcher and the Instantiator is easy. But I can't get my head into The simplifier.
(define (simplifier the-rules)
(define (simplify-exp exp)
(try-rules (if (compound? exp)
(map simplify-exp exp)
exp)))
(define (try-rules exp)
(define (scan rules)
(if (null? rules)
exp
(let ((dict (match (pattern (car rules))
exp
(empty-dictionary))))
(if (eq? dict 'failed)
(scan (cdr rules))
(simplify-exp (instantiate (skeleton (car rules)) dict))))))
(scan the-rules))
simplify-exp)
I saw another question here on this topic which defined compound? in terms of pair?. But, Then what simplify-exp feeding to try-rules?
Figured it out. The rules are going to apply in every node as promised. You can vote to delete the question. But, I would add some explanation on how I made it working.
I changed some code. The original code seems written with some other semantic in mind. I added some commentary where I made some decision on my own.
#lang racket
;matcher
(define (match pat exp dict)
(cond ((eq? dict 'failed) 'failed)
;matched
((and (null? pat) (null? exp)) dict)
;so far matched, but no more
((or (null? pat) (null? exp)) 'failed)
((atom? pat)
(if (atom? exp)
(if (eq? pat exp)
dict
'failed)
'failed))
((pat-const? pat)
(if (constant? exp)
(extend-dict pat exp dict)
'failed))
((pat-variable? pat)
(if (variable? exp)
(extend-dict pat exp dict)
'failed))
((pat-exp? pat)
(extend-dict pat exp dict))
((atom? exp) 'failed)
(else
(match (cdr pat)
(cdr exp)
(match (car pat) (car exp) dict)))))
(define (pat-const? pat)
(eq? (car pat) '?c))
(define (pat-variable? pat)
(eq? (car pat) '?v))
(define (pat-exp? pat)
(eq? (car pat) '?))
(define constant? number?)
(define variable? symbol?)
;instantiator
(define (instantiate skeleton dict)
(define (loop s)
(cond ((atom? s) s)
;we cant run past the nil line
((null? s) '())
((skeleton-evaluation? s) (evaluate s dict))
(else
(cons (loop (car s)) (loop (cdr s))))))
(loop skeleton))
(define (skeleton-evaluation? s)
(eq? (car s) ':))
;made it simpler, no environment constant, sorry
(define (evaluate s dict)
(let ((data (lookup (cadr s) dict)))
(if (null? data)
(display "error in rules. mismatch")
(cadr data))))
;simplifier
(define (simplifier rules)
(define (simplify-exp exp)
(try-rules (if (list? exp)
(map simplify-exp exp)
exp)))
(define (try-rules exp)
(define (scan rule)
(if (null? rule)
exp
(let ((dict (match (pattern (car rule)) exp (empty-dict))))
(if (eq? dict 'failed)
(scan (cdr rule))
(simplify-exp (instantiate (skeleton (car rule)) dict))))))
(scan rules))
simplify-exp)
(define pattern car)
(define skeleton cadr)
;dictionary
(define (empty-dict)
'())
(define (extend-dict pat exp dict)
(let ((v (lookup (cadr pat) dict)))
(if (null? v)
(cons (list (cadr pat) exp) dict)
(if (eq? (cadr v) exp)
dict
'failed))))
(define (lookup s dict)
(cond ((null? dict) '())
((eq? (caar dict) s) (car dict))
(else (lookup s (cdr dict)))))
;extend racket
(define (atom? a)
(and (not (null? a)) (not (pair? a))))
And? you know what? It works :)

Scheme function that returns a function

I need to write a scheme function that returns as a function which then takes another argument, eg a list and in turn return the desired result. In this example (c?r "arg") would return -- (car(cdr -- which then subsequently takes the list argument to return 2
> ((c?r "ar") '(1 2 3 4))
2
> ((c?r "ara") '((1 2) 3 4))
2
The problem I have is how can I return a function that accepts another arg in petite?
Here's how you might write such a function:
(define (c?r cmds)
(lambda (lst)
(let recur ((cmds (string->list cmds)))
(if (null? cmds)
lst
(case (car cmds)
((#\a) (car (recur (cdr cmds))))
((#\d) (cdr (recur (cdr cmds))))
(else (recur (cdr cmds))))))))
Note that I'm using d to signify cdr, not r (which makes no sense, to me). You can also write this more succinctly using string-fold-right (requires SRFI 13):
(define (c?r cmds)
(lambda (lst)
(string-fold-right (lambda (cmd x)
(case cmd
((#\a) (car x))
((#\d) (cdr x))
(else x)))
lst cmds)))
Just wanted to add my playing with this. Uses SRFI-1.
(import (rnrs)
(only (srfi :1) fold)) ;; require fold from SRFI-1
(define (c?r str)
(define ops (reverse (string->list str)))
(lambda (lst)
(fold (lambda (x acc)
((if (eq? x #\a) car cdr) ; choose car or cdr for application
acc))
lst
ops)))
Its very similar to Chris' version (more the previous fold-right) but I do the reverseso i can use fold in the returned procedure. I choose which of car or cdr to call by looking at the character.
EDIT
Here is an alternative version with much more preprocessing. It uses tail-ref and list-tail as shortcuts when there are runs of #\d's.
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (reverse
(if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs)))))
(lambda (lst)
(fold (lambda (fun lst)
(fun lst))
lst
funs))))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
This can be made even simpler in #!racket. we skip the reverse and just do (apply compose1 funs).
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs))))
(apply compose1 funs)))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
Assuming a compose procedure:
(define (compose funs . args)
(if (null? funs)
(apply values args)
(compose (cdr funs) (apply (car funs) args))))
(compose (list cdr car) '(1 2 3 4))
=> 2
c?r can be defined in terms of compose like so:
(define (c?r funs)
(lambda (e)
(compose
(map
(lambda (f) (if (char=? f #\a) car cdr))
(reverse (string->list funs)))
e)))
then
((c?r "ar") '(1 2 3 4))
=> 2
((c?r "ara") '((1 2) 3 4))
=> 2

Display elements in list with for-each

I have 1 big list of smaller 3-element-lists that look like:
( ("001" "Bob" 80) ("002" "Sam" 85) ("003" "Aaron" 94) etc . . .)
I'm trying to create something like:
No.1: ID=001, Name=’’Bob’’, Grade=80
No.2: ID=002, Name=’’Sam’’, Grade=85
No.3: ID=003, Name=’’Aaron’’, Grade=94
I only have access to display and for-each (no "for" or "printf" functions)
I've been trying to create a for-each function that takes the list and:
pseudo-code:
for-each list in list
display "ID=(car list)"
display "Name ="(cadr list)" "
etc
Any help would be greatly appreciated!
So, your interpreter doesn't have printf after all? that's a shame. We can get the desired output by hand, it's a bit cumbersome but this should work on most Scheme interpreters, notice that an extra procedure is required for keeping track of the index:
(define lst
'(("001" "Bob" 80) ("002" "Sam" 85) ("003" "Aaron" 94)))
(define (add-index lst)
(let loop ((lst lst) (idx 1))
(if (null? lst)
'()
(cons (cons idx (car lst))
(loop (cdr lst) (+ idx 1))))))
(for-each (lambda (e)
(display "No.")
(display (car e))
(display ": ID=")
(display (cadr e))
(display ", Name=’’")
(display (caddr e))
(display "’’, Grade=")
(display (cadddr e))
(newline))
(add-index lst))
It prints the desired result:
No.1: ID=001, Name=’’Bob’’, Grade=80
No.2: ID=002, Name=’’Sam’’, Grade=85
No.3: ID=003, Name=’’Aaron’’, Grade=94
Here's another version. It avoids construction of a temporary list.
(define lst
'(("001" "Bob" 80) ("002" "Sam" 85) ("003" "Aaron" 94)))
(define (print-list lst)
(define (display-one-item item index)
(display "No.")
(display index)
(display ": ID=")
(display (car item))
(display ", Name=’’")
(display (cadr item))
(display "’’, Grade=")
(display (caddr item))
(newline))
(define (helper in index)
(if (not (null? in))
(begin
(display-one-item (car in) index)
(helper (cdr in) (+ index 1))
)))
(helper lst 0))
(print-list lst)

Removing null elements from the scheme list

(define filter-in
(lambda (predicate list)
(let((f
(lambda (l)
(filter-in-sexpr predicate l))))
(map f list))))
(define filter-in-aux
(lambda (pred lst)
(if (null? lst) '()
(cons (filter-in-sexpr pred (car lst))
(filter-in-aux pred (cdr lst))))))
(define filter-in-sexpr
(lambda (pred sexpr)
(if (equal? (pred sexpr) #t)
sexpr
'())))
Calling (filter-in number? ’(a 2 (1 3) b 7)) produces ( () 2 () () 7).
How I can skip null elements from the generated list to get final outcome of (2 7) ?
The problem is that you're mapping filter-in-sxpr over the list. You can either run another filter pass to remove the nulls, or use a modified filter-in-aux like this:
(define filter-in-aux
(lambda (pred lst)
(if (null? lst) '()
(let ((h (filter-in-sexpr pred (car lst)))
(t (filter-in-aux pred (cdr lst))))
(if (null? h) t
(cons h t))))))

Resources