Brendan,

You are correct, your program did error when you applied `Lam-body` to a
non-`Lam`. What happened is that, in the process of printing the error
message, it tried to print that non-`Lam` value, which called your
custom printer, and so on.

Does that make sense?

Vincent


On Wed, 02 Mar 2016 16:08:04 -0600,
brendan wrote:
> 
> Today I wrote and then fixed a bug that caused my program to enter an 
> infinite loop for reasons I don't understand.
> 
> The program is the output display formatting for a prototype relational 
> lambda calculus interpreter. First I took my two structs, Lam and App (using 
> symbols for variables), and implemented the gen:custom-write interface for 
> both, essentially following the example in the documentation:
> 
> 
> #lang racket
> 
> (define-struct Lam (var body)
>   #:methods gen:custom-write [(define write-proc (λ (v port mode)
>                                                    (write-lam v port mode)))])
> (define-struct App (func arg)
>   #:methods gen:custom-write [(define write-proc (λ (v port mode)
>                                                    (write-app v port mode)))])
> 
> (define (write-lam v port mode)
>   (define recur (make-recur port mode))
>   (fprintf port "λ~a." (symbol->string (Lam-var v)))
>   (recur (Lam-body v)))
> 
> (define (write-app v port mode)
>   (define recur (make-recur port mode))
>   (write-string "(" port)
>   (recur (App-func v))
>   (write-string " " port)
>   (recur (App-arg v))
>   (write-string ")" port))
> 
> (define (make-recur port mode)
>   (define aux (case mode
>     [(#t) (lambda (v) (write v port))]
>     [(#f) (lambda (v) (display v port))]
>     [else (lambda (v) (print v port mode))]))
>   (λ (v)
>     (if (symbol? v)
>         (write-string (symbol->string v) port)
>         (aux v))))
> 
> 
> It worked fine. Then I defined two new structs, Lam* and App*, representing 
> how the written notation groups consecutive lambdas and consecutive 
> applications together to save parentheses. I also wrote procedures to convert 
> from the simple representation to the new one. Finally, I implemented 
> gen:custom-write for the new structs:
> 
> 
> (define-struct Lam* (var* body) #:transparent
>   #:methods gen:custom-write [(define write-proc (λ (v port mode)
>                                                    (write-lam* v port 
> mode)))])
> 
> (define-struct App* (body*) #:transparent
>   #:methods gen:custom-write [(define write-proc (λ (v port mode)
>                                                    (write-app* v port 
> mode)))])
> 
> (define (write-lam* v port mode)
>   (define recur (make-recur port mode))
>   (define var-str (string-append* (map symbol->string (Lam*-var* v))))
>   (fprintf port "λ~a." var-str)
>   (recur (Lam*-body v)))
> 
> (define (write-app* v port mode)
>   (define recur (make-recur port mode))
>   (define (space-recur v)
>     (write-string " " port)
>     (recur v))
>   (define body* (App*-body* v))
>   
>   (write-string "(" port)
>   (recur (car body*))
>   (map space-recur (cdr body*))
>   (write-string ")" port))
> 
> (define (exp->exp* e)
>   (match e
>     [(Lam _ _)
>      (define-values (var* body) (lam->var*+body e))
>      (Lam* var* body)]
>     [(App _ _)
>      (App* (reverse (app->body* e)))]
>     [else e]))
> 
> (define (lam->var*+body e)
>   (match e
>     [(Lam v (and b (Lam _ _)))
>      (define-values (var* body) (lam->var*+body b))
>      (values (cons v var*) body)]
>     [(Lam v b)
>      (values (list v) (exp->exp* b))]))
> 
> (define (app->body* e)
>   (match e
>     [(App (and e1 (App _ _)) e2)
>      (cons (exp->exp* e2) (app->body* e1))]
>     [(App e1 e2)
>      (list (exp->exp* e2) (exp->exp* e1))]))
> 
> 
> Since I knew that the new method implementations would be pretty similar to 
> the old ones, I followed my usual bad habit of cutting and pasting and then 
> making changes. And as happens more than I like to admit, I missed something. 
> Specifically, in the last line of write-lam*, where you now see Lam*-body, I 
> left it as Lam-body. When I tried displaying some simple test data, it went 
> into an infinite loop. When I tried to investigate with the debugger, I 
> learned that you can't break out of a loop in the debugger.
> 
> Anyway, long-story->short, I fixed the error, but now I'm puzzled. Shouldn't 
> the program have stopped with an error message when Lam-body was applied to a 
> non-Lam?
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to