[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Guile Impressions

From: Rob Browning
Subject: Re: Guile Impressions
Date: 10 May 2001 15:56:35 -0500
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

John Fitzgerald <address@hidden> writes:

> I am frustrated by the missing documentation, and resorting to code
> reading isn't the best way to answer queries as the answer often
> lies in the dynamic behaviour for which you need to read and
> understand large regions of the program.

And unfortunately, Guile's (use-modules (doc psychic)) is broken ATM.

> Quite possibly.  Approaching it from the necessity to grep
> libguile/*.h to find applicable scm_ and SCM_ items then trying to
> decipher the differences between some of them probably isn't the
> best, but from that viewpoint it does appear to have grown
> haphazardly rather than have been planned.

Right.  There definitely seem to me to be bits of the scm_ interface
that are probably too interpreter specific to be often useful as a
general interface, especially one we want to maintain compatibility
with in the long run, so I think we probably need to make it clear
which functions are considered officially part of the public
interface.  There's been some discussion about that on guile-devel
lately, in fact.

> Perhaps what is needed is a glossary of terms like 'closure',
> 'fluid' and 'continuation' (to name some Scheme language ones) which
> we newbies can refer to to get an plain English description.

OK.  I'm just writing this off the top of my head, but I figured it
might be useful.  Here are some not-so-polished attempts to describe
closures and continuations practically to a C-esque audience.

Closure for C programmers:

  (This isn't a complete description, but should get people on the
   right track...)

  Imagine being able to define some local variables inside a function
  foo and then, right there in the code for foo, create a *new*
  function bar that had access to all those local variables.  Imagine
  further that you could then return the pointer to your new function,
  and when other people called it, it would still be able to access
  the local variables available when it was created.  Imagine still
  further that every time you called foo in order to create a copy of
  bar, each copy had it's own private set of those variables.  The
  code might look something like this (though it's obviously not legal
  C code):

    int (*counter)()
      int local_counter = 0;
      int bar()
        return local_counter++;
      return bar;

  Given that definition, you would be then able to say:

    int (*counter)() counter_a = foo();
    int (*counter)() counter_b = foo();
    printf("a %d\n", counter_a());
    printf("a %d\n", counter_a());
    printf("b %d\n", counter_b());
    printf("b %d\n", counter_b());
    printf("b %d\n", counter_b());
    printf("b %d\n", counter_b());
    printf("a %d\n", counter_a());
    printf("a %d\n", counter_a());

  and the output would be


  Note that I'm not declaring local_counter as a static because, even
  though this is not legal code anyway, I figured it would imply to C
  programmers that there was only one copy of local_counter in the
  entire program, which is not true.  Each instance of bar will have
  it's own private copy of local_counter.

  Note too that if you created several functions inside foo at the
  same time and returned them all, they would all share the same copy
  of local_counter, and could communicate through it among themselves

  If C had closures, you would often not really need to add "void
  *user_data" pointers as arguments to your callback routines.  You
  could just build the function you need, that has access to the data it
  needs when you like.  This, of course, is much more powerful when
  coupled with a garbage collected language

  For example.  Imagine you had were using a GUI button press callback
  that didn't support *any* arguments, but you wanted to be able write
  *one* button_press callback that you could use for several buttons
  and each should print a different message.  You could do that with
  closures like this:

    /* callback prototype -- GUI designer was stingy with args ... */
    void (*button_press)();

    /* we work around that by creating a callback creator function */
    void (*press_func)
    make_button_press_func(const char *message)
      void what_to_do_when_pressed()
        printf("%s", message);
      return what_to_to_when_pressed;
    /* and then we can use it like this */

      gui_button button_a = gui_make_button();
      gui_button button_b = gui_make_button();
      gui_button button_c = gui_make_button();

                                   make_button_press_func("You pushed A/\n"));
                                   make_button_press_func("You pushed B/\n"));
                                   make_button_press_func("You pushed C/\n"));

  etc.  Nifty, huh?  We just don't need for the callback to have any
  user_data style arguments, and when the language is garbage
  collected, you don't have to worry about the allocation/deallocation
  of the strings involved.

Continuations (continued from above example):

  Imagine that at any point in your C program, you could call a
  function that would return to you a newly constructed function that
  if ever called, would jump you right back to the current place in
  the program, including preserving the stack and all of the visible
  variable bindings.  It's like a time-warp function, with the main
  exception that any global variables that have been modified won't be
  reset to the values they had when the time-warp function was
  created.  That time-warp function pointer is a continuation.  It's
  kind of like a longjmp on steroids.

  (This is actually a definition most appropriate to the
   call-with-current-continuation function, but it hopefully gets at
   least the "flavor" of a continuation across.)

Rob Browning <address@hidden> PGP=E80E0D04F521A094 532B97F5D64E3930

reply via email to

[Prev in Thread] Current Thread [Next in Thread]