On 25 October 2011 07:17, Joshua Ballanco <jballanc / gmail.com> wrote:
> On Monday, October 24, 2011 at 10:29 PM, Charles Oliver Nutter wrote:
>
> 2011/10/1 SASADA Koichi <ko1 / atdot.net>:
>
> - Remove Proc binding
>
> I added this one. Anyone who has ever attempted to optimize Ruby knows
> this is one of the biggest roadblocks. If any time, any local state
> can be seen by code you've passed a block to, you can't optimize any
> of that code in a way that would make it inaccessible.
>
> I'd also argue it breaks encapsulation in the same awful way that "retry"
> did:
>
> def foo
> password = get_password
> transaction do
> service.auth(password)
> service.do_something
> end
> end
>
> ...
>
> def transaction(&block) # my evil patch
> steal_password eval('password', block)
> end
>
> Any library that can patch "transaction" can see the "password" local.
> Shouldn't local variable encapsulation be sacred?
>
> Get rid of it.

No, thanks.

You need to pass variables into blocks.

Would you have to explicitly declare passed variables?

That's kind of non-ruby.

There are very few places where declarations are needed, and adding to
that would be sad.

While declarations have their place in programming the languages using
them aren't Ruby.

Yes, Java does, for sure.

>
> I've had an alternate idea to accomplish something like a compromise, but
> I'm still a ways away from having anything like a patch.
> The idea is this: make Proc#freeze snapshot all bindings.
> Essentially, telling a Proc to freeze would cause all bindings in the proc
> to be evaluated and replaced with their value at that moment. These values,
> themselves, would then be frozen, and references to the original code blocks
> could be released. Requiring an extra method call to accomplish this is
> slightly inconvenient, but it would keep Ruby 2.0 "backwards compatible" (in
> quotes because really? does anybody sensible actually abuse proc bindings
> like this?). The hope would be that eventually everyone would get into the
> habit of freezing their procs and eventually this could become the default
> behavior.

Maybe you could go a step further and make auto-freeze the default and
only add a switch to make the bindings non-frozen for compatibility if
somebody really needs that.

But I do abuse non-frozen bindings regularly.

When I need an accumulator for results that calculated inside a block
I declare a variable just before the method call that uses the block.

something like:

str = ""

some_stuff.do.something.that.gets.me.an.io{|io|
    begin
        loop do
            str << (io.readpartial READSIZE)
        end
    rescue EOFError
    end
}

Thanks

Michal