> What is lousy and expectation-violating about a keyword argument > doing what it name describes?
well, this should have been discussed at the R6RS committee, but... an API is facilitating efficient reading comprehension when the "verbs" are closer to the beginning of the "sentence" (the sexp), and nothing later in the sentence adjusts the meaning of the verb fundamentally. and especially not a keyword arg at the end of the sentence that is not even mandatory, and defaults to one of the rather different possibilities. in this case, it's a primitive to catch and handle exceptions. and it's possible to implement both #:unwind? #t and #f so that when the handler returns then the control flow continues at the guard, and never at the RAISE. it's just that one version would call the handler before unwinding. > If you have unwinded, it’s too late to return return from the raise > (unless the implementation is doing delimited continuations > shenanigans, which maybe you had in mind?), which explains the > behaviour for #:unwind #true. i didn't have anything on my mind, and that's the point. i'm simply new to scheme. now that i've learned it, i'll learn to live with it. put another way, my learning curve would have been much steeper if the two, rather different behaviors were defined under two distinct names (or at least mentioned with bold in the documentation). > That said, I would prefer it to be named something like [#:handler-context > 'raise]/[#:handler-context 'guard] that would be better, but i still wouldn't like the fact that it's focusing on the dynamic context of the handler, instead of the different flow of control. for reference, in CL they are called HANDLER-CASE and HANDLER-BIND, with completely different syntaxes. > Wait where did this happen? You say what’s happening, but you don’t > seem to be referring to false-if-exception stuff, and you didn’t > mention continuation barriers earlier. this has caused me layers of confusion, which is sadly reflected in my mails. guile prints a backtrace without any prelude, which made me think that it's my own code that is printing this backtrace and exception in the logs (remember, i'm working on nested error handling and logging in shepherd). then 3.0.9 does something funny with the control flow, which further made me believe that i'm logging an exception coming from inside FALSE-IF-EXCEPTION and it's somehow flying past my error handler, and reaching fibers. and i think i'm still confused about a possible continuation barrier being injected somewhere that probably/maybe causes the exception from inside FALSE-IF-EXCEPTION somehow ending up at fibers instead of my error handler. but at this point i'm reaching the frontier of my understanding of scheme, delimited continuations, fibers, etc. so, one step at a time. once this test.scm is clear, and i'm able to run shepherd on guile-next, then i'll get back to investigate my original issue in its original context. > It would be helpful to include in test.scm what the expected output > would be and what unexpected output is encountered. i've attached a new test.scm that contains the output of two runs, one with 3.0.9, and one with guile HEAD (more specifically, guile-next in guix, which is almost guile HEAD). HTH, -- • attila lendvai • PGP: 963F 5D5F 45C7 DFCD 0A39 -- “Life becomes easier when you learn to accept the apology you never got.” — Robert Brault
#!/usr/bin/env -S guile --no-auto-compile -e main -s !# (use-modules (ice-9 control)) (define* (test #:key (unwind? #f)) (let/ec return (with-exception-handler (let ((nested #f)) (lambda (c-level-1) (if nested (begin (format #t "level 1 handler got called recursively~%") 'level-1-handler-nested) (begin (set! nested #t) (with-exception-handler (lambda (c-level-2) (begin (format #t "level 2 handler got error ~A~%" c-level-2) (format #t "level 2 handler is returning~%") (return 'level-2-handler))) (lambda () (format #t "level 1 handler~%") (error "let's signal a nested error...") (format #t "level 1 handler is returning~%") (return 'level-1-handler)) #:unwind? unwind?))))) (lambda () (error "let's signal an error...") 'thunk) #:unwind? unwind?))) (define (main cmd) (unsetenv "COLUMNS") (format #t "~%~%*** calling with unwind~%") (format #t "return value is: ~A~%" (test #:unwind? #t)) (format #t "~%~%*** calling without unwind~%") (format #t "return value is: ~A~%" (test #:unwind? #f))) #| $ guile --version guile (GNU Guile) 3.0.9 $ guile --no-auto-compile -e main -s ~/workspace/guile/test.scm *** calling with unwind level 1 handler level 2 handler got error #<&compound-exception components: (#<&error> #<&origin origin: #f> #<&message message: "~A"> #<&irritants irritants: ("let's signal a nested error...")> #<&exception-with-kind-and-args kind: misc-error args: (#f "~A" ("let's signal a nested error...") #f)>)> level 2 handler is returning return value is: level-2-handler *** calling without unwind level 1 handler Backtrace: In ice-9/boot-9.scm: 1752:10 12 (with-exception-handler _ _ #:unwind? _ # _) In unknown file: 11 (apply-smob/0 #<thunk 7f8d73313300>) In ice-9/boot-9.scm: 724:2 10 (call-with-prompt ("prompt") #<procedure 7f8d73324f80 â¦> â¦) In ice-9/eval.scm: 619:8 9 (_ #(#(#<directory (guile-user) 7f8d73316c80>))) 163:9 8 (_ #(#(#<directory (guile-user) 7f8d73316c80>) ("/hoâ¦"))) In ice-9/boot-9.scm: 724:2 7 (call-with-prompt (let/ec) #<procedure 7f8d73352900 atâ¦> â¦) 1752:10 6 (with-exception-handler _ _ #:unwind? _ # _) In ice-9/eval.scm: 619:8 5 (_ #(#(#<directory (guile-user) 7f8d73316c80>))) In ice-9/boot-9.scm: 2007:7 4 (error _ . _) 1685:16 3 (raise-exception _ #:continuable? _) 1752:10 2 (with-exception-handler _ _ #:unwind? _ # _) In ice-9/eval.scm: 619:8 1 (_ #(#(#<directory (guile-user) 7f8d73316c80> #<procâ¦>))) In ice-9/boot-9.scm: 2007:7 0 (error _ . _) ice-9/boot-9.scm:2007:7: In procedure error: let's signal a nested error... $ |# #| $ /gnu/store/xm08cp3fz3jxq3zddg9cvj59idy3ri8b-guile-3.0.99-git/bin/guile --no-auto-compile -e main -s ~/workspace/guile/test.scm *** calling with unwind level 1 handler level 2 handler got error #<&compound-exception components: (#<&error> #<&origin origin: #f> #<&message message: "~A"> #<&irritants irritants: ("let's signal a nested error...")> #<&exception-with-kind-and-args kind: misc-error args: (#f "~A" ("let's signal a nested error...") #f)>)> level 2 handler is returning return value is: level-2-handler *** calling without unwind level 1 handler level 2 handler got error #<&compound-exception components: (#<&error> #<&origin origin: #f> #<&message message: "~A"> #<&irritants irritants: ("let's signal a nested error...")> #<&exception-with-kind-and-args kind: misc-error args: (#f "~A" ("let's signal a nested error...") #f)>)> level 2 handler is returning return value is: level-2-handler $ |#