From: "ara.t.howard" Date: 2010-12-24T16:48:32+09:00 Subject: [ANN] map.rb 2.0.0 ------=_Part_560_12723549.1293176775969 Content-Type: multipart/alternative; boundary="----=_Part_561_2307975.1293176775969" ------=_Part_561_2307975.1293176775969 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit NAME map.rb SYNOPSIS the awesome ruby container you've always wanted: a string/symbol indifferent ordered hash that works in all rubies maps are bitchin ordered hashes that are both ordered, string/symbol indifferent, and have all sorts of sweetness like recursive conversion, more robust implementation than HashWithIndifferentAccess, support for struct like (map.foo) access, and support for option/keyword access which avoids several nasty classes of errors in many ruby libraries INSTALL gem install map URI http://github.com/ahoward/map DESCRIPTION # maps are always ordered. constructing them in an ordered fashion builds # them that way, although the normal hash contructor is also supported # m = Map[:k, :v, :key, :val] m = Map(:k, :v, :key, :val) m = Map.new(:k, :v, :key, :val) m = Map[[:k, :v], [:key, :val]] m = Map(:k => :v, :key => :val) # ruh-oh, the input hash loses order! m = Map.new(:k => :v, :key => :val) # ruh-oh, the input hash loses order! m = Map.new m[:a] = 0 m[:b] = 1 m[:c] = 2 p m.keys #=> ['a','b','c'] ### always ordered! p m.keys #=> [0,1,2] ### always ordered! # maps don't care about symbol vs.string keys # p m[:a] #=> 0 p m["a"] #=> 0 # even via deep nesting # p m[:foo]['bar'][:baz] #=> 42 # many functions operate in a way one would expect from an ordered container # m.update(:k2 => :v2) m.update(:k2, :v2) key_val_pair = m.shift key_val_pair = m.pop # maps keep mapiness for even deep operations # m.update :nested => {:hashes => {:are => :converted}} # maps can give back clever little struct objects # m = Map(:foo => {:bar => 42}) s = m.struct p s.foo.bar #=> 42 # because option parsing is such a common use case for needing string/symbol # indifference map.rb comes out of the box loaded with option support # def foo(*args, &block) opts = Map.options(args) a = opts.getopt(:a) b = opts.getopt(:b, :default => false) end opts = Map.options(:a => 42, :b => nil, :c => false) opts.getopt(:a) #=> 42 opts.getopt(:b) #=> nil opts.getopt(:b, :default => 42) #=> 42 opts.getopt(:c) #=> false opts.getopt(:d, :default => false) #=> false # this avoids such bugs as # options = {:read_only => false} read_only = options[:read_only] || true # should be false but is true # with options this becomes # options = Map.options(:read_only => true) read_only = options.getopt(:read_only, :default => false) #=> true # maps support some really nice operators that hashes/orderedhashes do not # m = Map.new m.set(:h, :a, 0, 42) m.has?(:h, :a) #=> true p m #=> {'h' => {'a' => [42]}} m.set(:h, :a, 1, 42.0) p m #=> {'h' => {'a' => [42, 42.0]}} m.get(:h, :a, 1) #=> 42.0 m.get(:x, :y, :z) #=> nil m[:x][:y][:z] #=> raises exception! # they also support some different iteration styles # m = Map.new m.set( [:a, :b, :c, 0] => 0, [:a, :b, :c, 1] => 10, [:a, :b, :c, 2] => 20, [:a, :b, :c, 3] => 30 ) m.set(:x, :y, 42) m.set(:x, :z, 42.0) m.depth_first_each do |key, val| p key => val end #=> [:a, :b, :c, 0] => 0 #=> [:a, :b, :c, 1] => 10 #=> [:a, :b, :c, 2] => 20 #=> [:a, :b, :c, 3] => 30 #=> [:x, :y] => 42 #=> [:x, :z] => 42.0 USAGE see lib/map.rb and test/map_test.rb ------=_Part_561_2307975.1293176775969 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
NAME
  map.rb

SYNOPSIS
  the awesome ruby container you've always wanted: a stri= ng/symbol indifferent
  ordered hash that works in all = rubies

  maps are bitchin ordered hashes= that are both ordered, string/symbol
  indifferent, an= d have all sorts of sweetness like recursive conversion, more
&nb= sp; robust implementation than HashWithIndifferentAccess, support for = struct
  like (map.foo) access, and support for option/= keyword access which avoids
  several nasty classes of = errors in many ruby libraries

INSTALL
&n= bsp; gem install map

URI
 &nbs= p;http://github.com/ahoward/map

