Re: Comparing Pika-syle and JNI-style Jim Blandy 14 Jan 2004 20:45 UTC

Tom Lord <xxxxxx@emf.net> writes:
> /* untested code */
> t_scm_error
> scm_assq (t_scm_word * answer,
>           t_scm_arena instance,
>           t_scm_word * key,
>           t_scm_word * alist)
> {
>   struct assq_frame
>   {
>     SCM_FRAME;
>     scm_word_t * pair;
>     scm_word_t * key;
>   } l;
>
>   SCM_PROTECT_FRAME (l);
>
>
>   scm_make_false (answer, instance);
>
>   while (scm_is_pair (instance, alist))
>     {
>       scm_car (&l.pair, instance, alist);
>       scm_car (&l.key, instance, &l.pair);
>       if (scm_values_eq (instance, &l.key, key))
>         {
>           SCM_LSET (answer, instance, &l.pair);
>           break;
>         }
>       scm_cdr (alist, instance, alist);
>     }
>
>   SCM_UNPROTECT_FRAME (l);
>   return 0;
> }

It's worth noting here that SCM_LSET is essentially a 'linearizing'
assignment operator.  I'd been thinking of providing a similar
operator for Minor:

    /* Free the reference DEST, if DEST is non-zero; then return SRC.
       This is meant to help free a variable's value before assigning
       to it:

          x = mn_set (c, x, new_value);  */
    mn_ref *mn_set (mn_call *, mn_ref *dest, mn_ref *src);

If Minor provided an operator like that, then one could write the
Minor example in a very similar fashion to the Pika example:

     mn_ref *
     assq (mn_call *c, mn_ref *key, mn_ref *alist)
     {
       mn_ref *pair = 0;
       mn_ref *pair_key = 0;

       while (mn_pair_p (c, alist))
         {
           pair     = mn_set (c, pair,     mn_car (c, alist));
           pair_key = mn_set (c, pair_key, mn_car (c, pair));

           if (mn_ref_eq (c, key, pair_key))
             return pair;

           alist = mn_to_cdr (c, alist);
         }

       return mn_false (c);
     }

Here's Tom's code again, for reference:

    /* untested code */
    t_scm_error
    scm_assq (t_scm_word * answer,
              t_scm_arena instance,
              t_scm_word * key,
              t_scm_word * alist)
    {
      struct assq_frame
      {
        SCM_FRAME;
        scm_word_t * pair;
        scm_word_t * key;
      } l;

      SCM_PROTECT_FRAME (l);

      scm_make_false (answer, instance);

      while (scm_is_pair (instance, alist))
        {
          scm_car (&l.pair, instance, alist);
          scm_car (&l.key, instance, &l.pair);
          if (scm_values_eq (instance, &l.key, key))
            {
              SCM_LSET (answer, instance, &l.pair);
              break;
            }
          scm_cdr (alist, instance, alist);
        }

      SCM_UNPROTECT_FRAME (l);
      return 0;
    }

I think this underscores how fundamentally similar the two are:
- Minor calls correspond to Pika frames.
- Minor heap-allocates while Pika stack-allocates.

I think the biggest difference between the two is that Pika ties
reference lifetimes very tightly to lexical block lifetimes, whereas
Minor binds them to call lifetimes, but allows/requires you to do some
other explicit frees.  Each has some advantages and some
disadvantages.