Lisp/Ruby style symbols

Chris Nicholson-Sauls ibisbasenji at gmail.com
Sun Aug 5 11:11:53 PDT 2007


Alex wrote:
> I've been writing a lot of Ruby code lately, and I've really began to appreciate the convenience of certain features (dynamic typing, flexible metaprogramming, etc).  Obviously a lot of these features simply cannot be implemented in D (or would have a very awkward style of implementation), but one little thing that I've found to be very useful are the Lisp style symbols.  For those unfamiliar, it is a concept similar to enumerations, except that instead of having a defined range of values, you simple declare a variable ands set it equal to :name_of_symbol.  This flexibility less code has to be written (no type declaration) and IMHO would make for a nice addition to D.  I'd imagine we could allow something like the following:
> sym my_var = :foo;
> auto my_var2 = :bar;
> 
> any thoughts?  or more importantly, any chance of this actually making it in?

While I also enjoy and make extensive use of this in Ruby, I really 
don't see it making its way into D at all.  In face, you can technically 
use an invariant string to the same effect.  Prior to D/2.0 (and still, 
for now) I've used a class to achieve similar effect.  Here it is off 
the top of my head.

final class Symbol {

   public static class MismatchException : Exception {
     private this (char[] msg) {
       super("Symbol type cannot be compared with other types");
     }
   }

   private static Symbol[char[]] pool ;

   public static Symbol opCall (char[] str) {
     Symbol result ;

     if (auto ptr = str in pool) {
       result = *ptr;
     }
     else {
       auto copy = str.dup;
       pool[copy] = result = new Symbol(copy);
     }
     return result;
   }

   private char[] value ;

   private this (char[] value) {
     this.value = value;
   }

   public bool opEquals (Object other)
   in {
     assert((cast(Symbol) other) !is null);
   }
   body {
     if (auto sym = cast(Symbol) other) {
       return sym is this;
     }
     else {
       // for release code
       throw new MismatchException;
     }
   }

   version (Tango) {
     public char[] toUtf8 () {
       return value.dup;
     }

     alias toUtf8 toString;
   }
   else {
     public char[] toString () {
       return value.dup;
     }
   }

} // end class Symbol

I did mention that's off-top-o'-head, yes?  So it might have some small 
issue.  Remember that even in Ruby Symbol is a class which works in a 
similar fashion to this, except that it also associates a numeric id 
with each symbol, which I haven't bothered doing here.

Again, for D/2.0:
typedef invariant(char)[] symbol ;

Not technically the same, I suppose, as you lose the "this string exists 
exactly once" aspect.  For that, I think you'd have to modify the above 
class to use invariant typing in place of the .dup'ing.

If D were to get a symbol type of some sort, I don't think the :foo 
syntax would work well.  ColdC also has symbols, using the 'foo syntax, 
which also doesn't suit D at all, as it ambiguates with [w|d]char 
literals.  @foo maybe?  Hm.  \@foo even.  Bah, not worth worrying about.

-- Chris Nicholson-Sauls



More information about the Digitalmars-d mailing list