hamster 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +6 -0
 - data/README.rdoc +33 -16
 - data/lib/hamster.rb +1 -0
 - data/lib/hamster/core_ext.rb +2 -0
 - data/lib/hamster/core_ext/enumerable.rb +23 -0
 - data/lib/hamster/core_ext/io.rb +29 -0
 - data/lib/hamster/list.rb +23 -0
 - data/lib/hamster/version.rb +1 -1
 - data/spec/hamster/core_ext/enumerable_spec.rb +34 -0
 - data/spec/hamster/core_ext/io_spec.rb +17 -0
 - data/spec/hamster/core_ext/io_spec.txt +3 -0
 - data/spec/hamster/hash/all_spec.rb +2 -0
 - data/spec/hamster/hash/any_spec.rb +2 -0
 - data/spec/hamster/hash/construction_spec.rb +2 -0
 - data/spec/hamster/hash/copying_spec.rb +2 -0
 - data/spec/hamster/hash/each_spec.rb +2 -0
 - data/spec/hamster/hash/empty_spec.rb +2 -0
 - data/spec/hamster/hash/eql_spec.rb +2 -0
 - data/spec/hamster/hash/filter_spec.rb +2 -0
 - data/spec/hamster/hash/get_spec.rb +2 -0
 - data/spec/hamster/hash/has_key_spec.rb +2 -0
 - data/spec/hamster/hash/map_spec.rb +2 -0
 - data/spec/hamster/hash/none_spec.rb +2 -0
 - data/spec/hamster/hash/put_spec.rb +2 -0
 - data/spec/hamster/hash/reduce_spec.rb +2 -0
 - data/spec/hamster/hash/reject_spec.rb +2 -0
 - data/spec/hamster/hash/remove_spec.rb +2 -0
 - data/spec/hamster/hash/size_spec.rb +2 -0
 - data/spec/hamster/list/all_spec.rb +2 -0
 - data/spec/hamster/list/any_spec.rb +2 -0
 - data/spec/hamster/list/append_spec.rb +65 -0
 - data/spec/hamster/list/cadr_spec.rb +2 -0
 - data/spec/hamster/list/cons_spec.rb +2 -0
 - data/spec/hamster/list/construction_spec.rb +2 -0
 - data/spec/hamster/list/copying_spec.rb +2 -0
 - data/spec/hamster/list/drop_spec.rb +2 -0
 - data/spec/hamster/list/drop_while_spec.rb +2 -0
 - data/spec/hamster/list/each_spec.rb +2 -0
 - data/spec/hamster/list/empty_spec.rb +2 -0
 - data/spec/hamster/list/eql_spec.rb +2 -0
 - data/spec/hamster/list/filter_spec.rb +2 -0
 - data/spec/hamster/list/find_spec.rb +2 -0
 - data/spec/hamster/list/head_spec.rb +2 -0
 - data/spec/hamster/list/include_spec.rb +2 -0
 - data/spec/hamster/list/inspect_spec.rb +2 -0
 - data/spec/hamster/list/map_spec.rb +2 -0
 - data/spec/hamster/list/none_spec.rb +2 -0
 - data/spec/hamster/list/partition_spec.rb +101 -0
 - data/spec/hamster/list/reduce_spec.rb +2 -0
 - data/spec/hamster/list/reject_spec.rb +2 -0
 - data/spec/hamster/list/reverse_spec.rb +43 -0
 - data/spec/hamster/list/size_spec.rb +2 -0
 - data/spec/hamster/list/tail_spec.rb +2 -0
 - data/spec/hamster/list/take_spec.rb +2 -0
 - data/spec/hamster/list/take_while_spec.rb +2 -0
 - data/spec/hamster/list/to_a_spec.rb +2 -0
 - data/spec/hamster/list/to_ary_spec.rb +2 -0
 - data/spec/hamster/set/add_spec.rb +2 -0
 - data/spec/hamster/set/all_spec.rb +2 -0
 - data/spec/hamster/set/any_spec.rb +2 -0
 - data/spec/hamster/set/construction_spec.rb +2 -0
 - data/spec/hamster/set/copying_spec.rb +2 -0
 - data/spec/hamster/set/each_spec.rb +2 -0
 - data/spec/hamster/set/empty_spec.rb +2 -0
 - data/spec/hamster/set/eql_spec.rb +1 -0
 - data/spec/hamster/set/filter_spec.rb +2 -0
 - data/spec/hamster/set/include_spec.rb +2 -0
 - data/spec/hamster/set/map_spec.rb +2 -0
 - data/spec/hamster/set/none_spec.rb +2 -0
 - data/spec/hamster/set/reduce_spec.rb +2 -0
 - data/spec/hamster/set/reject_spec.rb +2 -0
 - data/spec/hamster/set/remove_spec.rb +2 -0
 - data/spec/hamster/set/size_spec.rb +2 -0
 - data/spec/hamster/set/to_a_spec.rb +2 -0
 - data/spec/hamster/stack/construction_spec.rb +2 -0
 - data/spec/hamster/stack/copying_spec.rb +2 -0
 - data/spec/hamster/stack/empty_spec.rb +2 -0
 - data/spec/hamster/stack/eql_spec.rb +2 -0
 - data/spec/hamster/stack/inspect_spec.rb +2 -0
 - data/spec/hamster/stack/pop_spec.rb +2 -0
 - data/spec/hamster/stack/push_spec.rb +2 -0
 - data/spec/hamster/stack/size_spec.rb +2 -0
 - data/spec/hamster/stack/top_spec.rb +2 -0
 - data/spec/spec_helper.rb +0 -2
 - metadata +11 -2
 
    
        data/History.rdoc
    CHANGED
    
    
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -6,8 +6,6 @@ Hamster started out as an implementation of Hash Array Mapped Hashes (HAMT) for 
     | 
