I want a utility class that works like ipchains or iptables did... really just a table with each row containing a test, and an action to perform if the test is positive. the table is read from the top to the bottom, until either entropy reaches 0 or a rule requests immediately opting out. the thing is, I'm really not very used to ruby, and I'm having trouble in two places. The first is working with the tests. I need my test objects to work with assigned code blocks (methods, procs, I'm not sure anymore because of this problem). I've almost got it, but not quite. Here's an example that sums up the problem nicely, using an
Editor class that is a lot like the tests I need:
CODE
module Defaults
def in_place ( *string )
string = "look I edited it in place! (was #{string})"
end
end
class Editor
include Defaults
attr_accessor :edit_internal
def initialize ( variable_edit_method=in_place )
self.edit_internal = variable_edit_method
end
def edit ( *string )
ready_made_function = lambda {self.edit_internal}
ready_made_function.call( string )
end
end
# usage-space
yo = Editor.new
puts yo.edit( "cambiame" ) # produces: look I edited it in place! (was )
It produces the call and returns a result, only the result doesn't include the passed argument. So what happened to
string?
The second issue is assigning to an argument. — I need to increment and decrement the
entropy in my entropy chain, from within objects in the rows of the Chain instance (and when entropy reaches zero when processing a chain, opt out). I had found somewhere something about how this is possible using a bang symbol ( the "!" symbol), but I can't find that reference again and I forget the specifics. I might have just misunderstood what I was loking at, but it was something like one of these:
examples editedCODE
def in_place (value)
value! = value + 1
end
def in_place (value)
value = value + 1!
end
Whatever, it should accomplish something like this:
CODE
entropy = 1 #for example
entropy = Test( testable_value, entropy )
But instead with code like this:
CODE
entropy = 1
Test ( testable_value, entropy )
— for extensability and cleansliness it would be nice to skip the external assignment. How to go about that? That's my second question.
For the curious, here's a mockup of the class so far. It contains some pseudocode to get around the problems I've just described: <somevar>! is short for assignment to the argument variable in the calling context, and the Effect code is the pseudocode for working around references and executing code blocks dynamically. It doesn't include the most important code, even just iterating through itself.. right now it is just the structure. (Potato is an object to share between all the different rules that is just intended for extensibility, and to opt to terminate execution in the chain).
CODE
module ECDefaults
module Chain
FAILOUT="FAILOUT"
PASSOUT="PASSOUT"
end
module Row
end
module Rule
def match ( some_attribute )
some_attribute.value # match if the value itself evalutes true
end
end
module Effect
def null_effect ( entropy, potato ) # works on the EC entropy and potato
# null effect, entonces, do nothing
end
def add_entropy ( entropy, potato ) # increases the entropy state, making it harder to "pass" the chain
entropy = entropy + 1
entropy!
end
def decline_entropy ( entropy, potato ) # decreases the entropy state, including "passing" the chain if necessary
entropy = entropy - 1
entropy!
end
def pass_now ( entropy, potato )
potato.Meta["req_result"] = ECDefaults::Chain::passout
end
def fail_now ( entropy, potato )
potato.Meta["req_result"] = ECDefaults::Chain::failout
end
end
end
class EntropyChain<Object
include ECDefaults::Chain
attr_reader :typename
attr_accessor :entropy,
:rule_stack,
:hot_potato
def initialize ( *name, inc_rule_stack=Array.new, inc_entropy=1, potato=Object.new )
self.typename = name
self.stack = inc_rule_stack
self.entropy = inc_entropy
self.hot_potato = potato
end
# Scoped stuff
class Row<Hash
attr_reader :typename
attr_accessor :rule, :effect
def initialize ( *name, inc_rule, inc_effect )
self.typename = name
self.rule = inc_rule
self.effect = inc_effect
end
end
class Rule
# if ( Rule.validate( Some_attribute ) ) then the rule matches
# Some_attribute.value must exist by convention this is the value checked
include ECDefaults::Rule
attr_reader :typename
attr_accessor :validate_internal
def initialize ( *name, variable_validate_method=match )
self.typename = name
self.validate_internal = variable_validate_method
end
def validate ( *string )
ready_made_function = lambda {self.validate_internal}
ready_made_function.call( string )
end
end
class Effect
# if the rule matches, Effect.apply( EntrChain.entropy, EntrChain.potato )
# is called. it is passed the entropy and the potato for edit-in-place
# changes, and this is the primary result of an Effect
include ECDefaults::Rule
attr_reader :typename
attr_accessor :apply_internal
def initialize ( *name, variable_apply_method=in_place )
self.typename = name
self.apply_internal = variable_apply_method
end
def edit ( *string )
ready_made_function = lambda {self.apply_internal}
ready_made_function.call( string )
end
end
end
This post has been edited by robbiemuffin: 21 Aug, 2008 - 11:07 AM