DESCRIPTION
<= div>
# maps are always ordered.  constructing them in an= ordered fashion builds
# them that way, although the normal hash= contructor is also supported
#
  m =3D Map[:= k, :v, :key, :val]
  m =3D Map(:k, :v, :key, :val)
  m =3D Map.new(:k, :v, :key, :val)

  m =3D Map[[:k, :v], [:key, :val]]
  m =3D= Map(:k =3D> :v, :key =3D> :val)  # ruh-oh, the input hash loses= order!
  m =3D Map.new(:k =3D> :v, :key =3D> :va= l)  # ruh-oh, the input hash loses order!

  m =3D Map.new
  m[:a] =3D 0
  m[:b] =3D 1
  m[:c] =3D 2
=
  p m.keys #=3D> ['a','b','c']  ### always= ordered!
  p m.keys #=3D> [0,1,2]     &nb= sp;  ### always ordered!

# maps don't care ab= out symbol vs.string keys
#
  p m[:a]  #= =3D> 0
  p m["a"] #=3D> 0

# even via deep nesting 
#
  p m[:foo]= ['bar'][:baz]  #=3D> 42

# many functions o= perate in a way one would expect from an ordered container
#
  m.update(:k2 =3D> :v2)
  m.update(= :k2, :v2)

  key_val_pair =3D m.shift
  key_val_pair =3D m.pop

# maps k= eep mapiness for even deep operations
#
  m.u= pdate :nested =3D> {:hashes =3D> {:are =3D> :converted}}

# maps can give back clever little struct objects
#
  m =3D Map(:foo =3D> {:bar =3D> 42})
  s =3D m.struct
  p s.foo.bar #=3D> 42<= /div>

# because option parsing is such a common use case= for needing string/symbol
# indifference map.rb comes out of the= box loaded with option support
#
  def foo(*= args, &block)
    opts =3D Map.options(args)
    a =3D opts.getopt(:a)
   &n= bsp;b =3D opts.getopt(:b, :default =3D> false)
  end=


  opts =3D Map.options(:= a =3D> 42, :b =3D> nil, :c =3D> false)
  opts.= getopt(:a)                   &= nbsp;#=3D> 42
  opts.getopt(:b)      =              #=3D> nil
&nb= sp; opts.getopt(:b, :default =3D> 42)    #=3D> 42 = ;
  opts.getopt(:c)           =          #=3D> false
  opts= .getopt(:d, :default =3D> false) #=3D> false

# this avoids such bugs as
#  
  option= s =3D {:read_only =3D> false}
  read_only =3D option= s[:read_only] || true  # should be false but is true

# with options this becomes
#
  optio= ns =3D Map.options(:read_only =3D> true)
  read_only= =3D options.getopt(:read_only, :default =3D> false) #=3D> true
=

# maps support some really nice operators that hashes/o= rderedhashes do not
#
  m =3D Map.new
  m.set(:h, :a, 0, 42)
  m.has?(:h, :a) &n= bsp;       #=3D> true
  p m   &n= bsp;                #=3D> {'h' = =3D> {'a' =3D> [42]}} 
  m.set(:h, :a, 1, 42= .0)
  p m             &nb= sp;      #=3D> {'h' =3D> {'a' =3D> [42, 42.0]}}&nbs= p;

  m.get(:h, :a, 1)     &nbs= p; #=3D> 42.0
  m.get(:x, :y, :z)     &nbs= p;#=3D> nil
  m[:x][:y][:z]       &nb= sp;  #=3D> raises exception!

# they also s= upport some different iteration styles
#
  m = =3D Map.new

  m.set(
 &nb= sp;  [:a, :b, :c, 0] =3D> 0,
    [:a, :b, = :c, 1] =3D> 10,
    [:a, :b, :c, 2] =3D> 20,=
    [:a, :b, :c, 3] =3D> 30
 &n= bsp;)

  m.set(:x, :y, 42)
&nbs= p; m.set(:x, :z, 42.0)

  m.depth_fi= rst_each do |key, val|
    p key =3D> val
=
  end

  #=3D> [:a, :b,= :c, 0] =3D> 0
  #=3D> [:a, :b, :c, 1] =3D> 10=
  #=3D> [:a, :b, :c, 2] =3D> 20
 =  #=3D> [:a, :b, :c, 3] =3D> 30
  #=3D> [:= x, :y] =3D> 42
  #=3D> [:x, :z] =3D> 42.0


USAGE
  see lib/map= .rb and test/map_test.rb

------=_Part_561_2307975.1293176775969-- ------=_Part_560_12723549.1293176775969--