lambda_driver 1.2.1 → 1.2.2
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/README.md +55 -8
- data/lib/lambda_driver/liftable.rb +75 -7
- data/lib/lambda_driver/version.rb +1 -1
- data/spec/shared/liftable.rb +37 -21
- metadata +8 -2
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
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
-
#
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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)
|
data/spec/shared/liftable.rb
CHANGED
@@ -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
|
-
|
22
|
-
(
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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.
|
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-
|
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
|