pattern-proc 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 570c658ac139da0ade4f67576ec391963253c432
4
+ data.tar.gz: c59c291c8cc567c685fe42c907c79eecee31f985
5
+ SHA512:
6
+ metadata.gz: f767b258e7adb44cc7c114dcc5f139dc560ea1554fc60cdc2d3eb1f9bc8dba25e1069b0601071df0ce7b0c7b3e21ebb4a809728a03f8106058e61066062f0369
7
+ data.tar.gz: fab0de65a0e2215f50119a4bae8883b8c4ff14f97392a8af839066314c18e3a1eb5a492aa68b1880fe5ab01ce44e3ec6d2bbd667bb6b391fe71bbec279003225
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 William Pleasant-Ryan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ pattern-proc
2
+ ============
3
+
4
+ pattern matching Proc definitions
@@ -0,0 +1,146 @@
1
+ class PatternProc
2
+
3
+ def initialize(cases = [])
4
+ @arity = -1
5
+ @cases = []
6
+ cases.each do |c| add_case c end
7
+ end
8
+
9
+ def with(*args, &block)
10
+ case_obj = PatternProcCase.new(args, &block)
11
+ add_case case_obj
12
+ case_obj
13
+ end
14
+
15
+ def to_proc
16
+ ->(*args) { call(args) }
17
+ end
18
+
19
+ private
20
+ def add_case(case_obj)
21
+ if @arity == -1
22
+ @arity = case_obj.arity
23
+ elsif @arity != case_obj.arity
24
+ raise "mismatched arity"
25
+ end
26
+ @cases << case_obj
27
+ end
28
+
29
+
30
+ def call(args)
31
+ if args.size == @arity
32
+ best_match = find_matches(args, true).first
33
+ if best_match
34
+ best_match.to_proc.call(args)
35
+ else
36
+ raise "no match"
37
+ end
38
+ elsif args.size < @arity
39
+ sliced_cases = find_matches(args, false)
40
+ if sliced_cases.size > 0
41
+ PatternProc.new(sliced_cases).to_proc
42
+ else
43
+ raise "no match"
44
+ end
45
+ else
46
+ raise "too many args"
47
+ end
48
+ end
49
+
50
+ def find_matches(args, stop_at_first_match)
51
+ results = []
52
+ sorted_cases = @cases.sort do |case_obj_1, case_obj_2|
53
+ case_obj_1.specificity <=> case_obj_2.specificity
54
+ end.reverse
55
+ sorted_cases.each do |case_obj|
56
+ result = case_obj.make_subcase(args)
57
+ if result
58
+ results << result
59
+ if stop_at_first_match
60
+ break
61
+ end
62
+ end
63
+ end
64
+ results
65
+ end
66
+ end
67
+
68
+ class PatternProcCase
69
+
70
+ attr_reader :proc_applied_level
71
+ attr_reader :proc_arity
72
+
73
+ def initialize(args, previous_specificity = 0, proc_arity = 0, &block)
74
+ @expected_args = args
75
+ @proc = block
76
+ @proc_arity = proc_arity
77
+ @previous_specificity = previous_specificity || 0
78
+ if block.present? && block.arity > 0
79
+ @proc_arity = block.arity
80
+ end
81
+ end
82
+
83
+ def returns(value)
84
+ @return_value = value
85
+ self
86
+ end
87
+
88
+ # private ish
89
+ def expected_arity
90
+ @expected_args.size || 0
91
+ end
92
+
93
+ def arity
94
+ expected_arity + proc_arity
95
+ end
96
+
97
+ def specificity
98
+ expected_arity + @previous_specificity
99
+ end
100
+
101
+ def make_subcase(args)
102
+ match_len = [args.size, @expected_args.size].min
103
+ expected = @expected_args.take(match_len)
104
+ actual = args.take(match_len)
105
+ if expected == actual
106
+ new_proc = to_proc.curry
107
+ curry_count = args.size - @expected_args.size
108
+ new_arity = proc_arity
109
+ if curry_count > 0
110
+ send_args = args.drop(match_len).take(curry_count)
111
+ new_proc = new_proc.call(*send_args)
112
+ new_arity -= curry_count
113
+ if new_arity == 0
114
+ return PatternProcCase.new([], specificity).returns(new_proc)
115
+ elsif !(new_proc.is_a?(Proc))
116
+ raise "uh oh"
117
+ end
118
+ end
119
+ PatternProcCase.new(@expected_args.drop(match_len), specificity, new_arity, &new_proc).returns(@return_value)
120
+ else
121
+ nil
122
+ end
123
+ end
124
+
125
+ def to_proc
126
+ @proc || ->(*args) { @return_value }
127
+ end
128
+ end
129
+
130
+ class Object
131
+ def partials(method)
132
+ @__partials ||= {}
133
+ unless @__partials[method]
134
+ proc_obj = ComposableProc.new
135
+ metaclass = class << self; self; end
136
+ metaclass.class_eval do
137
+ define_method(method) do |*args|
138
+ curried_method = proc_obj.to_proc.curry
139
+ curried_method[*args]
140
+ end
141
+ end
142
+ @__partials[method] = proc_obj
143
+ end
144
+ @__partials[method]
145
+ end
146
+ end
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'pattern-proc'
3
+ s.version = '0.0.1'
4
+ s.date = '2014-07-01'
5
+ s.summary = 'Pattern Proc'
6
+ s.description = 'define a Proc with pattern matching "re-declaration" ala Haskell'
7
+ s.authors = ['William Pleasant-Ryan']
8
+ s.email = ['krelian18@gmail.com']
9
+ s.files = `git ls-files`.split("\n")
10
+ s.files.delete(".gitignore")
11
+ s.homepage = "http://rubygems.org/gems/pattern-proc"
12
+ s.license = "MIT"
13
+ end
14
+
@@ -0,0 +1,54 @@
1
+ describe PatternProc do
2
+ subject { described_class.new }
3
+
4
+ it "simple" do
5
+ subject.with(3,4).returns(12)
6
+
7
+ prc = subject.to_proc
8
+ prc.(3,4).should == 12
9
+ prc.(3).(4).should == 12
10
+ end
11
+
12
+ it "works" do
13
+ subject.with(3,1,2).returns(12)
14
+ subject.with(4,4,1).returns(10)
15
+ subject.with(7,7,7).returns(777)
16
+ subject.with(7,7) do |l_arg|
17
+ 140 + l_arg
18
+ end
19
+ subject.with(7,3,4).returns(11)
20
+ subject.with(2) do |x, y| 2 * x * y end
21
+ subject.with do |x, y, z|
22
+ x * (y + z)
23
+ end
24
+
25
+ prc = subject.to_proc
26
+
27
+ prc.(3,1,2).should == 12
28
+ prc.(3).(1,2).should == 12
29
+ prc.(3).(1).(2).should == 12
30
+ prc.(3,1).(2).should == 12
31
+
32
+ prc.(4,4,1).should == 10
33
+ prc.(4,4,2).should == 24
34
+ prc.(4,4).(2).should == 24
35
+ prc.(4).(4,2).should == 24
36
+
37
+ prc.(7,7,7).should == 777
38
+ prc.(7).(7).(7).should == 777
39
+ prc.(7).(7,7).should == 777
40
+
41
+ prc.(7,7,3).should == 143
42
+ prc.(7).(7,3).should == 143
43
+ prc.(7,7).(3).should == 143
44
+ prc.(7).(7).(3).should == 143
45
+
46
+ prc.(2,1,1).should == 2
47
+ prc.(2,3).(8).should == 48
48
+
49
+ prc.(5,6,7).should == 65
50
+ prc.(5).(6,7).should == 65
51
+ prc.(5).(6).(7).should == 65
52
+ prc.(5,6).(7).should == 65
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pattern-proc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - William Pleasant-Ryan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: define a Proc with pattern matching "re-declaration" ala Haskell
14
+ email:
15
+ - krelian18@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - LICENSE
21
+ - README.md
22
+ - lib/pattern_proc.rb
23
+ - pattern-proc.gemspec
24
+ - spec/pattern_proc_spec.rb
25
+ homepage: http://rubygems.org/gems/pattern-proc
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 2.2.2
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Pattern Proc
49
+ test_files: []