|
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            Persistent data structures have a really neat property: very efficient copy-on-write operations. That allows you to create immutable data-structures that only need copying when something changes. For example:
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
              require 'hamster'
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
9 
     | 
    
         
             
              hash = Hamster.hash
         
     | 
| 
       12 
10 
     | 
    
         | 
| 
       13 
11 
     | 
    
         
             
              hash.put("Name", "Simon")
         
     | 
| 
         @@ -18,8 +16,6 @@ Persistent data structures have a really neat property: very efficient copy-on-w 
     | 
|
| 
       18 
16 
     | 
    
         | 
| 
       19 
17 
     | 
    
         
             
            Whoops! Remember, each call to <tt>#put</tt> creates an efficient copy containing the modifications, leaving the original unmodified. So, unlike Ruby's built-in <tt>Hash</tt> all Hamster classes follow Command-Query-Seperation (see http://martinfowler.com/bliki/CommandQuerySeparation.html) and return the modified copy of themselves after any mutating operation. Let's try that again:
         
     | 
| 
       20 
18 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
              require 'hamster'
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
19 
     | 
    
         
             
              original = Hamster.hash
         
     | 
| 
       24 
20 
     | 
    
         
             
              copy = original.put("Name", "Simon")
         
     | 
| 
       25 
21 
     | 
    
         | 
| 
         @@ -28,8 +24,6 @@ Whoops! Remember, each call to <tt>#put</tt> creates an efficient copy containin 
     | 
|
| 
       28 
24 
     | 
    
         | 
| 
       29 
25 
     | 
    
         
             
            The same goes for <tt>#remove</tt>:
         
     | 
| 
       30 
26 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
              require 'hamster'
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
27 
     | 
    
         
             
              original = Hamster.hash
         
     | 
| 
       34 
28 
     | 
    
         
             
              original = original.put("Name", "Simon")
         
     | 
| 
       35 
29 
     | 
    
         
             
              copy = hash.remove("Name")
         
     | 
| 
         @@ -47,8 +41,6 @@ Moreover, because they're immutable, you can pass them around between objects, m 
     | 
|
| 
       47 
41 
     | 
    
         | 
| 
       48 
42 
     | 
    
         
             
            There's a potential performance hit when compared with MRI's built-in, native, hand-crafted C-code implementation of <tt>Hash</tt>. For example:
         
     | 
| 
       49 
43 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
              require 'hamster'
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
44 
     | 
    
         
             
              hash = Hamster.hash
         
     | 
| 
       53 
45 
     | 
    
         
             
              (1..10000).each { |i| hash = hash.put(i, i) }  # => 0.05s
         
     | 
| 
       54 
46 
     | 
    
         
             
              (1..10000).each { |i| hash.get(i) }  # => 0.008s
         
     | 
| 
         @@ -67,8 +59,6 @@ Well, yes and no. The previous comparison wasn't really fair. Sure, if all you w 
     | 
|
| 
       67 
59 
     | 
    
         | 
| 
       68 
