lambda_driver 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -82,22 +82,70 @@ This method is aliased as `<<`.
82
82
  f << g < :hoge # => "44" ( == f.call(g.call(:hoge)) )
83
83
  ```
84
84
 
85
+ #### Proc#lift
86
+
87
+ Lift this function to the given context-function.
88
+ The lifted fucntion can compose other function with context-fucntion.
89
+
90
+ The given context-fuction used by `compose_with_lifting`
91
+ to compose other fucntion.
92
+
93
+ The context-funciton should recieve 2 arguments.
94
+
95
+ - first one is a function that reciver function of `compose_with_lifting` method.
96
+ - second arg is a result of g(x)
97
+ - g is a function passed to `compose_with_lifting`
98
+
85
99
 
86
100
  #### Proc#compose_with_lifting
87
101
 
88
- compose self and give fuction with checking g(x) is mzero.
102
+ Compose self and given function on the context-function.
103
+ The context-funciton is passed by `lift` method.
104
+
105
+ This method returns composed funciton like bellow.
106
+
107
+ ```ruby
108
+ lambda{|args| context(self, g(*args)) }
109
+ ```
110
+
111
+ For example, set context-function that logging the result.
112
+
113
+ ```ruby
114
+ hash = {:a => "foo"}
115
+ f = lambda{|x| x.length}
116
+ g = lambda{|y| hash[y]}
117
+
118
+ ctx = lambda{|f,x|
119
+ puts "g(x) -> #{x}"
120
+ y = f.call(x)
121
+ puts "f(g(x)) -> #{y}"
122
+ y
123
+ }
124
+
125
+ lifted = f.lift(ctx)
126
+ h = lifted.compose_with_lifting g
127
+
128
+ h.(:a)
129
+ #=> g(x) -> foo # output by ctx
130
+ #=> f(g(x)) -> 3 # output by ctx
131
+ #=> 3
132
+ ```
133
+
134
+ if context-function does not given,
135
+ default behaivior is compose function with checking g(x) is mzoro
136
+
89
137
  if g(x) is mzero, it does not call self and return g(x),
90
138
  otherwise returns f(g(x)).
91
139
 
92
140
  mzero means the object is nil or emtpy
93
141
 
94
142
  ```ruby
95
- hash = {:a => "foo"}
96
- f = lambda{|y| y.length }
97
- g = lambda{|y| hash[y]}
98
- h = f.compose_with_lifting g
99
- h.(:a) # => 3
100
- h.(:b) # => nil (it does not called f)
143
+ hash = {:a => "foo"}
144
+ f = lambda{|y| y.length }
145
+ g = lambda{|y| hash[y]}
146
+ h = f.compose_with_lifting g
147
+ h.(:a) # => 3
148
+ h.(:b) # => nil (it does not called f)
101
149
  ```
102
150
 
103
151
  This method is aliased as `<=`.
@@ -106,7 +154,6 @@ This method is aliased as `<=`.
106
154
  f <= g # => f.compose_with_lifting(g)
107
155
  ```
108
156
 
109
-
110
157
  #### Proc#with_args
111
158
 
112
159
  Returns partially applied function that has 2nd and more parameters are
@@ -1,7 +1,37 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module LambdaDriver::Liftable
3
3
 
4
- # compose self and give fuction with checking g(x) is mzero.
4
+ # Compose self and given function on the context-function.
5
+ # The context-funciton is passed by `lift` method.
6
+ #
7
+ # This method returns composed funciton like bellow.
8
+ #
9
+ # lambda{|args| context(self, g(*args)) }
10
+ #
11
+ # For example, set context-function that logging the result.
12
+ #
13
+ # hash = {:a => "foo"}
14
+ # f = lambda{|x| x.length}
15
+ # g = lambda{|y| hash[y]}
16
+ #
17
+ # ctx = lambda{|f,x|
18
+ # puts "g(x) -> #{x}"
19
+ # y = f.call(x)
20
+ # puts "f(g(x)) -> #{y}"
21
+ # y
22
+ # }
23
+ #
24
+ # lifted = f.lift(ctx)
25
+ # h = lifted.compose_with_lifting g
26
+ #
27
+ # h.(:a)
28
+ # #=> g(x) -> foo
29
+ # #=> f(g(x)) -> 3
30
+ # #=> 3
31
+ #
32
+ # if context-function does not given,
33
+ # default behaivior is compose function with checking g(x) is mzoro
34
+ #
5
35
  # if g(x) is mzero, it does not call self and return g(x),
6
36
  # otherwise returns f(g(x)).
7
37
  #
@@ -19,15 +49,53 @@ module LambdaDriver::Liftable
19
49
  # f <= g # => f.compose_with_lifting(g)
20
50
  #
21
51
  def compose_with_lifting(g)
