If you don't want to use the package or you want other criteria for
stooping, I think the correct way to do this are continuation marks, but an
easier but more inefficient way is using a parameter (so it is thread safe).

;-----
#lang racket
(define recursion-level (make-parameter 0))

(define (f x)
  (sleep (* .1 (random)))
  (cond
    [(<= (recursion-level) 5)
     (parameterize ([recursion-level (add1 (recursion-level))])
       (displayln (list (recursion-level) x))
       (f (* x 2)))]
    [else
     (displayln (list "too many recursions" x))]))

(thread (lambda () (f 10)))
(f 1)
; -----

Gustavo

On Fri, Aug 9, 2019 at 2:03 PM Sam Tobin-Hochstadt <[email protected]>
wrote:

> This is possible -- the central trick is to maintain information about
> the call stack separately, perhaps by using continuation marks.
>
> We (mostly Phil Nguyen) recently built a tool that does this. If you
> take your program, install the "termination" package, and then add:
>
>     (require termination)
>     (begin/termination (recur1 0))
>
> you get this error message:
>
> possible-non-termination: Recursive call to `#<procedure:recur1>` has
> no obvious descent on any argument
> - Preceding call:
>   * 1st arg: 3
> - Subsequent call:
>   * 1st arg: 6
>
> We have a paper, here: https://arxiv.org/abs/1808.02101 which goes
> into detail about how it works. The source code is here:
> https://github.com/philnguyen/termination
>
> Sam
>
> On Fri, Aug 9, 2019 at 11:58 AM Kees-Jochem Wehrmeijer
> <[email protected]> wrote:
> >
> > Hi,
> >
> > I'm wondering whether it's possible for a function to detect whether
> it's being called by itself, possibly indirectly. I want to use this to
> prevent endless loops and generate different results in these situations.
> For example, imagine I have the following functions:
> >
> > (define (foo loc)
> >   (list
> >    (cons loc 'a)
> >    (cons (+ loc 1) 'b)
> >    (cons (+ loc 2) 'c)))
> >
> > (define (combine a b)
> >   (lambda (loc)
> >     (append (a loc) (b (+ loc 3)))))
> >
> > So I can do:
> > > ((combine foo foo) 0)
> > => '((0 . a) (1 . b) (2 . c) (3 . a) (4 . b) (5 . c))
> >
> > Now, let's say I have these recursive definitions:
> >
> > (define (recur1 loc)
> >   ((combine foo recur2) loc))
> >
> > (define (recur2 loc)
> >   (recur1 loc))
> >
> > Defined in this way, a call to (recur1 0) loops endlessly. I would like
> it too return something like
> > > (recur1 0)
> > => '(0 . a) (1 . b) (2 . c) (loop 0))
> >
> > So I was thinking if I could make it work if I could do something like:
> > (define (recur1 loc)
> >   (if (in-recursive-call?)
> >       (list (cons 'loop 0))
> >       ((combine foo recur2) loc)))
> >
> > Is that something that's possible? Is there a better way to do what I
> want?
> >
> > Thanks,
> > Kees
> >
> > --
> > 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 [email protected].
> > To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/292977cf-7800-453f-9d4b-b6a1ee525287%40googlegroups.com
> .
>
> --
> 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 [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/CAK%3DHD%2Bb0odK1qfox9Ah2umLqKxUhas_GTJUv95Avm536g9ybGg%40mail.gmail.com
> .
>

-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAPaha9MPK2A5jBD4GVmtOZrSjb24tDD6-WQKPBCPuSe_Yiq6Fw%40mail.gmail.com.

Reply via email to