The weirdest code I've seen recently
I was kicking around in ActiveResource::Base recently and it took me a good solid ten minutes to figure out why the prefix method didn’t recur infinitely.
def prefix(options={})
default = site.path
default << '/' unless default[-1..-1] == '/'
# generate the actual method based on the current site path
self.prefix = default
prefix(options)
end
def prefix_source
prefix # generate #prefix and #prefix_source methods first
prefix_source
end
def prefix=(value = '/')
# Replace :placeholders with '#{embedded options[:lookups]}'
prefix_call = value.gsub(/:\w+/) { |key| "\#{options[#{key}]}" }
# Redefine the new methods.
code = <<-end_code
def prefix_source() "#{value}" end
def prefix(options={}) "#{prefix_call}" end
end_code
silence_warnings { instance_eval code, FILE, LINE }
rescue
logger.error "Couldn't set prefix: #{$!}\n #{code}"
raise
end
Do you see it? When prefix is called, it calls prefix=, which redefines prefix and returns. prefix in turn returns by calling not itself but the newly-created method of the same name.
I am not known for my low tolerance of metalanguage hackery (exhibit). But I do have my limits, and this exceeds them; calling it needlessly obfuscatory would be kind. Or am I wrong? Is there no better way to provide a method with the same semantics?
GitHub, briefly
I know that I’m late to the party here, that all of the cool kids have had accounts for what seems like Internet-decades, and that I can do nothing but add my voice belatedly to an already rapturous chorus; nevertheless, forgive my enthusiasm: GitHub rules, it is worth joining, and, once signed up, it took only a week for my workflow to be forever improved. I am, in short, a believer.
- It’s never been easier or more convenient to contribute to other open source projects.
- It’s never been easier to work remotely.
- It’s never been easier to track the progress of projects and developers you’re interested in.
- Unicorns! Rainbows! Puppies!
Over the next few weeks I’ll gradually be migrating all of my projects over to it, and I encourage you to do the same.
Posted in Professional | no comments |
Marketing Ruby
Scheme, a variant of Lisp popular in academic settings, has no download link on its extremely minimalist home page. If you click Implementations, it will list about fifty and recommend about ten. Visit the Ruby homepage and you are presented with a modern, polished, attractive site and a large, friendly Download Ruby link.
Marketing isn’t always about advertising. If you believe in a product, present it to the world in a way that makes it easy for others to believe in. It’s easy to be cynical about appearances, but they are, here and now as they have ever been, important. This principle is extended deeply into the Ruby language itself. From a technical standpoint, Ruby does very little that other languages don’t, but the metaprogramming hooks it makes available to users are straightforward and user-friendly and make its users feel immediately powerful. The elaborate contortions (do watch the presentation if you can, it’s awesome) that the language itself must go through in order to provide a convenient interface to the user doesn’t detract from the net result. Simplexity sells.
Ruby and, now, Rails have been around for long enough that it seems, at least to me, that most people who were ever going to have an opinion on it now do so. But accusations of hype are and always have been overblown; I would go so far as to call that particular brand of cynicism a kind of intellectual laziness convenient to those don’t understand a phenomenon and don’t particularly want to. Regardless of whether or not Ruby and/or Rails are here to stay (and I think they are, but then, I’m an optimist), it would be foolish to ignore the lessons here.
Posted in Professional | no comments |
Six Months with NetBeans on Rails: A Retrospective
I’m at RailsConf this weekend, capping a six-months engagement delivering a couple of Rails apps written using NetBeans as our team’s primary Ruby editor. We ended up with it because the client requested that we do our all development work in Ubuntu 6.06, and because we couldn’t build a consensus around a more lightweight editor like Vim or jEdit. I thought I’d share some of my thoughts on it for anyone’s who’s interested in switching.
Executive Summary
There’s a lot to love and a fair amount to hate, but it’s a solid alternative to TextMate if you’re not on a Mac.
Stuff I liked
- The basic refactoring support is surprisingly handy. Until I got back the ability to rename classes and methods I hadn’t realized I’d missed it. I’m told that Aptana can perform similar tricks, but it’s been a while since I’ve tried it out.
- Likewise, the ability to jump directly to a class definition is handy, although it isn’t perfect. (If you have more than one class of the same name defined but located in different files or scoped to different modules it can’t figure out which one, exactly, you’re referencing, which I suppose is understandable.)
- RSpec support! A must-have. And the ability to jump back and forth between test and class… most of the time.
- If you’re a Vi user, the jVi plugin is almost worth the price of switching purely on its own. It’s a truly excellent piece of software, with an enormous amount of tweakability and really support for Vi constructs, and one of my complaints with Vim itself has always been that it lacks good project/directory browsing support, and yes, I’ve tried the Project plugin… again and again and again.
- It knows to insert an “end” when I hit enter after a block or method definition. Just a stupid small thing, but I miss it now when I don’t have it.
Stuff I didn’t like
- It opens up a new output window each time you hit Shift-F6 to run a test, leading to a million open output windows after you’ve been using it for a while. This is an enormous pain in the ass, and it’s compounded by the problem of really poor tab management support in the section of the IDE that displays your previous test runs. This is my single biggest complaint.
- The “jump to file” functionality doesn’t insert automatic wildcards the way TextMate does. This drives me absolutely nuts and it’s something I miss desperately.
- Method autocomplete doesn’t work well and is far more trouble than it’s worth. I turn it off almost immediately.
- It does not, and here I am being charitable, have the most attractive design on the face of the planet. I realize that by stating this I am probably slagging the work of some diligent UI designer somewhere, and I realize that you have to work within the constraints of Swing themes across multiple platforms. But it doesn’t stack up well next to the clean design of TextMate, or the brand new, achingly sexy (YMMV) MacVim.
Lessons Learned
- Use a nightly build, and keep it fresh. It’s the only way to get support for stuff like RSpec. The nightly builds have been stable and make for happy funtimes.
- Spin up your dev server on the command line rather than using the builtin server runner. Maybe it’s just me, but using an IDE for this just doesn’t seem worth the trouble.
If you’ve spent any time working with Ruby in NetBeans I’d be curious to hear about it.
Posted in Professional | no comments |
I realize that this constitutes a flurry of activity
But it had to be done. Handshake 0.3.0 (should it have been 0.2.2?) will not enforce any contracts unless the global $DEBUG flag is set (ruby -d). Should have gotten around to it a while ago. Luckily, it’s a very easy change: don’t alias :new unless $DEBUG. A proxy object is never created, therefore no contract barrier exists.
Posted in Professional | no comments |
Handshake at Boston.rb
This is just a quick note that I’ll be giving a brief presentation on Handshake next Tuesday at the Boston Rubygroup. Once I finish the slides they’ll be another nice introduction. Unfortunately the other Tuesday presentation is on Hackety Hack, with which I cannot hope to compete. Such is life.
Posted in Professional | no comments |
Handshake 0.2.1 Released
I’ve pushed out a new version of Handshake. The big-ticket item in 0.2 is that method argument contracts now support contracts on blocks. When a block is passed to a method that’s protected by a block contract, the block will be modified to check the arguments and return values for that block in much the same way that a normal contract is checked. Note that this will probably not work in Ruby 1.9, or at least will have to be modified for recursive contract checking.
Here’s the syntax:
class StringArray < Array
contract :each, Block(String => anything) => self
endBlock checking in 0.2.0 involved reopening the Proc class; release 0.2.1 fixes that.
The new release also contains a new method, checked_self. Because of the way Handshake is implemented (with a proxy object), calls to private methods aren’t checked (because they’re called on the real object instead of the proxy object). checked_self returns the proxy object instance and calls made to that object will be contract checked.
I’ve also improved the documentation. You can find the rdoc at http://handshake.rubyforge.org, and the project page at http://rubyforge.org/projects/handshake/.
Posted in Professional | no comments |
Chicago: in fashion
I’m in Chicago tonight for another job interview tomorrow. Never been to Chicago before, so that’s very cool, and I’m excited about the interview. Not much more to say except that downtown Chicago is stunning (and I get a 28th-floor view here), and that overriding Proc#call does not in fact affect the behavior of yield. Nobody expects the Spanish inquisition:
class Proc
def weird(*args)
# Only get all weird if we ask for it.
puts "weird call!" if args.length > 0 && args[0] == "weird"
orig_call(*args)
end
alias :orig_call :call
alias :call :weird
end
def weird_call(str, &block)
block.call(str)
end
def weird_yield(str)
yield(str)
endand you get:
>> weird_call("weird") { true }
weird call!
=> true
>> weird_yield("weird") { true }
=> trueThis is frustrating, because I wanted Handshake to be able to support:
contract Block(String => Integer) => 1..5For example. Am I wrong? Or is there another mechanism for overriding the behavior of yield?
The degree to which Ruby’s core methods don’t appear to be orthogonal, instead employing lower-level mechanisms to do their work (Class#=== vs. Object#is_a? is another example) has been an unpleasant surprise to me.
Handshake released as a gem
I’ve released Handshake as a live RubyGem. After you update your gem index you should be able to get it with gem install handshake, and you can browse the RDoc at handshake.rubyforge.org. A couple of things have changed since my previous blog post, so pay attention:
- Pre- and post-conditions now expect you to check assertions rather than return a boolean value from the block. I changed this because the project I’m working on requires some moderately complex rule-checking and trying to string together &&’s got really ponderous. This is probably an indication that there are better conceptualizations of that particular problem. I do quite dislike invariant and before/after employing different usage patterns.
- I’ve added a few new clauses. Check the RDoc if you need more information on these.
- I’ve fixed a lot of bugs, specifically a couple dealing with class type checking and contract inheritance.
- Contract violation error messages have been improved. The stack traces are also slightly better but not yet up to par. To generate a proper stack trace it has to be seen as originating from the method in question rather than somewhere within the bowels of Handshake, and that’s been improved but in the worst case is still two or three levels removed from the caller.
I’ll push out another release once I have a better handle on error messages. I’m having a difficult time finding an authoritative answer to what the “best” way is of getting detailed stacktrace information. Is Binding.of_caller still broken? Will debug.rb get me what I need? Or call_stack?
ruby-contract’s default behavior is to ignore contract checking unless your application’s $DEBUG flag is set. Although I haven’t made that the default behavior in Handshake, it makes a lot of sense; a contract system would probably impose inexcusable performance penalties without some way of turning it off. And if we’re not worried about performance in the first place it seems to me like a pure-Ruby implementation of something like one of the above is preferable.
As an addendum, I should note that hoe is totally pimpin’. Hyuck hyuck.
Handshake vs. ruby-contract
Florian Groß (cool!) asks:
Interesting. Any chance of getting a comparison to ruby-contract? :)
ruby-contract is quite nice, and if I’d realized just how nice beforehand I probably wouldn’t have bothered with Handshake; imagine my chagrin. Its wiki is defunct, and I couldn’t gem install ruby-contract, so I figured the project was dead or unmaintained and never took a look. Lucky for me, there are enough big differences between the two in interface and approach that it’s worth spending some time to examine them. I can’t claim to understand everything that’s going on it it yet, so Florian, please correct me if I get it wrong.
Update: I misread one of Florian’s signature examples. Fixed.
Big Picture
See my previous post for the big picture on Handshake. The idea is that you define contracts directly in classes, whose behaviors are applied to subclasses. In contrast, ruby-contract’s contracts reside in their own class and are applied to other classes through the fulfills method. The code below comes from ruby-contract’s test cases (tc_contract.rb) and gives a good feel for how you would interact with the code to define contracts.
class EnumerableContract < Contract
provides :each
end
module List
module NonEmpty; end
end
class ListContract < Contract
implies List
def self.check_count() 3 end
provides :each
provides :[]
provides :size do
assert(@object.size >= 0)
end
end
class NonEmptyListContract < ListContract
implies List::NonEmpty
provides :size do
assert(@object.size > 0)
end
end
class EmptyList
def each() end
def [](idx) end
def size() 0 end
fulfills ListContract
end
class NonEmptyList < EmptyList
def size() 1 end
fulfills NonEmptyListContract
endThis code does a fair number of things that Handshake doesn’t attempt. Because Handshake agreements are defined either directly within a class or within its superclass there’s no way or reason to verify that a particular class provides or doesn’t provide a method. I also really, really like the syntax for the provides precondition checks. On the other hand, ruby-contract doesn’t appear to allow you to check class invariants, or to check postconditions in the context of all of a method’s arguments. Florian, please correct me if I’m mistaken.
Method Signature Checking
Both libraries offer method signature checking. I happen to prefer my syntax, but it’s mostly an aesthetics thing. I’m dismayed to discover that my idea of using the === operator for these clauses isn’t half as clever as I thought it was, or perhaps we are simply both clever. :)
Handshake:# accepts a string, return value doesn't matter
contract :name=, String => anything
# accepts a block, returns an array
contract :each, Block => Array
# Matches something that is an Enumerable and that responds to
# either :to_ary or :to_a.
contract :x, all?(
Enumerable,
any?(
responds_to?(:to_a),
responds_to?(:to_ary) ) ) => anything# accepts a string, return value doesn't matter
signature(:name=, String)
# accepts a block, returns an array
signature(:each, :block => true, :result => Array)
# Matches something that is an Enumerable and that responds to
# either :to_ary or :to_a.
# From ruby-contract docs.
signature :x, Contract::Check::All[
Enumerable,
Contract::Check::Any[
Contract::Check::Quack[:to_a],
Contract::Check::Quack[:to_ary]
]
]We both provided remarkably similar combinators for signature clauses, although mine are defined methods and his are classes. Mine are quite expressive in terms of the error messages they generate, but I haven’t checked ruby-contract in that regard.
Implementation
Handshake is implemented as a proxy object that resides on top of an object and intercepts all method calls, running them through invariant, signature, and general pre- and post-condition checks. It uses this to ascertain blame as necessary, although the exception messages are generated by the checks themselves. The proxy object looks, acts, and feels like the real object.
In contrast, if I understand things correctly, ruby-contract uses eval to redefine methods that the programmer wants to check. For end users, the difference lies in the way calls to methods within the same class are evaluated. In Handshake, the proxy object establishes a barrier but cannot monitor anything that occurs inside that barrier. This means that calls to private methods are effectively uncheckable. The upside is that it allows you to define invariants in terms of methods as well as instance variables without getting stuck in an infinite loop. This is particularly useful for cases where you want to extend the behavior of a core Ruby class but don’t have access to its internals; see the NonEmptyArray example from my last post.
ruby-contract also hooks into Test::Unit to allow access to its assert methods within provides blocks and utilizes its inheritance properties to automatically check those clauses as soon as a class is defined as fulfilling a contract. This is an insanely good idea and I may stealborrow some portion of it.
Conclusion
Both libraries provide some unique and complementary contract mechanisms. ruby-contract is more mature, judging by the code, although it hasn’t been updated for a while. Not to be all wishy-washy, but it looks like there are projects that could benefit from either library, or both. I’m glad I finally took the time to dig through it.
Older posts: 1 2