# File lib/facet/superstruct.rb, line 53
  def SuperStruct.new(*args)
    @table = []
    @setsyms = []        # Setter symbols
    klass = Class.new
    if (args.size == 1) && (args[0].is_a? Array)
      args = args[0]
    end
    strs = args.map {|x| x.to_s }
    args.each_with_index do |k,i|
      case
        when (! [String,Symbol].include? k.class)
          raise ArgumentError, "Need a String or Symbol"
        when (strs[i] !~ /[_a-zA-Z][_a-zA-Z0-9]*/)
          raise ArgumentError, "Illegal character"
      end
      k = k.intern if k.is_a? String
      @table << k
      @setsyms << (k.to_s + "=").intern
      klass.instance_eval { attr_accessor k }
    end

    setsyms = @setsyms
    table   = @table
    vals    = @vals
    klass.class_eval do
      attr_reader :singleton
      define_method(:initialize) do |*vals|
        n = vals.size
        m = table.size
        case 
          when n < m
            # raise ArgumentError, "Too few arguments (#{n} for #{m})"
            # Never mind... extra variables will just be nil
          when n > m
            raise ArgumentError, "Too many arguments (#{n} for #{m})"
        end
        setsyms.each_with_index do |var,i|
          self.send(var,vals[i])
        end
      end
      define_method(:pretty_print) do |q|  # pp.rb support
        q.object_group(self) do
          q.seplist(self.members, proc { q.text "," }) do |member|
#         self.members.each do |member|
#           q.text ","  # unless q.first?
            q.breakable
            q.text member.to_s
            q.text '='
            q.group(1) do
              q.breakable ''
              q.pp self[member]
            end
          end
        end
      end
      define_method(:inspect) do
        str = "#<#{self.class}:"
        table.each {|item| str << " #{item}=#{self.send(item)}" }
        str + ">"
      end
      define_method(:[]) do |*index|
        case index.map {|x| x.class }
          when [Fixnum]
            self.send(table[*index])
          when [Fixnum,Fixnum], [Range]
            table[*index].map {|x| self.send(x)}
          when [String]
            self.send(index[0].intern)
          when [Symbol]
            self.send(index[0])
        else
          raise ArgumentError,"Illegal index"
        end
      end
      define_method(:[]=) do |*index|
        value = index[-1]
        index = index[0..-2]
        case index.map {|x| x.class }
          when [Fixnum]
            self.send(table[*index])
          when [Fixnum,Fixnum], [Range]
            setsyms[*index].map {|x| self.send(x,value) }
          when [String]
            self.send(index[0].intern,value)
          when [Symbol]
            self.send(index[0],value)
        else
          raise ArgumentError,"Illegal index"
        end
      end
      define_method(:to_a)    { table.map {|x| eval("@"+x.to_s) } }
      define_method(:to_ary)  { to_a }
      define_method(:members) { table.map {|x| x.to_s } }
      define_method(:to_struct) do
        mems = table
        Struct.new("TEMP",*mems)
        # Struct::TEMP.new(*vals) # Why doesn't this work??
        data = mems.map {|x| self.send(x) }
        Struct::TEMP.new(*data)
      end
      define_method(:to_hash) do
        hash = {}
        table.each do |mem|
          mem = mem.to_s
          hash.update(mem => self.send(mem))
        end
        hash
      end
      define_method(:set) {|h| h.each_pair {|k,v| send(k.to_s+"=",v) } }

      # Class methods...

      @singleton = class << self
        self
      end

      @singleton.instance_eval do
        define_method(:members) do 
          table.map {|x| x.to_s }
        end
        me = self
        define_method(:attr_tester) do |*syms| 
          syms.each {|sym| alias_method(sym.to_s+"?",sym) }
        end
      end

    end
    klass
  end