Module: Kernel
- Defined in:
- lib/anaphoric_case.rb
Instance Method Summary collapse
-
#aif(result = true) {|Object| ... } ⇒ Object, FalseClass
aif - anaphoric if.
-
#on(result = true) {|Object| ... } ⇒ Object
on.
-
#switch(object = nil) { ... } ⇒ Object, FalseClase
switch - anaphoric case construct.
Instance Method Details
#aif(result = true) {|Object| ... } ⇒ Object, FalseClass
aif - anaphoric if.
English is nice, in that if you want to make a conditional, you can say “if the dog is on fire, then put it out!” to say the equivalent thing in Ruby you say “if the dog is on fire, then put the dog out.” - which is fine, if something of a hassle sometimes. The “it” in the first example is an anaphor -
27 28 29 30 31 32 33 34 35 36 |
# File 'lib/anaphoric_case.rb', line 27 def aif result = true, &block if result unless block.nil? new_result = block.call(*[result].slice(0,block.arity)) return new_result end return result end false end |
#on(result = true) {|Object| ... } ⇒ Object
on
the on
method is available only in the #switch block - it basically functions exactly like the aif method.
The first on
method whose argument is truthy will execute it’s block and cause switch to return the value of the block.
146 |
# File 'lib/anaphoric_case.rb', line 146 def on result=true; super; end |
#switch(object = nil) { ... } ⇒ Object, FalseClase
switch - anaphoric case construct
this is basically a form of sugar over a whole list of || operators or or
statements This prevents you from either writing a difficult to read list of || operators, or having to construct lazily evaluated list of methods and parameters in order to do the cheapest thing.
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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/anaphoric_case.rb', line 66 def switch object = nil, &block AnaphoricCase.__nest += 1 raise ArgumentError, "switch requires a block" unless block_given? block = block.dup # enable cross thread sharing of blocks class << self def on result = true, &block # the current switch block in this thread it = AnaphoricCase.switch_stack.last.instance_eval { @it } # when the subsumption operator is used in these classes # it basically means "equal" so we ignore it these cases if (it and [Kernel, Fixnum, String, Bignum, Float, Symbol].include? result.method(:===).owner) result_simple = true end begin if it and (result === it or result == true) result = Kernel.aif it, &block throw :result, result if result elsif result and (not it or result_simple) result = Kernel.aif result, &block throw :result, result if result end rescue ArgumentError => e if e. =~ /throw :result/ raise NameError, "on without associated switch" else raise e end end false end end block.instance_eval do @it = object end AnaphoricCase.switch_stack << block res = catch :result do if block.arity > 0 self.instance_exec(object, &block) else self.instance_eval(&block) end end res ? res : false ensure AnaphoricCase.__nest -= 1 Thread.current[:__switch_stack].pop if object if AnaphoricCase.__nest == 0 class << self #you can get here without the on method being defined, #so rescue this silently if so. remove_method :on rescue nil end end end |