By changing (fact 5) to (* 2 (fact 5)), the stack information becomes /: division by zero errortrace...: /Volumes/ramdisk/fact.rkt:6:17: (/ 1 0) /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n) /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n) /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n) /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n) /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n) /Volumes/ramdisk/fact.rkt:9:0: (* 2 (fact 5))
Here, the difference is that (fact 5) is no longer at tail position. I believe errortrace is aiming at preserving proper tail implementation behavior. On Mon, Jul 27, 2020 at 11:39 AM Sorawee Porncharoenwase <[email protected]> wrote: > > (By "integrating" with the new strategy, I meant having two keys: one for the > new strategy and one for the old strategy. I can see that the first entry of > the old strategy is useful, and it's missing in the new strategy). > > On Sun, Jul 26, 2020 at 8:21 PM Sorawee Porncharoenwase > <[email protected]> wrote: >> >> Hi everyone, >> >> I have a question about the implementation of errortrace. >> >> Consider the classic factorial program, except that the base case is buggy: >> >> (define (fact m) >> (let loop ([n m]) >> (cond >> [(zero? n) (/ 1 0)] >> [else (* (loop (sub1 n)) n)]))) >> >> (fact 5) >> >> Running this program with racket -l errortrace -t fact.rkt gives the >> following output: >> >> /: division by zero >> errortrace...: >> /Users/sorawee/playground/fact.rkt:9:17: (/ 1 0) >> /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n) >> /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n) >> /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n) >> /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n) >> /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n) >> >> I find this result subpar: it doesn’t indicate which call at the top-level >> leads to the error. You can imagine another implementation of fact that >> errors iff m = 5. Being able to see that (fact 5) at the top-level causes >> the error, as opposed to (fact 3), would be very helpful. >> >> Not only that, (* (loop (sub1 n)) n) also looks weird. There’s nothing wrong >> with multiplication, so I don’t find this information useful. >> >> The tail-recursive factorial is similarly not helpful: >> >> (define (fact m) >> (let loop ([n m] [acc 1]) >> (cond >> [(zero? n) (/ 1 0)] >> [else (loop (sub1 n) (* n acc))]))) >> >> (fact 5) >> >> produces: >> >> /: division by zero >> errortrace...: >> /Users/sorawee/playground/fact.rkt:9:17: (/ 1 0) >> >> ________________________________ >> >> I have been toying with another way to instrument the code. It roughly >> expands to: >> >> (define-syntax-rule (wrap f) >> (call-with-immediate-continuation-mark >> 'errortrace-k >> (λ (k) >> (let ([ff (thunk f)]) >> (if k >> (ff) >> (with-continuation-mark 'errortrace-k 'f >> (ff))))))) >> >> (define (handler ex) >> (continuation-mark-set->list (exn-continuation-marks ex) 'errortrace-k)) >> >> (define (fact m) >> (wrap (let loop ([n m]) >> (wrap (cond >> [(wrap (zero? n)) (wrap (/ 1 0))] >> [else (wrap (* (wrap n) (wrap (loop (wrap (sub1 >> n))))))]))))) >> >> (with-handlers ([exn:fail? handler]) >> (wrap (fact 5))) >> >> which produces: >> >> '((loop (wrap (sub1 n))) >> (loop (wrap (sub1 n))) >> (loop (wrap (sub1 n))) >> (loop (wrap (sub1 n))) >> (loop (wrap (sub1 n))) >> (fact 5)) >> >> This result is more aligned with the traditional stacktrace, and gives >> useful information that I can use to trace to the error location. >> >> It is also safe-for-space: >> >> (define (fact m) >> (wrap (let loop ([n m] [acc 1]) >> (wrap (cond >> [(wrap (zero? n)) (wrap (/ 1 0))] >> [else (wrap (loop (wrap (sub1 n)) (wrap (* n acc))))]))))) >> >> (with-handlers ([exn:fail? handler]) >> (wrap (fact 5))) >> >> produces: >> >> '((fact 5)) >> >> Now, the question: why is the current errortrace implemented in that way? Am >> I missing any downside of this new strategy? Would switching and/or >> integrating with the new strategy be better? >> >> Thanks, >> Sorawee (Oak) > > -- > 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/CADcuegto9%2BDtFTwAVmiReOcCwpARzBSbFhF0knyexb7UhoHQiA%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/CAMTzy%2BbkerQnMuNA3%3Do6QHSDy7PZAPPRo6s19G21ECBMKwqHFw%40mail.gmail.com.

