Class: Linguistics::Verbs::Verbvector::VerbvectorGenerator
- Inherits:
-
Object
- Object
- Linguistics::Verbs::Verbvector::VerbvectorGenerator
- Defined in:
- lib/verbvector.rb
Overview
A class designed to generate a module that can be mixed in into a given type of verb (French, Latin, Spanish). I’m not trying to be obscure, but I’m trying to be very generalizable.
Instance Attribute Summary collapse
-
#aspect_list ⇒ Object
readonly
Returns the value of attribute aspect_list.
-
#cluster_methods ⇒ Object
readonly
Returns the value of attribute cluster_methods.
-
#language(*l, &b) ⇒ Object
readonly
Language takes a symbol for
l
the language whose verb we seek to model. -
#respondable_methods ⇒ Object
readonly
Returns the value of attribute respondable_methods.
-
#vector_list ⇒ Object
readonly
Returns the value of attribute vector_list.
Instance Method Summary collapse
-
#all_vectors(position, &b) ⇒ Object
Method generates tense vectors based on aspects that are assumed to apply to all possible vectors.
-
#cluster_on(match, junk, method_name) ⇒ Object
Method to allow “clusters” of simiar vectors to be identified (see:
match_upto
) based on the 0th string match. -
#combinatorialize(h) ⇒ Object
Method to take a hash key where the key is an aspect and the value is an array of specifications valid for that aspect.
-
#exception(action, id, &b) ⇒ Object
Languages are not entirely rational, while something ought exist by the rules of rational combination, some times they simply _don’t_ exist.
-
#initialize(&b) ⇒ VerbvectorGenerator
constructor
Initialization.
-
#match_vector_upto_aspect(s) ⇒ Object
Vectors are specified at their most atomic Sometimes it is handy to return all the values that match “up to” a given aspect and then uniq’ify them.
-
#method_extension_module ⇒ Object
Creates the anonymous module based on the contents of @vector_list.
-
#vectors_that(condition, &b) ⇒ Object
Method appends vector definitions if the
condition
(a RegEx) is satisfied.
Constructor Details
#initialize(&b) ⇒ VerbvectorGenerator
Initialization
Takes the descriptive block of the tense structure in a DSL format
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/verbvector.rb', line 22 def initialize(&b) @aspect_list = [] @vector_list = [] @respondable_methods = [] @cluster_methods = {} @language = "" # Let's remember the difference between instance_ and class_eval. # # "class_eval sets things up as if you were in the body of a class # definition, so method definitions will define instance methods:" # # "instance_eval on a class acts as if you were working inside the # singleton class of self. Therefore, any methods you define will # become class methods." - prog ruby 1.9 v3, prag programmers p.388 # # As such, instance_eval here is about to apply this eval to the # eigenclass. That means any instance of this class will have this # method. instance_eval(&b) @aspect_list.sort! end |
Instance Attribute Details
#aspect_list ⇒ Object (readonly)
Returns the value of attribute aspect_list.
16 17 18 |
# File 'lib/verbvector.rb', line 16 def aspect_list @aspect_list end |
#cluster_methods ⇒ Object (readonly)
Returns the value of attribute cluster_methods.
16 17 18 |
# File 'lib/verbvector.rb', line 16 def cluster_methods @cluster_methods end |
#language(*l, &b) ⇒ Object (readonly)
Language takes a symbol for l
the language whose verb we seek to model. It then takes a block for the sub-specification of the verbs of that language.
108 109 110 |
# File 'lib/verbvector.rb', line 108 def language @language end |
#respondable_methods ⇒ Object (readonly)
Returns the value of attribute respondable_methods.
16 17 18 |
# File 'lib/verbvector.rb', line 16 def respondable_methods @respondable_methods end |
#vector_list ⇒ Object (readonly)
Returns the value of attribute vector_list.
16 17 18 |
# File 'lib/verbvector.rb', line 16 def vector_list @vector_list end |
Instance Method Details
#all_vectors(position, &b) ⇒ Object
Method generates tense vectors based on aspects that are assumed to apply to all possible vectors. These would be seen as the most general aspects possible For example, while only some vectors are present tense, all vectors have a voice.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/verbvector.rb', line 119 def all_vectors(position,&b) # Make sure there is a block given return unless (block_given? or yield.first) # Sentinel condition for stopping recursive call return @vector_list unless yield.first # Provided that there was a block, collect the DSL hash into # specifications specifications = yield # Extract the first k/v specification = specifications.first # Based on the key for each row, take that content and postpend # it.to_s to the ending of each value held in the hash element value = combinatorialize(specification) # Remove the expanded value from the specifications hash specifications.delete(specification[0]) # Keep a record of aspects we have seen @aspect_list.push specification[0] @aspect_list.uniq! # If it's the first go round put the first set of values in. In # general these should be the leftmost and theremfore most general if @vector_list.empty? @vector_list = else # If there's already a definition in the tens list, for each of # the _existing_ values add the array of strings seen in # expanded_specifications thereunto. Hold them in 'temp' and then # set @vector_list to temp. temp = [] @vector_list.each do |base| .each do |u| temp.push base+"_#{u}" end end @vector_list = temp end # Recursive call, sentnel contition is at the top of the method all_vectors(position) do specifications end instance_eval(&b) end |
#cluster_on(match, junk, method_name) ⇒ Object
Method to allow “clusters” of simiar vectors to be identified (see: match_upto
) based on the 0th string match. These clusters can be called by the method namd provided as the 2nd argument (0-index)
This allows active_voice_indicative_mood_imperfect_tense_singular_number_third_p erson and other such to be ‘clustered’ as active_voice_indicative_mood_imperfect_tense. This means the actual method will probably be done in the “cluster” and some sort of secondary logic (method_missing) will do the final resolution
Nevertheless, per the logic of this library, by defining all the atomic, we play nice and give respond_to? all the information it needs
Example: cluster_on /active_voice.*third/, "as method", :active_thirds
This means you want to collect several method names that match the Regexp and make them identifiable by a call to the method active_thirds
Alternatively, you might want to use a String or Symbol (making use of match_upto).
Example: cluster_on :tense, "as method", :tense_list
match
-
The String or Regex match_upto will use for matching
junk
-
Syntactic sugar, a string that makes the DSL look sensible
method_name
-
The method in the anonymous module that returns the matched method names. See
create_module
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/verbvector.rb', line 256 def cluster_on(match, junk, method_name) clustered_matches = if match.class == Regexp @vector_list.grep match elsif match.class.to_s =~ /^(String|Symbol)/ # Get the items that match_upto the specified clustering token match_vector_upto_aspect(match.to_s) else # This shouldn't happen, we should get a Regexp or a String/Symbol raise "Didn't fire for clustered match: #{match}" end unless clustered_matches.nil? # No, this should not be done: # ...and add them to the @vector_list. # @vector_list += clustered_matches # Clustered methods need to be defined, for real, somewhere. We # should not claim to respond to them here, but rather let the # framework using verbvector have the responsibility for # implementation. # Now, define a Proc that can correspond to arg[2] @cluster_methods[method_name] = Proc.new do clustered_matches end end end |
#combinatorialize(h) ⇒ Object
Method to take a hash key where the key is an aspect and the value is an array of specifications valid for that aspect.
220 221 222 223 224 225 226 |
# File 'lib/verbvector.rb', line 220 def combinatorialize(h) results = [] h[1].each do |k| results.push "#{k}_#{h[0]}" end results end |
#exception(action, id, &b) ⇒ Object
Languages are not entirely rational, while something ought exist by the rules of rational combination, some times they simply _don’t_ exist. That’s what this method is for.
action
-
:remove
or:add
id
-
method name to remove
- block
-
used to add
211 212 213 214 215 216 |
# File 'lib/verbvector.rb', line 211 def exception(action, id, &b) if action == :remove @vector_list.delete_if {|x| x =~ /#{id.to_s}/ } elsif action == :add end end |
#match_vector_upto_aspect(s) ⇒ Object
Vectors are specified at their most atomic Sometimes it is handy to return all the values that match “up to” a given aspect and then uniq’ify them
50 51 52 53 54 |
# File 'lib/verbvector.rb', line 50 def match_vector_upto_aspect(s) @vector_list.compact.sort.grep(/#{s}/).map{ |x| x.sub(/(^.*#{s}).*/,%q(\1)) }.uniq end |
#method_extension_module ⇒ Object
Creates the anonymous module based on the contents of @vector_list. The method names in this module are just stubs except those that are loaded into the @cluster_methods hash. By generating all the method names we allow responds_to?
to work as expected.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/verbvector.rb', line 61 def method_extension_module v = @vector_list c = @cluster_methods l = @language r = @respondable_methods Module.new do # This defines instance methods on the Module # m.instance_methods #=> [:say_foo, :say_bar, :say_bat] # Note, you can't use @someArray in the iteration because # self has changed to this anonymous module. Since a block # is a binding, it has the local context (including 'v') # bundled up with it -- despte self having changed! # Therefore, the following works. # Define a method for each name in vector_list. raise("Language was not defined." ) if l.nil? v.each do |m| r << "#{m}" define_method "#{l.downcase}_#{m}".to_sym do end end # Write something to spit out the vectors as well. define_method :vector_list do return v end define_method :respondable_methods do return r end # Spit out the clustered methods c.each_pair do |k,val| define_method k do val.call end end end end |
#vectors_that(condition, &b) ⇒ Object
Method appends vector definitions if the condition
(a RegEx) is satisfied
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/verbvector.rb', line 171 def vectors_that(condition,&b) matching_stems = @vector_list.grep condition temp = [] specifications = yield # Extract the first k/v specification = specifications.first # Based on the key for each row, take that content and postpend # it.to_s to the ending of each value held in the hash element value = combinatorialize(specification) # Remove the expanded value from the specifications hash specifications.delete(specification[0]) # Keep a record of aspects we have seen @aspect_list.push specification[0] @aspect_list.uniq! # So we grepped the desired stems and stored them in matching_stems # First we delete those stems (becasue we're going to further specify) them matching_stems.each do |x| @vector_list.delete x .each do |u| temp.push x+"_#{u}" end end # Combine the original list with the freshly expanded list @vector_list = (@vector_list + temp).sort end |