stunted 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -6,3 +6,5 @@ doc
6
6
  Gemfile.lock
7
7
  rdoc
8
8
  pkg/*
9
+ .idea
10
+ TAGS
data/README.md CHANGED
@@ -9,3 +9,9 @@ written by other people.
9
9
 
10
10
  Documentation is in the [wiki](https://github.com/marick/stunted/wiki).
11
11
  There is a mailing list for [functional programming in Ruby](http://groups.google.com/group/rubyfoopers).
12
+
13
+ Contributors:
14
+
15
+ * Brian Marick
16
+ * Edward Monical-Vuylsteke
17
+ * Lar Van Der Jagt
data/Rakefile CHANGED
@@ -7,14 +7,6 @@ Rake::TestTask.new(:test) do |test|
7
7
  test.verbose = true
8
8
  end
9
9
 
10
- require 'rcov/rcovtask'
11
- Rcov::RcovTask.new do |test|
12
- test.libs << 'test'
13
- test.pattern = 'test/**/test_*.rb'
14
- test.verbose = true
15
- test.rcov_opts << '--exclude "gems/*"'
16
- end
17
-
18
10
  task :default => :test
19
11
 
20
12
  require 'rdoc/task'
@@ -1,3 +1,7 @@
1
1
  require "stunted/version"
2
2
  require "stunted/chaining"
3
+ require 'stunted/shapeable'
4
+ require 'stunted/hash-array'
3
5
  require "stunted/functional-hash"
6
+ require "stunted/stutils"
7
+ require "stunted/mocking"
@@ -8,6 +8,7 @@ module Stunted
8
8
  if fn
9
9
  define_method(name) { fn }
10
10
  else
11
+ puts "Lambda rigamarole could be just { block }"
11
12
  define_method(name) { lambda(&block) } # Todo: why is this lambda rigamarole required?
12
13
  end
13
14
  module_function name if respond_to?(:module_function, true)
@@ -1,6 +1,8 @@
1
1
  module Stunted
2
2
 
3
3
  class FunctionalHash < Hash
4
+ include Shapeable
5
+ extend ShapeableClassMethods
4
6
 
5
7
  def initialize(hash = {})
6
8
  hash.each do | k, v |
@@ -32,6 +34,10 @@ module Stunted
32
34
  end
33
35
  alias_method :+, :merge
34
36
 
37
+ def transform(symbol)
38
+ merge(symbol => yield(self[symbol]))
39
+ end
40
+
35
41
  def change_within(*args)
36
42
  if (args.first.is_a? Hash)
37
43
  merge(args.first)
@@ -71,23 +77,11 @@ module Stunted
71
77
  self.class[*keys.zip(self.values_at(*keys)).flatten(1)]
72
78
  end
73
79
 
74
- def self.shaped_class(*shapes)
75
- klass = Class.new(self)
76
- shapes.each do | mod |
77
- klass.send(:include, mod)
78
- end
79
- klass
80
- end
81
-
82
80
  def self.make_maker(*shapes)
83
81
  klass = shaped_class(*shapes)
84
82
  ->(inits={}) { klass.new(inits) }
85
83
  end
86
84
 
87
- def become(*shapes)
88
- self.class.shaped_class(*shapes).new(self)
89
- end
90
-
91
85
  def component(hash) # For now, just one pair
92
86
  field = hash.keys.first
93
87
  shape = hash.values.first
@@ -104,20 +98,4 @@ module Stunted
104
98
  private :[]=, :clear, :delete, :delete_if
105
99
  end
106
100
 
107
-
108
- module FHUtil
109
- def F(hash = {})
110
- FunctionalHash.new(hash)
111
- end
112
-
113
- def Fonly(tuples)
114
- F(tuples.first)
115
- end
116
-
117
- def Fall(tuples)
118
- tuples.map { | row | F(row) }
119
- end
120
- end
121
-
122
-
123
101
  end
