[racket-dev] Simple loop checking in beginner?

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Wed Nov 10 09:50:55 EST 2010

Your reasoning is correct. What's the performance hit? 


On Nov 9, 2010, at 9:13 PM, John Clements wrote:

> Here's a simple macro that prevents same-argument recursive calls (including non-tail ones).  It's illustrated by a student function that made a teeny mistake which would result in looping forever, but (using this macro) instead signals an error.  To the best of my limited knowledge, beginner is purely functional aside from the use of the test functions, right? So any recursive call with eq? args is guaranteed to loop forever, right?
> 
> Hmm... well, I suppose there's (random)... 
> 
> It seems to me that a macro like this one (or even complete memoization) could potentially reduce student frustration, and would not prevent students from writing the programs that they wanted to.
> 
> No?
> 
> John Clements
> 
> 
> 
> #lang racket
> 
> (require rackunit)
> 
> (define-syntax (define/noloop stx)
>  (syntax-case stx ()
>    [(_ (funname arg ...) body ...)
>     #`(define funname
>         (let ()
>           (define fresh-key (gensym 'funname))
>           (define (funname arg ...)
>             (let* ([most-recent-args (continuation-mark-set-first #f fresh-key)]
>                    [these-args (list arg ...)])
>               (when (and most-recent-args
>                          (= (length these-args)
>                             (length most-recent-args))
>                          (andmap eq? these-args most-recent-args))
>                 (error 'funname "recursive call with identical arguments ~s is guaranteed to run forever." these-args))
>               (with-continuation-mark fresh-key these-args
>                 body
>                 ...)))
>           funname))]))
> 
> ;; NOW I'M A STUDENT:
> 
> ;; only-long-strings : (listof string) -> (listof string)
> ;; return a list containing the strings longer than 2 chars
> (define/noloop (only-long-strings l)
>  (cond [(empty? l) empty]
>        [else (cond [(< 2 (string-length (first l))) 
>                     (cons (first l) 
>                           (only-long-strings (rest l)))]
>                    [else (only-long-strings l)])]))
> 
> 
> (check-equal? (only-long-strings (cons "abc" (cons "de" (cons "fgh" empty))))
>              (cons "abc" (cons "fgh" empty)))_________________________________________________
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/dev



Posted on the dev mailing list.