> 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
$
|#
  • bug#46009: exce... Maxime Devos
    • bug#46009:... Attila Lendvai
      • bug#46... Attila Lendvai
        • bu... Bug reports for GUILE, GNU's Ubiquitous Extension Language
          • ... Attila Lendvai
            • ... Bug reports for GUILE, GNU's Ubiquitous Extension Language
              • ... Attila Lendvai
                • ... Bug reports for GUILE, GNU's Ubiquitous Extension Language

Reply via email to