I’m currently rewriting most of my JRuby/Java based machine learning toolbox, which I’m using for my research work, and stumbled upon a little Ruby “feature”: At least the way I see it, Ruby is a bit unbalanced with its scoping rules which make modules less useful as namespaces for organizing functions.
Every now and then, you will find that a certain functionality is best
exposed as a set of functions, instead of a set of objects. Even Java
has accepted this and provides the import static
directive since
1.5. For example, consider a module which provides all kinds of
mathematical special functions like Bessel
functions or the like.
The way Ruby supports module functions is through the
module_function
statement. For example,
Then you can both call it via MoreMath.bessel(a, x)
and also after
you have included it in your workspace, or your class, etc.
Now, interestingly (and probably also annoyingly), you don’t see the function from any class defined in the module:
On the other hand, constants are visible (as shown with the
CONSTANT
above). In order to make bessel
visible in SomeClass
,
you have to include the module in which the class is defined in the
class:
Okay, maybe there is something fundamental which I haven’t yet grasped about Ruby, but for me this feels just wrong. The whole point of lexical scoping is that you don’t have to be explicit about what scope is active, but you can see it from the nesting structure of the code. To me it also seems like lexical scoping has been hacked into Ruby for constants (because otherwise you couldn’t probably even see other classes defined in the same module, which would be even more painful), and someone just forgot module functions. I think part of the problem is that modules also double as mixins which doesn’t, well, mix well.
By the way, another “feature” is that module functions aren’t treated properly when you include a module in another. Including a module only works with the instance functions which means that you cannot invoke the function making the module explicit:
For me, the cleanest way out is to collect all modules in a sub-module
with a generic short name like Fcts
, then you can at least access
the functions without having to fully qualify the module (which works,
again because module names are constants, and the lexcial scoping
works for modules):
In summary, although I really like Ruby, I think the module scoping rules are broken as they are and using modules as namespaces for functions isn’t really working.
Posted by at 2009-10-07 11:55:00 +0000
blog comments powered by Disqus