[#31647] [Backport #3666] Backport of r26311 (Bug #2587) — Luis Lavena <redmine@...>

Backport #3666: Backport of r26311 (Bug #2587)

13 messages 2010/08/07

[#31666] [Bug #3677] unable to run certain gem binaries' in windows 7 — Roger Pack <redmine@...>

Bug #3677: unable to run certain gem binaries' in windows 7

10 messages 2010/08/10

[#31676] [Backport #3680] Splatting calls to_ary instead of to_a in some cases — Tomas Matousek <redmine@...>

Backport #3680: Splatting calls to_ary instead of to_a in some cases

10 messages 2010/08/11

[#31681] [Bug #3683] getgrnam on computer with NIS group (+)? — Rocky Bernstein <redmine@...>

Bug #3683: getgrnam on computer with NIS group (+)?

13 messages 2010/08/11

[#31843] Garbage Collection Question — Asher <asher@...>

This question is no doubt a function of my own lack of understanding, but I think that asking it will at least help some other folks see what's going on with the internals during garbage collection.

17 messages 2010/08/25
[#31861] Re: Garbage Collection Question — Roger Pack <rogerdpack2@...> 2010/08/26

> The question in short: when an object goes out of scope and has no

[#31862] Re: Garbage Collection Question — Asher <asher@...> 2010/08/26

Right - so how does a pointer ever get off the stack?

[#31873] Re: Garbage Collection Question — Kurt Stephens <ks@...> 2010/08/27

On 8/26/10 11:51 AM, Asher wrote:

[#31894] Re: Garbage Collection Question — Asher <asher@...> 2010/08/27

I very much appreciate the response, and this is helpful in describing the narrative, but it's still a few steps behind my question - but it may very well have clarified some points that help us get there.

[#31896] Re: Garbage Collection Question — Evan Phoenix <evan@...> 2010/08/27

You have introduced something called a "root node" without defining it. What do you mean by this?

[#31885] Avoiding $LOAD_PATH pollution — Eric Hodel <drbrain@...7.net>

Last year Nobu asked me to propose an API for adding an object to

21 messages 2010/08/27

[#31947] not use system for default encoding — Roger Pack <rogerdpack2@...>

It strikes me as a bit "scary" to use system locale settings to

19 messages 2010/08/30

[#31971] Change Ruby's License to BSDL + Ruby's dual license — "NARUSE, Yui" <naruse@...>

Ruby's License will change to BSDL + Ruby's dual license

16 messages 2010/08/31

[ruby-core:31929] Proposal: Autoload with block

From: Magnus Holm <judofyr@...>
Date: 2010-08-29 15:06:27 UTC
List: ruby-core #31929
= A proposal for autoload w/block:

== autoload(:Constant, &blk)
== autoload(&blk)

When Constant is accessed, the following happens:

1. The block is called with the constant name as a parameter and the scope
   where it's looking for the constant as self:

   scope.instance_exec(:Constant, &blk)

2. If the block raises an error, the error isn't rescued

3. If the block raises a specific error or throws something specific,
   it signals that the constant is missing unless it has been set earlier
   in the block:

3a. It checks if the constant is defined now
3b. If not, the constant doesn't exists and it'll continue searching for
    the constant in the constant chain.

4. If the block succeeds:
4a. It sets the constant to result of the block

If you don't specify a constant name to autoload, it will catch all
missing constants, but otherwise it works exactly the same as above.

There should also be a way to specify an autoload which triggers on all
scopes. So with the given code:

  # Not sure about how we should specify it though:
  autoload(true) do
    throw :stop
  end

  module Foo::Bar
    p Hello
  end

It will run the autoload block with respectivly Foo::Bar and Object as
scope (as opposed to Foo::Bar, Foo and Object which it'll search through
if you hack it up with const_missing).

There are basically two scenarios which this API covers:

- Easily use autoload without using #const_set:

  autoload(:C) { generate_C }

- Run code which might set the constant:

  autoload(:C) { set_C; throw :stop }

- The two scenarios above with an unspecified constant name.

None of these changes previous behaviour and you can also create a Ruby
monkey-patch which sort-of works similar through #const_missing (which you
can use where this proposal isn't implemented).

= Example of uses
== Camping

In Camping (http://whywentcamping.com) we use autoload to load optional
features which requires dependencies. Example:

  # in camping.rb
  module Camping
    autoload :Template, "camping/template"
  end

  # in camping/template.rb
  require 'tilt'
  module Camping
    Template = Tilt
  end

With the proposed changes to autoload, this could be written as:

  # in camping.rb
  module Camping
    autoload(:Template) { require 'tilt'; Tilt }
  end

Which is way easier to maintain and understand for everyone.

=== Rails

Rails overwrites const_missing in order to automagically load files
(from different locations) when a constant is accessed. Example of how
this could be implemented with the proposed autoload:

  autoload do |constant|
    # Convert FooBar to foo_bar.rb
    file = constant.to_s.underscore + '.rb'
    # Search through the list of directores:
    Rails.autoload_paths.each do |dir|
      full_path = File.join(dir, file)
      # Load the file and stop searching:
      File.exists?(full_path) && load(full_path) && break
    end

    throw :stop
  end

This is also more correct than Rails' version, which can't use the proper
cref because it uses const_missing:

  module Foo::Bar
    p Hello
  end

Rails will search through Foo::Bar, Foo and Object instead of Foo::Bar and
Object. This is really impossible to properly implement with
const_missing, but is doable with autoload with blocks.

=== Implementing regular autoload in Ruby

Just to show that this implementation is the general case of autoloading,
implementing regular autoloading is really simple with this API:

  autoload(:Constant) { load(file); throw :stop }

= Thoughts?

What are your thoughts on:

- A more general autoload solution?
- This proposal?
- Other ways to solve this "problem"?

// Magnus Holm

In This Thread

Prev Next