@@ -0,0 +1,20 @@
1
+ module Stunted
2
+ class HashArray < Array
3
+ include Shapeable
4
+ extend ShapeableClassMethods
5
+
6
+ def collapse_and_aggregate(*keys)
7
+ keys.reduce(first) do | accumulator, key |
8
+ collection = collect(&key)
9
+ collection = yield(collection) if block_given?
10
+ accumulator.merge(key => collection)
11
+ end
12
+ end
13
+
14
+ def segregate_by_key(key)
15
+ group_by(&key).values.collect do | inner |
16
+ self.class.new(inner)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ class Module
2
+ def with_replacement_methods(hash)
3
+ old_pairs = hash.collect do | key, value |
4
+ old_method = instance_method(key)
5
+ define_method(key, value)
6
+ [key, old_method]
7
+ end
8
+ yield
9
+ ensure
10
+ old_pairs.each { | pair | define_method(*pair) }
11
+ end
12
+ end
13
+
14
+ module Stunted
15
+
16
+ class FunctionalHash
17
+ def with_replacement_methods(hash, &block)
18
+ self.class.with_replacement_methods(hash, &block)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Stunted
2
+ module ShapeableClassMethods
3
+ def shaped_class(*shapes)
4
+ klass = Class.new(self)
5
+ shapes.each do | mod |
6
+ klass.send(:include, mod)
7
+ end
8
+ klass
9
+ end
10
+ end
11
+
12
+ module Shapeable
13
+ def become(*shapes)
14
+ return self if shapes.empty?
15
+ self.class.shaped_class(*shapes).new(self)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ module Stunted
2
+ module Stutils
3
+ def F(hash = {}, *shapes)
4
+ FunctionalHash.new(hash).become(*shapes)
5
+ end
6
+
7
+ def Fonly(tuples, *shapes)
8
+ F(tuples.first, *shapes)
9
+ end
10
+
11
+ def Fall(tuples, *args)
12
+ first = args.first
13
+ if first.is_a?(Hash)
14
+ array_shapes = first[:array] || []
15
+ hash_shapes = first[:hash] || []
16
+ else
17
+ hash_shapes = args
18
+ array_shapes = []
19
+ end
20
+ HashArray.new(tuples.map { | row | F(row, *hash_shapes) }).
21
+ become(*array_shapes)
22
+ end
23
+ end
24
+
25
+ Stutil = Stutils unless defined?(Stutil) # Backward compatibility
26
+ FHUtil = Stutils unless defined?(FHUtil) # Backward compatibility
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Stunted
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -20,11 +20,9 @@ Gem::Specification.new do |s|
20
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
21
  s.require_paths = ["lib"]
22
22
 
23
- s.add_runtime_dependency "hamster"
24
-
25
23
  s.add_development_dependency "shoulda", ">= 0"
26
- s.add_development_dependency "assert2"
27
- s.add_development_dependency "bundler", "~> 1.0.0"
24
+ s.add_development_dependency "bundler"
28
25
  s.add_development_dependency "jeweler", "~> 1.6.4"
29
- s.add_development_dependency "rcov", ">= 0"
26
+ s.add_development_dependency "test-unit"
27
+ s.add_development_dependency "wrong"
30
28
  end
@@ -2,7 +2,7 @@ require 'helper'
2
2
 
3
3
  class FunctionalHashTest < Test::Unit::TestCase
4
4
  include Stunted
5
- include Stunted::FHUtil
5
+ include Stunted::Stutils
6
6
 
7
7
 
8
8
  context "non-lazy behavior" do
@@ -24,7 +24,9 @@ class FunctionalHashTest < Test::Unit::TestCase
24
24
  end
25
25
  end
26
26
 
27
+
27
28
  context "lazy behavior" do
29
+ puts "==== What is the behavior with procs good for?"
28
30
  should "take procs as arguments and evaluate them on demand" do
29
31
  @sut = FunctionalHash.new(:a => lambda { @global })
30
32
  @global = 33
@@ -86,7 +88,17 @@ class FunctionalHashTest < Test::Unit::TestCase
86
88
  assert { empty.object_id != sut.object_id }
87
89
  end
88
90
 
89
- context "changing within" do
91
+ should "allow transformations of particular key values" do
92
+ sut = FunctionalHash.new(value: 5)
93
+ new_sut = sut.transform(:value) { | value | value * 3 }
94
+ assert { new_sut.value == 15 }
95
+
96
+ sut = FunctionalHash.new("string-key" => 1)
97
+ new_sut = sut.transform("string-key") { | value | value * 3 }
98
+ assert { new_sut["string-key"] == 3 }
99
+ end
100
+
101
+ context "removing within" do
90
102
  setup do