22
- lambda{|*args|
23
- result = g.to_proc.call(*args)
24
- mzero_method = result.respond_to?(:mzero?) ? :mzero? : :nil?
25
- result.send(mzero_method) ? result : self.to_proc.call(result)
26
- }
52
+ context = lambda_driver_liftable_context
53
+
54
+ lambda{|*args| context.call(self.to_proc, g.to_proc.call(*args)) }.lift(context)
55
+ end
56
+
57
+ # This is a default context-function.
58
+ # default behaivior is compose function with checking g(x) is mzoro
59
+ #
60
+ # if g(x) is mzero, it does not call self and return g(x),
61
+ # otherwise returns f(g(x)).
62
+ #
63
+ # mzero means the object is nil or emtpy
64
+ #
65
+ # hash = {:a => "foo"}
66
+ # f = lambda{|y| y.length }
67
+ # g = lambda{|y| hash[y]}
68
+ # h = f.compose_with_lifting g
69
+ # h.(:a) # => 3
70
+ # h.(:b) # => nil (it does not called f)
71
+ #
72
+ DEFAULT_CONTEXT = lambda{|f, x|
73
+ mzero_method = x.respond_to?(:mzero?) ? :mzero? : :nil?
74
+ x.send(mzero_method) ? x : f.call(x)
75
+ }
76
+
77
+ # Lift this function to the given context-function.
78
+ # The lifted fucntion can compose other function with context-fucntion.
79
+ #
80
+ # The given context-fuction used by `compose_with_lifting`
81
+ # to compose other fucntion.
82
+ #
83
+ # The context-funciton should recieve 2 arguments.
84
+ # - first one is a function that reciver function of `compose_with_lifting` method.
85
+ # - second arg is a result of g(x)
86
+ # -- g is a function passed to `compose_with_lifting`
87
+ #
88
+ def lift(g = DEFAULT_CONTEXT)
89
+ @lambda_driver_liftable_context = g
90
+ self
91
+ end
92
+
93
+ def lambda_driver_liftable_context
94
+ @lambda_driver_liftable_context || DEFAULT_CONTEXT
27
95
  end
28
96
 
29
97
  def >=(g)
30
- g.to_proc <= self
98
+ g.to_proc.lift(lambda_driver_liftable_context) <= self
31
99
  end
32
100
 
33
101
  def self.included(klass)
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module LambdaDriver
3
- VERSION = "1.2.1"
3
+ VERSION = "1.2.2"
4
4
  end
@@ -17,28 +17,44 @@ shared_examples_for 'liftable' do
17
17
  end
18
18
  }
19
19
  }
20
+ let(:h) { lambda{|x| (x.to_s * 3) + "_h" } }
20
21
 
21
- it('" f >= g" returns function that does not call g if args is mzero'){
22
- (subject >= g).should be_a_kind_of Proc
23
- }
22
+ context 'lift on default-context' do
23
+ it('" f >= g" returns function that does not call g if args is mzero'){
24
+ (subject >= g).should be_a_kind_of Proc
25
+ }
24
26
 
25
- it('"(f >= g).call(nil) returns nil and does not call g'){
26
- (subject >= g).call(nil).should be_nil
27
- }
28
- it('"(f >= g).call(x) should be g(f(x))'){
29
- (subject >= g).call(x).should == g.call(subject.to_proc.call(x))
30
- }
31
- it('"(f >= g).call([]) returns [] and does not call g'){
32
- (subject >= g).call([]).should == []
33
- }
34
- it('"(f >= g).call([1,2]) should be g(f([1,2]))'){
35
- (subject >= g).call(y).should == g.call(subject.to_proc.call(y))
36
- }
37
- it('"(f >= g).call({}) returns {} and does not call g'){
38
- (subject >= g).call({}).should == {}
39
- }
40
- it('"(f >= g).call({:a => 1,:b => 2}) should be g(f({:a => 1, :b => 2}))'){
41
- (subject >= g).call(z).should == g.call(subject.to_proc.call(z))
42
- }
27
+ it('"(f >= g).call(nil) returns nil and does not call g'){
28
+ (subject >= g).call(nil).should be_nil
29
+ }
30
+ it('"(f >= g).call(x) should be g(f(x))'){
31
+ (subject >= g).call(x).should == g.call(subject.to_proc.call(x))
32
+ }
33
+ it('"(f >= g).call([]) returns [] and does not call g'){
34
+ (subject >= g).call([]).should == []
35
+ }
36
+ it('"(f >= g).call([1,2]) should be g(f([1,2]))'){
37
+ (subject >= g).call(y).should == g.call(subject.to_proc.call(y))
38
+ }
39
+ it('"(f >= g).call({}) returns {} and does not call g'){
40
+ (subject >= g).call({}).should == {}
41
+ }
42
+ it('"(f >= g).call({:a => 1,:b => 2}) should be g(f({:a => 1, :b => 2}))'){
43
+ (subject >= g).call(z).should == g.call(subject.to_proc.call(z))
44
+ }
45
+ end
43
46
 
47
+ context 'lift on given context' do
48
+ let(:ctx) { lambda{|f,x| f.call(x) + "_ctx_" }}
49
+
50
+ it(" f.lift(ctx) >= g returns funciton that compose with ctx"){
51
+ (subject.lift(ctx) >= g).should be_a_kind_of Proc
52
+ }
53
+ it('"(f.flit(ctx) >= g).call(x) should be ctx(g, f(x))'){
54
+ (subject.lift(ctx) >= g).call(x).should == ctx.call(g, subject.to_proc.call(x))
55
+ }
56
+ it('"(f.flit(ctx) >= g >= h).call(x) should be ctx(h, ctx(g, f(x)))'){
57
+ (subject.lift(ctx) >= g >= h).call(x).should == ctx.call(h, ctx.call(g, subject.to_proc.call(x)))
58
+ }
59
+ end
44
60
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lambda_driver
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-29 00:00:00.000000000 Z
12
+ date: 2014-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -87,12 +87,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
87
  - - ! '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
+ segments:
91
+ - 0
92
+ hash: -4555734478937324057
90
93
  required_rubygems_version: !ruby/object:Gem::Requirement
91
94
  none: false
92
95
  requirements:
93
96
  - - ! '>='
94
97
  - !ruby/object:Gem::Version
95
98
  version: '0'
99
+ segments:
100
+ - 0
101
+ hash: -4555734478937324057
96
102
  requirements: []
97
103
  rubyforge_project:
98
104
  rubygems_version: 1.8.23