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

Re: Comparing Pika-syle and JNI-style

This page is part of the web mail archives of SRFI 50 from before July 7th, 2015. The new archives for SRFI 50 contain all messages, not just those from before July 7th, 2015.



Tom Lord <lord@xxxxxxx> 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.