[gambit-list] ##car ##cdr ##null?

Álvaro Castro-Castilla alvaro.castro.castilla at gmail.com
Fri Jun 11 09:59:42 EDT 2010


El 11 de junio de 2010 15:25, Marc Feeley <feeley at iro.umontreal.ca>escribió:

>
> On 2010-06-11, at 8:34 AM, Álvaro Castro-Castilla wrote:
>
> > Hi,
> >
> > I can see sometimes these kind of procedures ##car, ##cdr, ##null? etc...
> in code that has been optimized for Gambit. What is exactly the difference
> between those and the standard ones? And if these ones are faster, why are
> they defined as separate functions instead of just substituting the standard
> ones when in (unsafe) compilation? Then, how are they really used?
>  >
>
Gambit has a namespace mechanism and identifiers can be qualified with the
> namespace.  So foo#bar is the identifier bar in the namespace foo.  The
> namespace declaration allows mapping unqualified identifiers to a particular
> namespace, so with the code
>


>
> (namespace ("foo#" bar baz))
>
> (bar 123)
> (other#bar 999)
>
> the call to bar is a call to foo#bar and the call to other#bar is really a
> call to other#bar.  So regardless of the namespace declarations, a call to
> ##car will really call ##car.
>
> The Gambit source uses namespace declarations sparingly.  From memory there
> are 3 namespaces in the runtime system:
>
> - "c#" is for the Gambit compiler
> - "sc#" is for the syntax-case expander
> - "##" is for the Gambit runtime system procedures
>
> The Gambit runtime system procedures implement a wide variety of
> functionality, from simple "primitive" procedures (such as ##car, ##pair?,
> ...) that translate to a few machine instructions, to complex procedures
> such as ##eval (the interpreter), ##repl (the REPL), etc.
>
> Gambit's runtime system is built on top of the primitive procedures.  Given
> that most of the runtime system is written in Scheme, for performance it is
> important to have primitives which assume that there are no run time errors.
>  So ##car assumes that its argument is a pair.  The car procedure on the
> other hand does type checking at run time.  In fact, car is defined like
> this (more or less):
>
> (define (car x) (if (##pair? x) (##car x) (error "pair expected"))
>
> When the "not safe" declaration is used (and "standard-bindings"), the
> compiler can avoid the type checking.  So what the compiler does is replace
> the call to car by a call to ##car.  Here's an example:
>
> % cat sum.scm
> (declare (standard-bindings) (not safe))
>
> (define (sum x) (fx+ (car x) (cdr x)))
>
> % gsc -expansion sum.scm
> Expansion:
>
> (define sum
>  (lambda (x)
>    ('#<procedure #2 ##fx+>
>     ('#<procedure #3 ##car> x)
>     ('#<procedure #4 ##cdr> x))))
>
> As you see, it is now explicit what is being called.
>
>



Thanks for the deep explanation, it was really useful.



> Now why are qualified names (such as ##car) used all over the place in the
> runtime system?  Mostly for historical reasons (a large part of the runtime
> system was written before the existence of the namespace mechanism and the
> procedure specializer (i.e. car + "not safe" -> ##car).  I've been wanting
> to "clean things up" for a while now, but that's a major undertaking that
> adds little tangible value to Gambit users.  Perhaps someone on this list
> who likes manual labor would like to refactor the Gambit runtime system...
>  You know where to reach me if you have the urge!
>
> Marc
>
>
Actually I would expect to see that procedures in the runtime
implementation, and I think that is even good, and also saves (perhaps?) a
tiny amount of computation avoiding all the transformations. I wondered
about code that I was reading from different places, of libraries made for
Gambit that I use as reference.

Thanks again for the explanations. Best regards,


Álvaro
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20100611/20b678fb/attachment.htm>


More information about the Gambit-list mailing list