first is with…yield trying to achieve the same thing as ruby’s instance_eval? since crystal doesn’t have instance_eval ,
then
class Person
def foo
puts "person foo"
end
end
def foo
puts "foo"
end
def some_proc(&block : Int32 -> _)
with Person.new yield 15
end
some_proc do
foo
break
end
outputs foo
while removing type declaration.
def some_proc(&block)
with Person.new yield 15
end
outputs person foo
so the only difference here is type declaration,
which is quite confusing to me,
whether the block is captured or not(under both 2 circumstances),
I deliberate add break in block since the docs says captured doesn’t support break.
Yeah, it’s basically a subset of instance_exec’s functionality.
This sounds like a bug. Here is a more concise reproduction of it:
class Person
def foo
puts "foo"
end
end
def some_proc(& : Int32 ->)
with Person.new yield 15
end
some_proc { foo }
It doesn’t compile, but if you change it to def some_proc, it compiles and runs as expected. I have a feeling that it’s because when you use yield, you don’t need to provide a type declaration for the block (it’s inferred from the yield) and usage with the type declaration in place never ended up being tested.
I think you just need to remove the 15 and do an empty yield, without the typed block mentioned previously. When using with ... yield you’re not supposed to give a value after the yield. Otherwise I’m pretty sure it just drops the with Person.new and yields 15. If that is in fact true, maybe some error could be raised pointing that out.
Just use yield is a non-captured block, a non-captured block is always inlined, no performance pency!
I guess, as describe by above, when use yield ???, there is no block actually, so any (& : Type → Type) will be ignored. but when yield use with with ??? yield separately, the inline invalid apparently, use &block, in this case, when you specify & : Int32 ->, will assume yield a number into block instead of yield self.