[plt-scheme] %, @, ^, etc.

From: Joe Marshall (jrm at ccs.neu.edu)
Date: Tue Sep 9 09:27:10 EDT 2003

From: "Michael Sperber" <sperber at informatik.uni-tuebingen.de>
> >>>>> "Eli" == Eli Barzilay <eli at barzilay.org> writes:
> Eli>   For list-related administrative tasks:
> Eli>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> Eli> On Sep  8, Anton van Straaten wrote:
> >> 
> >> Do combined prefix-suffix cases count?
> >> 
> >>  *name*  =>  global name
> Eli> I think it makes more sense for global parameters.
> I believe this convention comes from Common Lisp, where DEFVAR has
> consequences on local uses of the same name.  In Scheme, it doesn't
> really make that much sense.

I disagree.  The reason `globals' are `global' is that they are visible
to large amounts of code, and modifications to them can have far-reaching
effects.  In Common Lisp, you tend to dynamically-bind globals more
than you do in Scheme (aka fluid-let), but still the asterisks are a
good indication of `don't SET! this unless you realize that it might
affect a lot of things'.

vis-a-vis prefixes and suffixes:

I use a leading % sign to indicate an `unsafe' routine --- one that
doesn't check arguments, manipulates raw memory, calls out to C,
or does something squirrely.  I usually have a non-% version that
checks the arguments and then calls the %-version.  This is useful
when you are writing low-level, high-performance code:

;;; moves bytes from src to dest where src and dest
;;; are fixnums that represent machine addresses
  (define (%move-bytes src src-start src-end dest dest-start)

  (define (move-bytes src-string src-start src-end dest dest-start)
      (check-type src-string string)
      (check-range src-start 0 (length src-string))
      (gc-interlock (%move-bytes (address-of src-string) src-start ....)))

So the %move-bytes function would presumably compile into a
couple of machine instructions, but it should only be called by something
that checks the safety.  I'll usually have some sort of low-level
abstraction layer that hides this.

I'll put two percent signs for truly insane code:

;;; Mutate a byte-vector to a string by bashing the type code.
(define (byte-vector->string! bv)
  (%%write-memory-offset bv 0 immediate-string-tag))

Two percents means `just because I did this, don't think you can get
away with it'.  Or maybe `close your eyes, nothing to see here....'

Lately, I have become fond of  `type/selector' notation:

    (define (queue/pop! queue)
       (if (queue/empty? queue)
           (error "Queue is empty")
           (let ((head (queue/head queue)))
             (queue/set-head! queue (cdr head))
             (car head))))

This turns out to be rather handy notation in a large system, but
you have to watch out and *not* do this for polymorphic operators.

Posted on the users mailing list.