adt 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/adt.rb +24 -8
- metadata +2 -2
data/lib/adt.rb
CHANGED
@@ -29,7 +29,7 @@ module ADT
|
|
29
29
|
# end
|
30
30
|
# end
|
31
31
|
#
|
32
|
-
# This will
|
32
|
+
# This will provide 2 core pieces of functionality.
|
33
33
|
#
|
34
34
|
# 1. Constructors, as class methods, named the same as the case, and expecting
|
35
35
|
# parameters as per the symbol arguments provided in the `cases` block.
|
@@ -79,9 +79,9 @@ module ADT
|
|
79
79
|
dsl.__instance_eval(&definitions)
|
80
80
|
|
81
81
|
cases = dsl._church_cases
|
82
|
-
num_cases =
|
83
|
-
case_names =
|
84
|
-
is_enumeration =
|
82
|
+
num_cases = cases.length
|
83
|
+
case_names = cases.map { |x| x[0] }
|
84
|
+
is_enumeration = cases.all?{ |(_, args)| args.count == 0 }
|
85
85
|
|
86
86
|
# creates procs with a certain arg count. body should use #{prefix}N to access arguments. The result should be
|
87
87
|
# eval'ed at the call site
|
@@ -105,10 +105,13 @@ module ADT
|
|
105
105
|
end
|
106
106
|
|
107
107
|
# If we're inside a named class, then set up an alias to fold
|
108
|
-
|
108
|
+
fold_synonym = StringHelp.underscore(name.split('::').last)
|
109
|
+
if fold_synonym && fold_synonym.length > 0 then
|
110
|
+
define_method(fold_synonym) do |*args| fold(*args) end
|
111
|
+
end
|
109
112
|
|
110
113
|
# The Constructors
|
111
|
-
|
114
|
+
cases.each_with_index do |(name, case_args), index|
|
112
115
|
constructor = proc { |*args| self.new(&eval(proc_create[num_cases, "a", "a#{index+1}.call(*args)"])) }
|
113
116
|
if case_args.size > 0 then
|
114
117
|
singleton_class.send(:define_method, name, &constructor)
|
@@ -122,11 +125,24 @@ module ADT
|
|
122
125
|
end
|
123
126
|
end
|
124
127
|
|
128
|
+
# Getter methods for common accessors
|
129
|
+
all_arg_names = cases.map { |(_, args)| args }.flatten
|
130
|
+
all_arg_names.each do |arg|
|
131
|
+
case_positions = cases.map { |(_, args)| args.index(arg) && [args.index(arg), args.count] }
|
132
|
+
if case_positions.all?
|
133
|
+
define_method(arg) do
|
134
|
+
fold(*case_positions.map { |(position, count)|
|
135
|
+
eval(proc_create[count, "a", "a#{position+1}" ])
|
136
|
+
})
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
125
141
|
# Case info methods
|
126
142
|
# Indexing is 1-based
|
127
143
|
define_method(:case_index) do fold(*(1..case_names.length).to_a.map { |i| proc { i } }) end
|
128
144
|
define_method(:case_name) do fold(*case_names.map { |i| proc { i.to_s } }) end
|
129
|
-
define_method(:case_arity) do fold(*
|
145
|
+
define_method(:case_arity) do fold(*cases.map { |(_, args)| proc { args.count } }) end
|
130
146
|
|
131
147
|
# Enumerations are defined as classes with cases that don't take arguments. A number of useful
|
132
148
|
# functions can be defined for these.
|
@@ -141,7 +157,7 @@ module ADT
|
|
141
157
|
|
142
158
|
# The usual object helpers
|
143
159
|
define_method(:inspect) do
|
144
|
-
"#<" + self.class.name + fold(*
|
160
|
+
"#<" + self.class.name + fold(*cases.map { |(cn, case_args)|
|
145
161
|
index = 0
|
146
162
|
bit = case_args.map { |ca|
|
147
163
|
index += 1
|