60 
     | 
    
         
             
            A more realistic comparison might look like:
         
     | 
| 
       69 
61 
     | 
    
         | 
| 
       70 
     | 
    
         
            -
              require 'hamster'
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
62 
     | 
    
         
             
              hash = Hamster.hash
         
     | 
| 
       73 
63 
     | 
    
         
             
              (1..10000).each { |i| hash = hash.put(i, i) }  # => 0.05s
         
     | 
| 
       74 
64 
     | 
    
         
             
              (1..10000).each { |i| hash.get(i) }  # => 0.008s
         
     | 
| 
         @@ -97,6 +87,9 @@ And don't forget that even if threading isn't a concern for you, the safety prov 
     | 
|
| 
       97 
87 
     | 
    
         | 
| 
       98 
88 
     | 
    
         
             
            Indeed I did.
         
     | 
| 
       99 
89 
     | 
    
         | 
| 
      
 90 
     | 
    
         
            +
            === Sets
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
       100 
93 
     | 
    
         
             
            === Lists
         
     | 
| 
       101 
94 
     | 
    
         | 
| 
       102 
95 
     | 
    
         
             
            Lists have a head--the value of the item at the head of the list--and a tail--containing the remaining items. For example:
         
     | 
| 
         @@ -126,17 +119,41 @@ The following code will only call <tt>prime?</tt> as many times as necessary to 
     | 
|
| 
       126 
119 
     | 
    
         | 
| 
       127 
120 
     | 
    
         
             
            Compare that to the conventional equivalent which needs to calculate all possible values in the range before taking the first 3:
         
     | 
| 
       128 
121 
     | 
    
         | 