91
103
  @hashlike = F(:val => 3,
92
104
  :other => "other",
@@ -104,7 +116,7 @@ class FunctionalHashTest < Test::Unit::TestCase
104
116
  end
105
117
 
106
118
  should "allow nesting" do
107
- actual = @hashlike.change_within(:nested, val => 44)
119
+ actual = @hashlike.change_within(:nested, :val => 44)
108
120
  assert { actual.is_a?(FunctionalHash) }
109
121
  assert { actual.val == 3 }
110
122
  assert { actual.nested.val == 44 }
@@ -112,7 +124,7 @@ class FunctionalHashTest < Test::Unit::TestCase
112
124
  end
113
125
 
114
126
  should "allow n levels of nesting" do
115
- actual = @hashlike.change_within(:nested, :nested, val => 444)
127
+ actual = @hashlike.change_within(:nested, :nested, :val => 444)
116
128
  assert { actual.is_a?(FunctionalHash) }
117
129
  assert { actual.val == 3 }
118
130
  assert { actual.nested.val == 33 }
@@ -261,6 +273,9 @@ class FunctionalHashTest < Test::Unit::TestCase
261
273
  end
262
274
 
263
275
  end
276
+
277
+
278
+
264
279
  end
265
280
  end
266
281
 
@@ -0,0 +1,74 @@
1
+ require 'helper'
2
+
3
+ class HashArrayTest < Test::Unit::TestCase
4
+ include Stunted
5
+ include Stunted::Stutils
6
+
7
+ context "collapsing a hash-array into one hash" do
8
+ should "aggregate named key values into an array" do
9
+ input = Fall([ {:id => 33, :name => "fred"},
10
+ {:id => 33, :name => "betsy"} ])
11
+
12
+ actual = input.collapse_and_aggregate(:name)
13
+ expected = {:id => 33, :name => ["fred", "betsy"]}
14
+ assert { actual == expected }
15
+ end
16
+
17
+ should "aggregate allow multiple keys" do
18
+ input = Fall([ {:id => 33, :name => "fred", :hair => 3},
19
+ {:id => 33, :name => "betsy", :hair => 44} ])
20
+
21
+ actual = input.collapse_and_aggregate(:name, :hair)
22
+ expected = {:id => 33, :name => ["fred", "betsy"], :hair => [3, 44]}
23
+ assert { actual == expected }
24
+ end
25
+
26
+ should "silently do the wrong thing if non-constant keys are not named" do
27
+ input = Fall([ {:id => 33, :name => "fred", :hair => 3},
28
+ {:id => 33, :name => "betsy", :hair => 44} ])
29
+ actual = input.collapse_and_aggregate(:name)
30
+ deny { actual.hair == [3, 44] }
31
+ end
32
+
33
+ should "take a block that can be used to process the arrays" do
34
+ input = Fall([ {:id => 33, :name => "fred", :hair => 3},
35
+ {:id => 33, :name => "betsy", :hair => 44},
36
+ {:id => 33, :name => "fred", :hair => 44},
37
+ {:id => 33, :name => "betsy", :hair => 3}])
38
+ actual = input.collapse_and_aggregate(:name, :hair) { | a | a.sort.uniq }
39
+ expected = {:id => 33, :name => ["betsy", "fred"], :hair => [3, 44]}
40
+ assert { actual == expected }
41
+ end
42
+ end
43
+
44
+ context "segregation by keys" do
45
+ setup do
46
+ @input = Fall([ {:id => 1, :name => "fred"},
47
+ {:id => 2, :name => "betsy"},
48
+ {:id => 1, :name => "dawn"} ])
49
+
50
+ @actual = @input.segregate_by_key(:id)
51
+ @expected = [ [ {:id => 1, :name => "fred"},
52
+ {:id => 1, :name => "dawn"} ],
53
+ [ {:id => 2, :name => "betsy"} ] ]
54
+ end
55
+
56
+ should "produce an array of arrays" do
57
+ assert { @actual == @expected }
58
+ end
59
+
60
+ should "make the inner arrays HashArrays" do
61
+ assert { @actual.first.is_a?(Stunted::HashArray) }
62
+ end
63
+ end
64
+
65
+ context "shapeability" do
66
+ module ArrayShaped
67
+ def neg_count; -count; end
68
+ end
69
+
70
+ should "also apply to hash arrays" do
71
+ assert { Fall([ {:a => 1}]).become(ArrayShaped).neg_count == -1 }
72
+ end
73
+ end
74
+ end
@@ -9,11 +9,12 @@ rescue Bundler::BundlerError => e
9
9
  end
10
10
  require 'test/unit'
11
11
  require 'shoulda'
12
- require 'assert2'
12
+ require 'wrong'
13
13
 
14
14
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
15
  $LOAD_PATH.unshift(File.dirname(__FILE__))
16
16
  require 'stunted'
17
17
 
18
18
  class Test::Unit::TestCase
19
+ include Wrong
19
20
  end
@@ -0,0 +1,118 @@
1
+ require 'helper'
2
+
3
+ class FunctionalHashTest < Test::Unit::TestCase
4
+ include Stunted
5
+ include Stunted::Stutils
6
+
7
+ context "mocking out methods via a class" do
8
+ class ClassWithMethods < FunctionalHash
9
+ def my_method; "value of unmocked method"; end
10
+ end
11
+
12
+ should "be able to temporarily replace a module's instance methods" do
13
+ ClassWithMethods.with_replacement_methods(my_method: -> { "replaced value" }) do
14
+ assert { ClassWithMethods.new.my_method == "replaced value" }
15
+ end
16
+ assert { ClassWithMethods.new.my_method == "value of unmocked method" }
17
+ end
18
+
19
+ should "undo the replacement no matter what" do
20
+ assert_raises(Exception) do
21
+ ClassWithMethods.with_replacement_methods(my_method: -> { "replaced value" }) do
22
+ raise Exception.new("boom")
23
+ end
24
+ end
25
+ assert { ClassWithMethods.new.my_method == "value of unmocked method" }
26
+ end
27
+
28
+ should "keep the modified instance methods for all versions of the object" do
29
+ ClassWithMethods.with_replacement_methods(my_method: -> a { merge(value: self.value * a) }) do
30
+ first = ClassWithMethods.new(value: 1)
31
+ second = first.my_method(5)
32
+ third = second.my_method(10)
33
+
34
+ assert { second.value == 5 }
35
+ assert { third.value == 50 }
36
+ end
37
+ end
38
+
39
+ should "The overriding of the method ends at the end of the block" do
40
+ initial = "declared local"
41
+ ClassWithMethods.with_replacement_methods(my_method: -> a { merge(value: self.value * a)}) do
42
+ initial = ClassWithMethods.new
43
+ end
44
+ assert { initial.my_method == "value of unmocked method" }
45
+ end
46
+
47
+ end
48
+
49
+ module ModuleWithMethods
50
+ def my_method; "value of unmocked method"; end
51
+ end
52
+
53
+ context "mocking out methods on a module" do
54
+ class ClassWithIncludedMethods < FunctionalHash
55
+ include ModuleWithMethods
56
+ end
57
+
58
+ should "be able to temporarily replace a module's instance methods" do
59
+ ModuleWithMethods.with_replacement_methods(my_method: -> { "replaced value" }) do
60
+ assert { ClassWithIncludedMethods.new.my_method == "replaced value" }
61
+ end
62
+ assert { ClassWithIncludedMethods.new.my_method == "value of unmocked method" }
63
+ end
64
+ end
65
+
66
+ context 'mocking out methods for a "made" class' do
67
+ maker = FunctionalHash.make_maker(ModuleWithMethods)
68
+
69
+ should "be able to temporarily replace a made class's instance methods" do
70
+ maker.().class.with_replacement_methods(my_method: -> { "replaced value" }) do
71
+ assert { maker.().my_method == "replaced value" }
72
+ end
73
+ assert { maker.().my_method == "value of unmocked method" }
74
+ end
75
+
76
+ should "The overriding of the method ends at the end of the block" do
77
+ initial = "declared local"
78
+ ClassWithMethods.with_replacement_methods(my_method: -> a { merge(value: self.value * a)}) do
79
+ initial = ClassWithMethods.new
80
+ end
81
+ assert { initial.my_method == "value of unmocked method" }
82
+ end
83
+ end
84
+
85
+ context "mocking particular objects" do
86
+ should "be able to apply the mock function to an object, not just a module." do
87
+ object = ClassWithMethods.new
88
+ object.with_replacement_methods(my_method: -> { "replaced value" }) do
89
+ assert { object.my_method == "replaced value" }
90
+ end
91
+ assert { object.my_method == "value of unmocked method" }
92
+ end
93
+
94
+ should_eventually "changing one object's methods doesn't affect another's" do
95
+ mocked = ClassWithMethods.new
96
+ unmocked = ClassWithMethods.new
97
+ mocked.with_replacement_methods(my_method: -> { "replaced value" }) do
98
+ assert { unmocked.my_method == "value of unmocked method" }
99
+ end
100
+ end
101
+
102
+ end
103
+
104
+ context "mocking out lambdas attached to a class" do
105
+ class ClassWithLambdas < FunctionalHash
106
+ extend Stunted::Defn
107
+ defn :my_lambda, -> { "value of unmocked lambda" }
108
+ end
109
+
110
+ should_eventually "be able to temporarily replace a module's `defn`ed lambdas" do
111
+ ClassWithLambdas.with_replacement_methods(my_lambda: -> { "replaced value" }) do
112
+ assert { ClassWithLambdas.new.my_lambda.() == "replaced value" }
113
+ end
114
+ assert { ClassWithLambdas.new.my_lambda.() == "value of unmocked lambda" }
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ class ShapeableTests < Test::Unit::TestCase
4
+ include Stunted
5
+ include Stunted::Stutils
6
+
7
+ # Mostly tested through use in including classes
8
+
9
+ module Shapely
10
+ end
11
+
12
+ should "normally return a new class" do
13
+ # For some reason, putting this inside an `assert` makes test hang.
14
+ klass = FunctionalHash.new.become(Shapely).class
15
+ # The test library hangs if it tries to print a class created by
16
+ # Class.new
17
+ test = (klass == FunctionalHash); deny { test }
18
+ test = klass.ancestors.include?(FunctionalHash); assert { test }
19
+ end
20
+
21
+ should "not return a new class if there is nothing to become" do
22
+ # For some reason, putting this inside an `assert` makes test hang.
23
+ klass = FunctionalHash.new.become().class
24
+ test = (klass == FunctionalHash); assert { test }
25
+ end
26
+
27
+ end
28
+
@@ -0,0 +1,83 @@
1
+ require 'helper'
2
+
3
+ class StutilsTest < Test::Unit::TestCase
4
+ include Stunted
5
+ include Stunted::Stutils
6
+
7
+ module Upable
8
+ def up; "up!"; end
9
+ end
10
+
11
+ module Downable
12
+ def down; "down!"; end
13
+ end
14
+
15
+ context "F" do
16
+ should "create a functional hash" do
17
+ # Only is a function that's not on the real Hash
18
+ assert { F(:a => 1, :b => 2).only(:a).is_a? FunctionalHash }
19
+ end
20
+
21
+ should "allow shape to be specified" do
22
+ h = F({}, Upable, Downable)
23
+ assert { h.up == "up!" }
24
+ assert { h.down == "down!" }
25
+ end
26
+ end
27
+
28
+ context "Fonly" do
29
+ should "create a functional hash from within an array" do
30
+ h = Fonly([{}], Upable, Downable)
31
+ assert { h.is_a? FunctionalHash }
32
+ assert { h.up == "up!" }
33
+ assert { h.down == "down!" }
34
+ end
35
+ end
36
+
37
+ context "Fall" do
38
+ should "create a HashArray wrapping Functional Hashes" do
39
+ a = Fall([{}])
40
+ assert { a.is_a?(HashArray) }
41
+ assert { a.first.is_a?(FunctionalHash) }
42
+ end
43
+
44
+ should "shape the hash entries if given one or more arguments" do
45
+ a = Fall([{}], Upable)
46
+ assert {a.first.respond_to?(:up) }
47
+ deny {a.first.respond_to?(:down) }
48
+
49
+ a = Fall([{}], Upable, Downable)
50
+ assert {a.first.respond_to?(:up) }
51
+ assert {a.first.respond_to?(:down) }
52
+ end
53
+
54
+ should "allow the shape of the array to be given" do
55
+ a = Fall([{}], :array => Upable)
56
+ assert {a.up == "up!" }
57
+ deny {a.first.respond_to?(:up) }
58
+ end
59
+
60
+ should "allow more than one shape for the array" do
61
+ a = Fall([{}], :array => [Upable, Downable])
62
+ assert {a.up == "up!" }
63
+ assert {a.down == "down!" }
64
+ end
65
+
66
+ should "allow both array and hash to be shaped" do
67
+ a = Fall([{}], :array => Upable, :hash => Downable)
68
+ assert {a.respond_to?(:up) }
69
+ deny {a.respond_to?(:down) }
70
+ assert {a.first.respond_to?(:down) }
71
+ deny {a.first.respond_to?(:up) }
72
+ end
73
+
74
+ should "allow both array and hash to be shaped with multiple shapes" do
75
+ a = Fall([{}], :array => [Upable, Downable], :hash => [Upable, Downable])
76
+ assert {a.respond_to?(:up) }
77
+ assert {a.respond_to?(:down) }
78
+ assert {a.first.respond_to?(:down) }
79
+ assert {a.first.respond_to?(:up) }
80
+ end
81
+ end
82
+ end
83
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stunted
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-19 00:00:00.000000000Z
12
+ date: 2012-04-20 00:00:00.000000000Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: hamster
16
- requirement: &2156591000 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: *2156591000
25
14
  - !ruby/object:Gem::Dependency
26
15
  name: shoulda
27
- requirement: &2156590360 !ruby/object:Gem::Requirement
16
+ requirement: &2153385740 !ruby/object:Gem::Requirement
28
17
  none: false
29
18
  requirements:
30
19
  - - ! '>='
@@ -32,10 +21,10 @@ dependencies:
32
21
  version: '0'
33
22
  type: :development
34
23
  prerelease: false
35
- version_requirements: *2156590360
24
+ version_requirements: *2153385740
36
25
  - !ruby/object:Gem::Dependency
37
- name: assert2
38
- requirement: &2156395500 !ruby/object:Gem::Requirement
26
+ name: bundler
27
+ requirement: &2153385340 !ruby/object:Gem::Requirement
39
28
  none: false
40
29
  requirements:
41
30
  - - ! '>='
@@ -43,32 +32,32 @@ dependencies:
43
32
  version: '0'
44
33
  type: :development
45
34
  prerelease: false
46
- version_requirements: *2156395500
35
+ version_requirements: *2153385340
47
36
  - !ruby/object:Gem::Dependency
48
- name: bundler
49
- requirement: &2156394280 !ruby/object:Gem::Requirement
37
+ name: jeweler
38
+ requirement: &2153384800 !ruby/object:Gem::Requirement
50
39
  none: false
51
40
  requirements:
52
41
  - - ~>
53
42
  - !ruby/object:Gem::Version
54
- version: 1.0.0
43
+ version: 1.6.4
55
44
  type: :development
56
45
  prerelease: false
57
- version_requirements: *2156394280
46
+ version_requirements: *2153384800
58
47
  - !ruby/object:Gem::Dependency
59
- name: jeweler
60
- requirement: &2156393420 !ruby/object:Gem::Requirement
48
+ name: test-unit
49
+ requirement: &2153384380 !ruby/object:Gem::Requirement
61
50
  none: false
62
51
  requirements:
63
- - - ~>
52
+ - - ! '>='
64
53
  - !ruby/object:Gem::Version
65
- version: 1.6.4
54
+ version: '0'
66
55
  type: :development
67
56
  prerelease: false
68
- version_requirements: *2156393420
57
+ version_requirements: *2153384380
69
58
  - !ruby/object:Gem::Dependency
70
- name: rcov
71
- requirement: &2156392760 !ruby/object:Gem::Requirement
59
+ name: wrong
60
+ requirement: &2153383860 !ruby/object:Gem::Requirement
72
61
  none: false
73
62
  requirements:
74
63
  - - ! '>='
@@ -76,7 +65,7 @@ dependencies:
76
65
  version: '0'
77
66
  type: :development
78
67
  prerelease: false
79
- version_requirements: *2156392760
68
+ version_requirements: *2153383860
80
69
  description: Support code for functional programming
81
70
  email: marick@exampler.com
82
71
  executables: []
@@ -100,12 +89,20 @@ files:
100
89
  - lib/stunted.rb
101
90
  - lib/stunted/chaining.rb
102
91
  - lib/stunted/functional-hash.rb
92
+ - lib/stunted/hash-array.rb
93
+ - lib/stunted/mocking.rb
94
+ - lib/stunted/shapeable.rb
95
+ - lib/stunted/stutils.rb
103
96
  - lib/stunted/version.rb
104
97
  - stunted.gemspec
105
98
  - test/chainable-tests.rb
106
99
  - test/defn-tests.rb
107
100
  - test/functional-hash-test.rb
101
+ - test/hash-array-tests.rb
108
102
  - test/helper.rb
103
+ - test/mocking-tests.rb
104
+ - test/shapeable-tests.rb
105
+ - test/stutils-test.rb
109
106
  homepage: http://github.com/marick/stunted
110
107
  licenses:
111
108
  - MIT
@@ -135,4 +132,8 @@ test_files:
135
132
  - test/chainable-tests.rb
136
133
  - test/defn-tests.rb
137
134
  - test/functional-hash-test.rb
135
+ - test/hash-array-tests.rb
138
136
  - test/helper.rb
137
+ - test/mocking-tests.rb
138
+ - test/shapeable-tests.rb
139
+ - test/stutils-test.rb