unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Panicz Maciej Godek <godek.maciek@gmail.com>
To: "guile-user@gnu.org" <guile-user@gnu.org>
Subject: Exceptions that pass continuations
Date: Fri, 19 Jul 2013 12:39:55 +0200	[thread overview]
Message-ID: <CAMFYt2Z+_iPSLQnXXa1Nvw9T79DiYsWZxzLf7WPoE-41ZtGyFA@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2699 bytes --]

Recently I had to solve the following design problem:
I was implementing a high-level wrapper for OpenGL
lights. In order to use the lights, I had to allocate them
before drawing an OpenGL scene, and then release
them after the scene has been drawn.

Initially, I wrote a comment in the function that allocated
the lights that they need to be deallocated. I though,
however, that this is insufficient, because if I ever decided
to reuse the function that allocated the light, I'd need to
read its source code again (which isn't a common practice
-- when I use a function, I'm only interested in what the
function is doing, and not -- how it's doing that)

Instead I finally decided to guarantee that the caller
is at least aware that the light needs to be deallocated,
so that even if it decides to ignore the deallocation, it
does so consciously.

I came up with the idea to throw an exception with current
continuation. The caller can do whatever is needed to later
release the resources, and then call the received continuation.

I wrapped it in the following constructs:

(define (demand to-do-something-with . args)
  (call/cc (lambda(go-on)
             (apply throw 'demand go-on to-do-something-with args)))
  ;; for some reason, the code fails to work without the following
  ;; empty (begin) form
  (begin))

(define-syntax supply
  (syntax-rules ()
    ((_ (((do-something-with . args) do-what ...) ...)
        actions ...)
     (let ((handlers (make-hash-table))
           (unsupported (lambda details
                          (apply throw 'unsupported-reminder
                                 details))))
       (hash-set! handlers (quote do-something-with)
                  (lambda args do-what ...))
       ...
       (catch 'demand
         (lambda () actions ...)
         (lambda (key go-on memorandum . subjects)
           (apply (hash-ref handlers memorandum unsupported) subjects)
           (go-on)))))))

and the whole thing can be used as follows

(let ((resources '()))
  (supply (((release-resource r)
               (set! r (cons r resources))))
    (let ((r (allocate-resource)))
      (demand 'release-resource r)
      (do-something-constructive-with r)))
  (for-each release-resource resources))

(of course, this makes little sense if the
resource is released within the same
procedure it is allocated, but if the release
cannot be performed locally, it seems the
right thing)

I wonder whether this design pattern has ever
been used before, or if there are any potential
flaws with its application.

The advantage is that it reduces the congnitive
load of the programmer: there's less to remember,
because unsatisfied demands remind about
themselves.

Regards

[-- Attachment #2: Type: text/html, Size: 3591 bytes --]

             reply	other threads:[~2013-07-19 10:39 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-19 10:39 Panicz Maciej Godek [this message]
2013-07-19 13:00 ` Exceptions that pass continuations Thien-Thi Nguyen
2013-07-19 13:52   ` Panicz Maciej Godek
2013-07-19 16:14     ` Thien-Thi Nguyen
2013-07-19 14:12   ` Taylan Ulrich B.

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAMFYt2Z+_iPSLQnXXa1Nvw9T79DiYsWZxzLf7WPoE-41ZtGyFA@mail.gmail.com \
    --to=godek.maciek@gmail.com \
    --cc=guile-user@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).