| 
       129 
     | 
    
         
            -
              (10000..1000000).select { |i| prime?(i) }[ 
     | 
| 
      
 122 
     | 
    
         
            +
              (10000..1000000).select { |i| prime?(i) }[0, 3]   # => 10s
         
     | 
| 
       130 
123 
     | 
    
         | 
| 
       131 
     | 
    
         
            -
            Besides <tt>Hamster.list</tt> there  
     | 
| 
      
 124 
     | 
    
         
            +
            Besides <tt>Hamster.list</tt> there are other ways to construct lists:
         
     | 
| 
       132 
125 
     | 
    
         | 
| 
       133 
     | 
    
         
            -
            <tt 
     | 
| 
      
 126 
     | 
    
         
            +
            <tt>Hamster.interval(from, to)</tt> (aliased as <tt>.range</tt>) creates a lazy list equivalent to a list containing all the values between <tt>from</tt> and <tt>to</tt> without actually creating a list that big.
         
     | 
| 
       134 
127 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
            <tt 
     | 
| 
      
 128 
     | 
    
         
            +
            <tt>Hamster.stream { ... }</tt> allows you to creates infinite lists. Each time a new value is required, the supplied block is called.
         
     | 
| 
       136 
129 
     | 
    
         | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
      
 130 
     | 
    
         
            +
            You also get <tt>Enumerable#to_list</tt> so you can slowly transition from built-in collection classes to Hamster.
         
     | 
| 
       138 
131 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
      
 132 
     | 
    
         
            +
            And finally, you also <tt>IO#to_list</tt> allowing you to lazily processes huge files. For example, imagine the following code to process a 10MB file:
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
              File.open("my_10_mb_file.txt") do |io|
         
     | 
| 
      
 135 
     | 
    
         
            +
                lines = []
         
     | 
| 
      
 136 
     | 
    
         
            +
                io.each_line do |line|
         
     | 
| 
      
 137 
     | 
    
         
            +
                  break if lines.size == 10
         
     | 
| 
      
 138 
     | 
    
         
            +
                  lines << line.chomp.downcase.reverse
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
              end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            How many times/how long did you read the code before it became apparent what the code actually did? Now compare that to the following:
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
              File.open("my_10_mb_file.txt") do |io|
         
     | 
| 
      
 145 
     | 
    
         
            +
                io.map(&:chomp).map(&:downcase).map(&:reverse)[0, 10]
         
     | 
| 
      
 146 
     | 
    
         
            +
              end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            Unfortunately, though the second example reads nicely, it takes around 3 seconds to run--compared with 0.033 seconds for the first--even though we're only interested in the first 10 lines! However, using a little <tt>#to_list</tt> magic, we can get the running time down to 0.033 seconds!
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
              File.open("my_10_mb_file.txt") do |io|
         
     | 
| 
      
 151 
     | 
    
         
            +
                puts io.to_list.map(&:chomp).map(&:downcase).map(&:reverse).take(10)
         
     | 
| 
      
 152 
     | 
    
         
            +
              end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
            How is this even possible? It's possible because <tt>IO#to_list</tt> creates a lazy list whereby each line is only ever read and processed as needed, in effect converting it to the first example without all the syntactic, imperative, noise.
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
            === Stacks
         
     | 
| 
       140 
157 
     | 
    
         | 
| 
       141 
158 
     | 
    
         
             
            == Disclaimer
         
     | 
| 
       142 
159 
     | 
    
         | 
    
        data/lib/hamster.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'hamster/list'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Hamster
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              module CoreExt
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                module IO
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def to_list(sep = $/)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    line = gets(sep)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    if line
         
     | 
| 
      
 12 
     | 
    
         
            +
                      Stream.new(line) { to_list }
         
     | 
| 
      
 13 
     | 
    
         
            +
                    else
         
     | 
| 
      
 14 
     | 
    
         
            +
                      EmptyList
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            class IO
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              include Hamster::CoreExt::IO
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/hamster/list.rb
    CHANGED
    
    | 
         @@ -164,6 +164,22 @@ module Hamster 
     | 
|
| 
       164 
164 
     | 
    
         
             
                end
         
     | 
| 
       165 
165 
     | 
    
         
             
                alias_method :detect, :find
         
     | 
| 
       166 
166 
     | 
    
         | 
| 
      
 167 
     | 
    
         
            +
                def partition(&block)
         
     | 
| 
      
 168 
     | 
    
         
            +
                  return self unless block_given?
         
     | 
| 
      
 169 
     | 
    
         
            +
                  EmptyList.cons(reject(&block)).cons(filter(&block))
         
     | 
| 
      
 170 
     | 
    
         
            +
                end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                def append(other)
         
     | 
| 
      
 173 
     | 
    
         
            +
                  Stream.new(head) { tail.append(other) }
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
                alias_method :concat, :append
         
     | 
| 
      
 176 
     | 
    
         
            +
                alias_method :cat, :append
         
     | 
| 
      
 177 
     | 
    
         
            +
                alias_method :+, :append
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                def reverse
         
     | 
| 
      
 180 
     | 
    
         
            +
                  reduce(EmptyList) { |list, item| list.cons(item) }
         
     | 
| 
      
 181 
     | 
    
         
            +
                end
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
       167 
183 
     | 
    
         
             
                def eql?(other)
         
     | 
| 
       168 
184 
     | 
    
         
             
                  return false unless other.is_a?(List)
         
     | 
| 
       169 
185 
     | 
    
         | 
| 
         @@ -290,6 +306,13 @@ module Hamster 
     | 
|
| 
       290 
306 
     | 
    
         
             
                    self
         
     | 
| 
       291 
307 
     | 
    
         
             
                  end
         
     | 
| 
       292 
308 
     | 
    
         | 
| 
      
 309 
     | 
    
         
            +
                  def append(other)
         
     | 
| 
      
 310 
     | 
    
         
            +
                    other
         
     | 
| 
      
 311 
     | 
    
         
            +
                  end
         
     | 
| 
      
 312 
     | 
    
         
            +
                  alias_method :concat, :append
         
     | 
| 
      
 313 
     | 
    
         
            +
                  alias_method :cat, :append
         
     | 
| 
      
 314 
     | 
    
         
            +
                  alias_method :+, :append
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
       293 
316 
     | 
    
         
             
                end
         
     | 
| 
       294 
317 
     | 
    
         | 
| 
       295 
318 
     | 
    
         
             
              end
         
     | 
    
        data/lib/hamster/version.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'hamster/core_ext/enumerable'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe Enumerable do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              class TestEnumerable
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(*values)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @values = values
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def each(&block)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @values.each(&block)
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              describe "#to_list" do
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                before do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  enumerable = TestEnumerable.new("A", "B", "C")
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @list = enumerable.to_list
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                it "returns an equivalent list" do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @list == Hamster.list("A", "B", "C")
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'hamster/core_ext/io'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe IO do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              describe "#to_list" do
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                it "returns an equivalent list" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  File.open(File.dirname(__FILE__) + "/io_spec.txt") do |io|
         
     | 
| 
      
 11 
     | 
    
         
            +
                    io.to_list.should == Hamster.list("A\n", "B\n", "C\n")
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     |