I am trying to create a DSL with operator methods. However, in a “with self yield” block, the operators don’t work.
Given following code:
class Adder
getter ns : Array(Int32) = [] of Int32
def add=(n : Int32)
ns.push n
end
def min(n : Int32)
ns.push (-1 * n)
end
def calc(&)
with self yield
end
end
adder = Adder.new
puts adder.ns
adder.add = 1
puts adder.ns
adder.calc do
add = 2
end
puts adder.ns
adder.min(3)
puts adder.ns
adder.calc do
min(4)
end
puts adder.ns
I get output
[1]
[1]
[1, -3]
[1, -3, -4]
But I expected
[1]
[1, 2]
[1, 2, -3]
[1, 2, -3, -4]
Is it possible to use operator methods in a “with self yield” block?
Think the problem here is add = 2 is ambiguous, so the compiler is assuming it’s a local variable assignment. If you want it to call the setter, you can do itself.add = 2. Tho really a more practical solution would be to use a more idiomatic method name, like def <<(n : Int32) and/or push to make it more clear and not involve assignment so compiler will know what to do.
The “add” and “minus” was just an example. In my DSL, I’ve got a lot of configuration options that can be set by assignment operator. The idea is to set options that can occur only once by assignment (=), and options that can occur multiple times by <<.
I’ll see if there’s another operator I can use instead of = for options I can set once.