Name: Xavier Noria
Member since: 2001-06-15 10:41:45
Last Login: 2010-01-31 18:03:16
Homepage: http://www.hashref.com
Notes:
About me
Everlasting student. Interested in X for all X.
Feel free to contact me at `echo -n ska@unfuers.pbz | tr a-z n-za-m`.
Certification
30 Jan 2010 (updated 30 Jan 2010 at 18:23 UTC) »
Tracking Class Descendants in Ruby (II)
My previous post explains a way to keep track of a class' descendants, and encapsulates the technique into a module.
There are two things you may want to do different: Since all descendants inherit the descendants class method you may prefer them to be functional. On the other hand, the module defines the inherited class method into the base class because it needs it to be a closure. That may work for some particular need, but it is not good for a generic solution. The inherited hook is the business of your client's code.
Now we'll see a different approach that addresses both concerns. Using the same hook any class in the hierarchy may easily keep track of its direct subclasses, and compute its descendants:
class C
def self.inherited(subclass)
subclasses << subclass
end
def self.subclasses
@subclasses ||= []
end
def self.descendants
subclasses + subclasses.map(&:descendants).flatten
end
end
In the previous solution the inherited hook needed to ensure descendants was invoked on the root of the hierarchy. In this solution it doesn't care because we precisely take advantage of polymorphism. The way it is written a class pushes into its own @subclasses instance variable, which is what we want.
The module that encapsulates that pattern is much simpler:
module DescendantsTracker
def inherited(subclass)
subclasses << subclass
super
end
def subclasses
@subclasses ||= []
end
def descendants
subclasses + subclasses.map(&:descendants).flatten
end
end
class C
extend DescendantsTracker
end
You know extend is like doing an include in the metaclass of C. In particular we are not defining C.inherited, we are defining a method with the same name in an ancestor of the metaclass. That way C can still define its own inherited class method. A call to super within such a C.inherited will go up the next ancestor of the metaclass, eventually reaching the inherited from DescendantsTracker.
29 Jan 2010 (updated 30 Jan 2010 at 18:25 UTC) »
Tracking Class Descendants in Ruby
I am going through all Active Support core extensions lately because I am writing the Active Support Core Extensions guide, due for Rails 3. There are some patches in master as a result of that walkthrough, and I am now focusing on keeping track of descendants in a class hierarchy.
A known technique uses ObjectSpace.each_object. That is a method that receives a class or module as argument and yields all objects that have that class or module among their parents. Since classes are instances of the class Class, you can select descendants of class C this way:
descendants_of_C = []
ObjectSpace.each_object(Class) do |klass|
descendants_of_C << klass if klass < C
end
That is a brute force approach, it works, but it is inefficient. JRuby even disables ObjectSpace by default for performance reasons.
A better approach is to leverage the inherited hook. Classes may optionally implement a class method inherited that is called whenever they are subclassed. The subclass is passed as argument:
class User
def self.inherited(subclass)
puts 0
end
end
class Admin < User
puts 1
end
# output is
0
1
That's a perfect place to keep track of descendants:
class C
class << self
def inherited(subclass)
C.descendants << subclass
super
end
def descendants
@descendants ||= []
end
end
end
In that code we have an array of descendants in @descendants. That is an instance variable of the very class C. Remember classes are ordinary objects in Ruby and so they may have instance variables. It is better to use an instance variable instead of a class variable because class variables are shared among the entire hierarchy of the class and we need an exclusive array.
Another fine point is that we force descendants to be the one in the C class. If we didn't and we had A < B < C, the hook would be called when A was defined, but by polymorphism it would be B.descendants what would be called, thus setting B's instance variable @descendants. That is not what we want.
The call to super is just a best practice. In general a hook like this should pass the call up the hierarchy in case parents have their own hooks.
That pattern can be implemented in a module for reuse indeed:
module DescendantsTracker
def self.included(base)
(class << base; self; end).class_eval do
define_method(:inherited) do |subclass|
base.descendants << subclass
super
end
end
base.extend self
end
def descendants
@descendants ||= []
end
end
class C
include DescendantsTracker
end
A class only needs to include DescendantsTracker to track its descendants.
When the module is included in a class Ruby invokes its inherited hook. The hook receives the class that is including the module, and we leverage that to inject the class methods we saw before. For inherited we open the metaclass of base and define the method in a way that has base in scope, which is something we saw before we need. After that we add the descendants class method with an ordinary extend call.
Update: There's a followup to this post.
3 Jan 2010 (updated 3 Jan 2010 at 20:13 UTC) »
Rails Tip: Avoid mixing require and Rails autoloading
I've seen in a few Rails applications warnings about constants being redefined at some point. Problem was always the same: a file was autoloaded and required afterwards, and this results in the file being interpreted twice. If the class or module defines ordinary constants you may be lucky and see a warning, but if not you may not even be aware of it. Let me explain why this happens.
For example, given:
# lib/utils.rb
module Utils
X = 1
end
If we autoload the module and then require the file:
$ script/runner 'Utils; require "utils"'
a warning is issued:
warning: already initialized constant X
This is an artificial example, but in practice it may be the case for instance that some initializer autoloads Utils and later a model requires lib/utils.rb. Of course you don't need and shouldn't do that, but perhaps the model was written by someone not conversant in Rails or whatever.
OK, the warning is telling us lib/utils.rb is being interpreted twice. That happens both in development and production modes, but for different reasons.
In development mode Rails autoloading uses Kernel#load by default to be able to reinterpret code per request. So, the usage of the constant Utils triggers the interpretation of lib/utils.rb with load, and since require knows nothing about that file it happily interprets its content again.
In production mode Rails autoloading uses require, and that is supposed to run the file once, what's the matter?
When require loads something, it stores its path in the array $":
$ ruby -rdate -e 'puts $"' enumerator.so rational.rb date/format.rb date.rb
require checks that array to see whether a given file was already loaded before it attempts to go for it. If it was there's nothing to do and just returns (false). The point is that require does not detect whether two different paths point to the same file, and Rails autoloading passes absolute pathnames to autodiscovered source files:
$ script/runner -e production 'Utils; require "utils"; puts $"' ... /Users/fxn/tmp/test_require/lib/utils.rb utils.rb
Since they do not match, the file is again loaded twice.
The solution to this gotcha is as simple as removing the call to require. An idiomatic Rails application names its files after the classes or modules they define and delegate their loading to the dependencies mechanism. Generally, the only calls to require load external libraries.
19 Dec 2009 (updated 20 Dec 2009 at 11:40 UTC) »
Kinesis Advantage Pro
My family of somewhat special keyboards includes a IBM Model M, a couple of Happy Hackings, a Unicomp Customizer and now Santa came with a Kinesis Advantage Pro.
This is the less conventional of them as you can see in this set of photos I took while unpacking it. Besides the design itself, it supports macros, you can remap keys, have Mac and PC layouts (hot-switchable), builtin support for QWERTY and DVORAK (you can choose any with a key combo), and support for foot switches. In addition to emit a beautiful minimal beep-beep sound I love done by software to add feedback. Everything operated from the very keyboard, no additional software distributed. The computer only sees an ordinary USB keyboard.
I've known personally two seasoned programmers that have only used them for years, having owned several units, and do not want to use anything else. I think I understand them. Typing with this keyboard feels really good. Your arms are relaxed and your hands, fingers, and wrists work with little stress compared with standard desigs. This is not only an investment for your health, I think the typing experience is hands down better, something very important if you like me spend hours and hours day after day typing.
That's mainly because of three characteristics: First, as you can observe in the pictures keys are aligned in columns, instead of being staggered. So, your fingers move mostly in straight lines. Second, hands are more quiet thanks to the convex shape, the curve matches naturally your fingers reach. Third, the space bar, backspace, return key, commad, option, and a few more keys are pressed with your thumbs.
I've been using the Kinesis non-stop since Tuesday. I think you need to do an immersion to get used to it and don't want to use any other keyboard at least until I finish the adaptation period. The box includes a booklet with exercises designed to ease the transition. It is not a touch typing course, they are designed to help you to adapt. I was not a touch typist so it is taking me a while to get a decent speed, though as of today it is already quite acceptable.
The Pro model comes with a foot switch. That is a switch you can map to any key. I have it mapped to Shift but I am unconvinced by now. Problem is that even if the pedal is built in a way that prevents quite well accidental presses, I can't for the life of me train myself to relax my foot on it for a long time period. So I have some tension which is not good. I'll try a little more before giving up though.
Keyboard shortcuts is something you need to retrain completely because your current muscle memory is useless here, since involved keys are in different spots.
That's pretty normal, it is known that you need a few weeks to get at full speed and have your brain rewired, but I believe from my experience so far it is going to be worth the effort.
25 Oct 2009 (updated 26 Oct 2009 at 11:00 UTC) »
Emulating Ruby Blocks in Perl
Ruby Blocks
Ruby blocks allow you to run code in the caller from within a method:
# definition
def twice
yield 1
yield 2
end
# example call
twice do |n|
puts "croak! (#{n})"
end
# output
# croak! (1)
# croak! (2)
In case you never saw something like that before, twice expects to be called with a block. That's the code between the do ... end keywords in the example call. Each call to yield runs the block in the caller. Arguments may be passed, in the example we pass a integer.
This is a powerful tool, Ruby is full of all sorts of internal iterators thanks to it:
array.each_with_index do |item, i|
# ...
end
You can wrap/decorate chunks of code with them providing a very easy and intuitive usage. For example:
File.open(filename) do |file|
# ...
end
opens a file, passes the filehandle to the block, and when the block is done it closes it.
Another example from my Rails Contributors application (simplified here):
acquiring_sync_file do
# ...
end
The code within the block runs only if acquiring_sync_file could get a lock on some given sync file. If it could, once the block is done the lock is released.
Ruby Blocks in Perl
Perl does not have blocks like that, but you can emulate them in a way that may cover some use cases:
acquiring_sync_file {
# ...
};
The trick comes from a feature of Perl that is not widely used: subroutine prototypes.
You may have noticed that some builtin Perl subroutines behave in a strange way. For example push:
push @array, 5;
If push was an ordinary subroutine, it would receive the elements of @array and a 5 in @_, with no possible way to modify @array, which was lost by its evaluation in list context before the function call.
But push somehow is able to tell @array from the 5, and actually modify it. There's something special going on there. You can write you own subroutines like push and other thanks to subroutine prototypes. They are documented in perlsub.
Point is: if the first argument of a call is an anonymous subroutine, Perl forgives you the sub keyword if you set an appropriate prototype:
sub twice(&) {
my $coderef = shift;
$coderef->(1);
$coderef->(2);
}
# as if it said twice sub { ... }
twice {
my $i = shift;
print "croak! ($i)\n";
};
The rationale for that is to give you a way to write your own subroutines with map-like syntax. As you see, we can pass arguments as well.
Opening a file with automatic close would be:
sub xopen(&@) { ... }
xopen {
my $fh = shift;
# ...
} $mode, $filename;
As you see xopen arguments would go after the anonymous subroutine, because this trick is only allowed if the coderef is the very first argument.
Drawbacks
The whole range of subroutine prototypes have a few gotchas, but what's specifically needed here works fine and some Ruby idioms can be emulated quite well. Subroutine prototypes do not work at all in methods though.
rubyisms
Simon Cozens' rubyisms Perl module provides a hackish yield so that you do not need to execute coderefs explicitly.
fxn certified others as follows:
Others have certified fxn as follows:
[ Certification disabled because you're not logged in. ]
FOAF updates: Trust rankings are now exported, making the data available to other users and websites. An external FOAF URI has been added, allowing users to link to an additional FOAF file.
Keep up with the latest Advogato features by reading the Advogato status blog.
If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!