Yield with self does not work when calling operator methods

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.

Thanks for your quick answer!

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.