CSS Insert

digg del.icio.us TRACK TOP
By admin | Filed in css, html | Comments

I imagine every web designer has, at one point or another, wondered why HTML does not support some means of HTML insertion. You can find numerous hacks to provide this capability such as Apache Server Side Includes, AJAX solutions such as jQuery’s $.load, scripting solutions like PHP’s include(), and even middle-ware like recent posts I have been thinking about using CSS for more than it’s original purpose as “Style Sheet” to mean something broader and more useful, “Semantic Structure”. In other words, the HTML would specify only the what and the CSS would specify all of the how. I think this is best approach for the future of web standards as it creates very good separation-of-concern.

Interestingly, it occurs to me that this could potentially mean that HTML inserts should not be done in the markup at all, but rather in the CSS. Consider this simple pseudo example in Jaxer:

  <html>
  <body>
    <jaxer:insert src="header.html"/>
    Content of said webpage.
    <jaxer:insert src="footer.html"/>
  </body>
  </html>

It is clear enough what the intention of this is even if you have never used Jaxer. Clearly this example is mixing content with structure. Using a CSS Insert instead (if CSS could do such a thing) we might have:

  <html>
  <body>
    <span id="header"/>
    Content of said webpage.
    <span id="footer"/>
  </body>
  </html>
  #header{
    insert: url(header.html)
  }
  #footer{
    insert: url(footer.html)
  }

Taking it one step further, per my last post, our “HTML” can become XML:

  <html>
  <body>
    <header/>
    Content of said webpage.
    <footer/>
  </body>
  </html>
  #header{
    insert: url(header.html)
  }
  #footer{
    insert: url(footer.html)
  }

CSS Inserts could be a very powerful tool. For example, changing the class of a div that has an insert style, rather than using an AJAX load. It would be interesting to explore the full potential of this idea –and it’s downsides. At the very least, it is clear that it would effectively allow us to work with HTML in much the same way as we can currently work with images in our CSS.

Tags: ,

wxRuby for the Lazy

digg del.icio.us TRACK TOP
By trans | Filed in gui, ruby | Comments

WxRuby is probably the best overall GUI library for Ruby currently available. It is cross-platform, provides native look-and-feel and is stable enough for production use. All other GUI libraries, despite their various merits, fall short in at least one of the areas. However, WxRuby does have one major downfall. It is pretty much a straight port of the C API. Writing WxRuby code is largely the same as writing actual WxWidgets C code. It’s far from the “Ruby Way”.

So how did I mange to get fairly nice Ruby code despite a binding that is essentially a straight port of the underlying C API? I built it from the bottom-up using a lazy coding technique. And I mean “bottom-up” literally –the following code might actually be easier to read if you start from the bottom and work your way up to the top. The trick is to break down one’s interface into individual widgets and create an instance method for each using the ||= memoization trick.

You can see from the following code I was able to apply this “trick” to everything but toolbar buttons (aka ‘tools’). This is because the toolbar itself is needed to create them. So I simply defined attributes for each tool, but actually created the tool buttons in the toolbar’s method. Have a look.

  class View < ::Wx::Frame
    def initialize
      super(nil, -1, "My Application",
        :style => Wx::DEFAULT_FRAME_STYLE | Wx::TAB_TRAVERSAL,
        :size => [800,600]
      )
      setup_controls
      setup_events
    end
 
    # kickstart widget creation from the bottom up
    def setup_controls
      search_toolbar
      settings_toolbar
      search_list
    end
 
    def frame_panel
      @frame_panel ||= (
        panel = Wx::Panel.new(self)
        panel
      )
    end
 
    def frame_sizer
      @frame_sizer ||= (
        sizer = Wx::VBoxSizer.new
        frame_panel.sizer = sizer
        sizer
      )
    end
 
    def notebook
      @notebook ||= (
        notebook = Wx::Notebook.new(frame_panel)
        frame_sizer.add(notebook, 1, Wx::GROW)
        notebook
      )
    end
 
    def search_panel
      @search_panel ||= (
        panel = Wx::Panel.new(notebook)
        notebook.add_page(panel, 'Search')
        panel
      )
    end
 
    def settings_panel
      @settings_panel ||= (
        panel = Wx::Panel.new(notebook)
        notebook.add_page(panel, 'Settings')
        panel
      )
    end
 
    def search_sizer
      @search_sizer ||= ( 
        sizer = Wx::VBoxSizer.new
        search_panel.set_sizer(sizer)
        sizer
      )
    end
 
    def settings_sizer
      @settings_sizer ||= (
        sizer = Wx::VBoxSizer.new
        settings_panel.set_sizer(sizer)
        sizer
      )
    end
 
    def search_toolbar
      @search_toolbar ||= (
        toolbar = Wx::ToolBar.new(search_panel)
        @search_start_tool   = toolbar.add_tool(-1, 'Start'   ,
            Wx::Bitmap.new(DIR + '/images/search.gif', Wx::BITMAP_TYPE_GIF), 'Start')
        @search_stop_tool    = toolbar.add_tool(-1, 'Stop'    ,
            Wx::Bitmap.new(DIR + '/images/stop.gif'  , Wx::BITMAP_TYPE_GIF), 'Stop')
        @search_insert_tool  = toolbar.add_tool(-1, 'Insert'  ,
            Wx::Bitmap.new(DIR + '/images/insert.gif', Wx::BITMAP_TYPE_GIF), 'Insert')
        @search_import_tool  = toolbar.add_tool(-1, 'Import'  ,
            Wx::Bitmap.new(DIR + '/images/import.gif', Wx::BITMAP_TYPE_GIF), 'Import')
        @search_delete_tool  = toolbar.add_tool(-1, 'Delete'  ,
            Wx::Bitmap.new(DIR + '/images/delete.gif', Wx::BITMAP_TYPE_GIF), 'Delete')
        search_sizer.add(toolbar, 0, Wx::GROW)
        toolbar
      )
    end
 
    def search_start_tool    ; @search_start_tool   ; end
    def search_stop_tool     ; @search_stop_tool    ; end
    def search_insert_tool   ; @search_insert_tool  ; end
    def search_import_tool   ; @search_import_tool  ; end
    def search_delete_tool   ; @search_delete_tool  ; end
 
    def settings_toolbar
      @settings_toolbar ||= (
        toolbar = Wx::ToolBar.new(settings_panel)
        @settings_save_tool     = toolbar.add_tool(-1, 'Save'    ,
            Wx::Bitmap.new(DIR + '/images/save.gif'    , Wx::BITMAP_TYPE_GIF), 'Save')
        @settings_undo_tool     = toolbar.add_tool(-1, 'Undo'    ,
            Wx::Bitmap.new(DIR + '/images/undo.gif'    , Wx::BITMAP_TYPE_GIF), 'Undo')
        @settings_restore_tool  = toolbar.add_tool(-1, 'Restore' ,
            Wx::Bitmap.new(DIR + '/images/restore.gif' , Wx::BITMAP_TYPE_GIF), 'Restore')
        settings_sizer.add(toolbar, 0, Wx::GROW)
        toolbar
      )
    end
 
    def settings_save_tool    ; @settings_save_tool    ; end
    def settings_undo_tool    ; @settings_undo_tool    ; end
    def settings_restore_tool ; @settings_restore_tool ; end
 
    def search_list
      @search_list ||= (
        list = Wx::ListBox.new(search_panel, :choices=>ctlr.sites.map{|s| s.href})
        search_sizer.add(list, 1, Wx::GROW)
        list
      )
    end
 
    def setup_events
      evt_menu( search_start_tool     ) { ctlr.search_start     }
      evt_menu( search_stop_tool      ) { ctlr.search_stop      }
      evt_menu( search_insert_tool    ) { ctlr.search_insert    }
      evt_menu( search_import_tool    ) { ctlr.search_import    }
      evt_menu( search_delete_tool    ) { ctlr.search_delete    }
 
      evt_menu( settings_save_tool    ) { ctlr.settings_save    }
      evt_menu( settings_undo_tool    ) { ctlr.settings_undo    }
      evt_menu( settings_restore_tool ) { ctlr.settings_restore }
    end
  end
 
  class Controller < ::Wx::App
    attr :service
    attr :view
 
    def on_init
      @service = Service.new   # backend service
      @service.connect         # connect to database
 
      @view = View.new(self)
      @view.show(true)
    end
 
    def sites ; service.sites ; end
 
    def search_start     ; service.search_start     ; end
    def search_stop      ; service.search_stop      ; end
    def search_insert    ; service.search_insert    ; end
    def search_import    ; service.search_import    ; end
    def search_delete    ; service.search_delete    ; end
 
    def settings_save    ; service.settings_save    ; end
    def settings_undo    ; service.settings_undo    ; end
    def settings_restore ; service.settings_restore ; end
  end
 
  Controller.new.main_loop

The thing to notice, if you haven’t caught it yet, is how calling #search_toolbar leads to calling #search_sizer which in turn leads to calling #search_panel, and so forth all the way to the top #frame_panel. This code is a striped down version of actual code I am using. I hope it helps others create wxRuby application more easily. As I said in my previous post, I found in mind-numbingly difficult to create WxRuby interfaces until I worked out this approach. WxRuby is still a difficult API to master, but this technique makes the effort more manageable, and therefore more likely to succeed.

For another example of building structures lazily, have a look at my solution for Ruby Quiz 10 – Crosswords.

Tags: , ,

GUtopIa Revisted

digg del.icio.us TRACK TOP
By trans | Filed in ruby | Comments

Recently I had to buckle down and create and honest to goodness desktop GUI application in Ruby. So once again, after some six years, I set down to weigh my options. It saddens me to say, after all these years, the state of desktop GUI programming with Ruby is still a rather sorry affair. Yes, there have been many improvements –thanks to the hard work of many a good programmer, but the task of creating a Ruby-based GUI application still remains a very non-Ruby-esque ordeal.

My first attempt at it this time was with Shoes. Shoes is a new and very nice GUI engine written largely from scratch by the well known WhyTheLuckyStiff. It’s a noble effort and some really neat programs can come from using Shoes. Unfortunately for my needs Shoes proved to be too buggy and immature –at times I saw visual artifacts and there are a very limited number of controls. And worst of all, the fact that it includes it’s own Ruby interpretor and manges it’s own gems caused it not to work well with some other libraries. For instance, I could not get it to use the latest version of Mechanize.

After examining other choices, such as creating one GUI script per major platform (too much work), or using the old standby FxRuby (never been happy with the lack of native look-and-feel), I decided to try a different course. I was well versed in web application design, so I tried my hand at rigging a web app to act like a desktop app via a locally running server using Ajax calls. The end result certainly looked good and basically worked. But there was a troubling lack of robustness in the interaction between the front-end and back-end. I had to poll the back-end to see what was going on, and the back-end had to spawn threads in order to provide a response to the browser while continuing to work on long-running processes. So it worked, but barely. I’m sure it could be improved, but for a devote POLSer like myself, that meant getting into mucky waters I really didn’t feel like I should need to be diving into anyway. Too bad. Web GUI design is quite advanced compared to Desktop GUI. Why no one has tried to map it directly to the desktop before is beyond me (but you can believe me when I tell you, I can’t wait to delve into Plam’s pre and it’s webOS development platform, which apparently does exactly this).

So where did this leave me? Well, I figured I had one last good shot with wxRuby. Ironically I had something to do with the birth of that project. It was those six years ago that I first looked into GUI frameworks for Ruby. Rich Kilmer was talking about his Utopia/Alpha ideas and I was just starting to feel comfortable with writing scripts in Ruby. I decided there needed to be something better, and working off of Rich’s idea’s for an API I came up the idea of GUtopIa, which would supply a font-end API that anyone could interface to a back-end GUI framework. Sort of a best of all worlds kind of design. A number of people were psyched about the idea, and joined with me to discuss and pursue the project. Unfortunately, I was still wet behind the ears, and the fellow programmers who first entertained working with me didn’t care much for my new-boy-brash style. They told me so, and decided on their own course, to create bindings for wxWidgets instead. I wasn’t happy about it personally. Having studied wxWidgets some, I knew it would be a long time before anything really useful was to come of that project –if at all. In hindsight, while I still believe GUtopIa is a good idea, I am glad it’s didn’t proceed back then –I still had a lot to learn about Ruby before I could do something like that as well as I would really like.

So it was time to check out what the wxRuby team had accomplished. My first handful, or so, attempts were miserable failures. WxRuby has some issues. It is tempermental, and so much like the C API I felt like I was actually programming in C. This is not how Ruby programming is supposed to be! I was having real trouble getting anything more then a basic frame and menu to work. Frustrated with the straight coding approach, I decided to see what WYSIWYG form builders were to be had. I knew wxWidgets touted these, so I looked around and found the precisely named wxFormBuilder. This made it fairly easy to design my complex form and best of all it made it clearer to me how wxWidget GUIs are built. Unfortunately the generated markup, called an XRC file, had issues of it’s own and wouldn’t load properly into Ruby. Once again, I was at a dead end.

Something really needed to be done about this state of affairs. And so I have decided to resurrect the GUtopIa project. I found my old code, looked at it, scrapped it, and started fresh. I’m going to proceed by specifying the front-end API as much as possible, before even considering back-end implementations. With any luck others will see what I’m doing and offer to build a an interface to their favorite framework. So far what I have looks very sweet. Just to wet your whistle, here’s a potential example.

  layout = GUtopIa::Layout.new do
    [ [ 'Name'  ], [ entry ] ]
    [ [ 'Phone' ], [ entry ] ]
    [ [ 'EMail' ], [ entry ] ]
  end
  layout.show

Yes, believe it or not, that’s a fairly complete GUI layout. In an upcoming post I’ll explain how it all works in more detail. But before I get into that, I still need a working desktop GUI application ASAP! I don’t have time to develop GUtopIa for this. So now I’ve tried again at coding wxRuby from hand, but this time using a very Ruby-esque lazy evaluation approach I had experimented with a long time ago in a Ruby Quiz on crossword puzzle drawing. Finally I got the results I wanted with out going cross-eyed looking at the code. Amazing how a well organized approach can make all the difference. I’ll demonstrate my design in my next blog post.

Tags:

XML+CSS: The future of Web Design?

digg del.icio.us TRACK TOP
By trans | Filed in css, html, xml | Comments

In a previous post I point out that microformats bring an additional layer of useful information to a document, which I dubbed semantic structure. In short, HTML tags provide useful information about the data they contain. A good example of this has been the insistent push to use divs rather than tables for page layout. The reason is that tables describe a semantic structure, a table of data, and not layout. I for one have found this a frustrating haggle in the design of my pages. Time and time again I have been stymied by unwieldy divs. Tables are much easier to use, despite additional verbosity. But I have stuck to divs because it is “the right thing to do”. Thankfully my saving grace will soon be here. The 3rd revision the CSS standard supports a new display style. With it, one can specify that a div is to behave like a table, table row or table cell. Woohoo! Three cheers for tabley divs!!

The display style got me to thinking about semantic structure again. If we can designate that a div is a table structure via CSS, then why not any structure? And if divs, why not any tag? If we were able to do that, then semantic structure could be specified solely through CSS. And our HTML pages could go from rather simple, repetitive occurrences of div to … can you guess?… pure XML.

Let’s got through it step by step. Here some HTML:

Now with CSS 3:

Of course no one would recommend doing this to something that really is a table of data. But bare with me, because now we are coming full circle:

I think this is a rather remarkable outcome. And you might be surprised to learn that Firefox handles it just fine. What we have achieved is an ultra-clean separation between the data and it’s semantic meaning, via XML, and it’s semantic structure, via CSS. If this approach were embraced by the XHTML and CSS standards bodies, I would not be surprised to see it revolutionize web design.

Facets Associations

digg del.icio.us TRACK TOP
By trans | Filed in ruby | Comments

For this edition of our exploration of Ruby Facets we’ll look at something a bit unconventional. As many of you may already be aware all of the libraries in Facets are divided into three groups. The CORE library houses all the extensions to Ruby’s core classes; the LORE library (the most recent division) is a funny name for extensions to Ruby’s standard library; and the MORE library is a collection of original additions. In the MORE library you will find a script called, association.rb.

  require 'facets/association.rb'

This script provides a class called, obviously enough, Association, which can be used to create generic one-way associations between objects, i.e. allowing one object to be associated with another. It has a variety of uses, such as link-lists, ordered maps and mixed collections.

While one can use Association.new to draw these associations, they can be drawn more conveniently using the #>> operator.

  :Apple >> :Fruit
  :Apple >> :Red

We can see the associations that have been drawn by calling the #associations method on the object in question.

  :Apple.associations   #=> [ :Fruit, :Red ]

That’s really all there is to associations. Beyond this is simply a matter of how to put them to good use. For example, one interesting use is in arrays to make simple lists of ordered pairs.

  c = [ :a >> 1, :b >> 2 ]
  c.each { |k,v| p "#{k} is associated with #{v}" }

produces

  "a is associated with 1"
  "b is associated with 2"

There is one caveat to using association.rb. Since it defines the #>> operator universally, one needs to be mindful of areas in which it may conflict with other definitions. Generally this is not an issue because #>> is a rarely used method. But, for instance, you can’t use it for any of the following classes because they use #>> for other things.

  Bignum
  Fixnum
  Date
  IPAddr
  Process::Status

When there is this potential for a conflict, you can always fall back to using Association.new. Unfortunately, it is this caveat that makes this library unconventional. If it were otherwise, I believe Associations could be a much more widely used class.

And that brings to the reason I choice the association.rb library for this edition. I would like to get feedback on ways to improve the implementation. My main concerns are 1) should object have one single association, or handle multiple associations as they do now; 2) how best to store these relationships, eg. globalb variable or class variable, &c.; and 3) how best to notate them so they are convenient to define but unobtrusive, something #>> is not.

What’s µF got on XML?

digg del.icio.us TRACK TOP
By trans | Filed in xml | Comments

Decisions, decisions. Therein lies the reason why convention over configuration is so bloody great, precisely because it requires fewer decisions. Reap, my humble build tool, outputs log files. Yea, logs are good. But the decision I have to make is, “in what format?”

Now old-school would just put out some asterisk-studded text files with plenty of precise timestamps, maybe some nice long ------------------------------ lines to divide things up. No doubt these files are easy to access and fairly readable. We like out text files. But hey wait. This is the age of magical markups. At the very least we can coax that log into a Wiki-tongue. For us Rubyists, we have rdoc, markdown and textile’s just a few gemy fingertips away. These formats can be even easier to read thanks to structural consistency from log to log. Plus, fire-up a web server and we can get some really nice looking HTML too. That’s the beauty of Wiki Wiki markup after all.

Now if beauty were all that matter, then there would be no point in looking further. But like America’s continental shelves there is untapped wealth going to waste here. There is data in them there logs! The modern buzzword is semantic. Taking logs to the next level requires us to ensure their semantic value. On that account, XML was created, and long predicted the format of the future. Certainly XML has made great strides, but it is still far from meeting its promise. There is simply too much complexity involved in both marking up the content and in generating nice output.

Then comes along the microformat. The microformat combines the semantic capabilities of XML with the layout capabilities of HTML. Microformats are relatively new and still finding their footing. Indeed, I think a Universal Uniform Microformat Specification is ultimately the necessary outcome. In that vain I make a first rough estimate of what such unifying system might look like, and why, contrary to many arguments otherwise, microformats do in fact bring more to the table than XML.

Where XML provides semantic information within a doubly linked hierarchy (via attributes and body), microformats provide the same plus a set of well defined data structures. Microformats provide semantics through a small set of tag attributes, role, rel, rev and primarily the class attribute. The class attribute alone is enough to make microformats fully equatable to XML. We can easily map the same data set in either format:

  <people>
    <person>
      <name>John Jay</name>
    </person>
  </people>

as opposed to

  <div class="people">
    <div class="person">
      <span class="name">John Jay</span>
    </div>
  </div>

Although the microformat is more verbose, the two contian the same original semantic value. But the extra verbosity isn’t just a waste of UTF bytecodes, it says something. Specifically it gives us a semantic structure. It just so happens that HTML evolved to offer these structures precisely because that is what data presenters require to do their jobs well. And for the same reason, why you are always being beat with the div-stick when you try to take the load road of laying out your pages with tables.

So what semantic structures do micorformats via HTML make available to us? The quick rundown: we have layouts using div and span, lists using ol, ul and li; definition lists using dl, dd and dt; and tables using table, tr, th and td. Those are the obvious structures. There are still other smaller structure’s like a for links, and the hefty set of form elements. All these elements provide us a way to say what type of thing our data is or partakes in, not just what the data is.

Clearly, the creators of XML saw the need for something like this and tried to achieve it through XML Namespaces. But namespaces are less effective because they are completely arbitrary, whereas HTML gives us a limited but universal structural language. Seems to me there is a principle to be found here that can be a guide for both the future of HTML and Microformats.

Tags: , ,

Facets Hash#rekey

digg del.icio.us TRACK TOP
By admin | Filed in ruby | Comments

This is the first in a series of posts in which I plan to introduce my fellow Rubyists to the plethora or goodness that is Ruby Facets.

Ruby Facets has been in development for several years, starting out as a rather rag-tag collection general purpose Ruby scripts, and has evolved into the latest release, version 2.5.0, which has reached a nice level of maturity –getting pretty close, I suppose one could say, to that stately realm of “enterprise-ready”.

Every few weeks or so, I’ll pick a library or particular extension and expound upon it. While the main intent of this series is to let others know what Facets makes available to them. I will also use it as a platform to further improve and polish Facets. So please, feel free to comment, make suggestions and point out alternatives, so that Facets might better serve the Ruby community in the future.

Okay, now to the meat of this edition…

I decided to start with something quite simple, but very useful, homogenizing hash keys. Currently in Ruby, this requires code like:

  new_hash = {}
  old_hash.each do |k,v|
    k = k.to_sym
    new_hash[k] = v
  end

Of course, that can be golfed-down a bit, but I wanted to spell it out for clarity. In this particular example, I converted all the keys to symbols (to_sym). Along with strings, that is one of the most commonly needed key conversions. Common enough in fact that Rails’ ActiveSupport library provides symbolize_keys and an alias #to_options. It’s also provides stringify_keys. Facets offers these methods too, since they are certainly so well known by now. However, Facets provides and recommends a more versatile method, rekey. With it the above example becomes as simple as:

  old_hash.rekey

Hash#rekey actually takes a block, but if no block is given, as in the above, it defaults to symbol conversion. If we wanted to convert the keys to strings instead, the magic of Symbol#to_proc makes that as simple as:

  old_hash.rekey(&:to_s)

And lastly, of course, we could get crazy with it and make every key a “Turk”.

  old_hash.rekey{ |k| Turk.new(k) }

I don’t know about you, but I like turk-keys. Oh, the pun! It hurts! :)

Happy Thanksgiving.

The YADSL Rule

digg del.icio.us TRACK TOP
By trans | Filed in ruby | Comments

Looks like the Ruby world is a fire with new DSLs for BDD/TDD. There’s

… woulda, coulda … My word! So many choices. I o doubt there are more. It’s fitting that it’s Thanksgiving, what we have here is a cornicopia of framework!!! Uh… Okay, you’ll have to forgive me. I get carried away.

I suppose it all started with that RSpec. Those guys built an incredibly elaborate nomenclature to help us spell out our code’s behaviors in gruesome detail. But as wonderfully grandiose as it may be, there’s just one tiny little itty-bitty problem… I can’t remember it. Oh, sure, I could sit down and jam it into my already overloaded brain somewhere, but you know what. I ain’t gonna. I already have enough new stuff to learn and I’m not going to bother to learn another DSL when those I already know work just as well.

So therein lies the serious downside to any new DSL. They require more brain cells. We’re talking the old “learning yet another language” dilemma here. I was thinking about this today, and it strikes me as one of those cool rules we oft hear about. So I decided to ‘writ’ one for the occasion.

Do not create a DSL if a native solution would be as elegant.

In fact, a good DSL will likely need to be substantially more elegant in order to fully justify its existence.

I’m calling this the YADSL Rule, for “Yet Another Domain Specific Language”.

Now, a quick look around the world of modern programming (see [DZone](http://dzone.com)), just as quickly makes clear that the YADSL rule is in no short supply of violations. Indeed, I dare say, that most of programming today is not innovative, but masquerading around as such via YADSL.

Now I don’t want to seem too harsh. There is of course a certain level of refinement taking place in some areas. And that naturally has to play itself out. But it’s getting a little crazy. Besides test frameworks, web frameworks and Javscript development frameworks seem to have hit a New Cambrian Explosion. I don’t see how we’re supposed to keep up with it. I can only hope that my little rule might help to cool all this exuberance down a bit; so we can catch our breaths and take some time to consider the drenchal downpour of verbage that has befallen us.

Of course, the real problem may be that too many people want to make YANFT (Yet Another Name For Themselves).

I sware to you. I’m not one of them. But I will be introducing my own Ruby test framework soon.

No. I’m not kidding.

Don’t worry, there’s no new DSL to learn. And that’s what makes my framework so very special. I’ll keep you posted.

Tags: , ,

This Old Hash

digg del.icio.us TRACK TOP
By trans | Filed in ruby | Comments

The Hash may well be the most used class in Ruby. Sure, our programs have arrays and strings galore, but they generally come and go without much ado. Hashes on the other hand get *used*; and by that I mean to say, we spend a lot of time fussing with them. I think there are two significant reasons for this and I will focus on the first, and the more important of the two, here.

Now, I suspect you would agree, if I were to present you with a class which was clearly overkill for vast majority of its intended uses, and its use required repeated mitigation of its unused features, I have no doubt, you’d unequivocally advise me to select a “better tool for the job“. And yet, that’s the situation all Ruby programmers face, day in and day out, with Ruby’s Hash.

Ruby’s Hash is exceptionally powerful because it supports any type of object as a hash key. That’s really really cool… for all of about five minutes. The truth is, the vast majority of cases only require one type of key –for Ruby that will either be a Symbol or a String, and because of this, a great deal of time and code is wasted ensuring all keys are that single type. Because of this, methods like #to_sym often riddle our scripts.

The issue is undeniably attested to by real world “solutions” others have created to address it, such as Ruby Facets’ Hash#rekey. and Ruby on Rails’ HashWithIndifferentAccess. But let’s face it, these are both underwhelming attempts at mitigating the fundamental problem.

A real solution would have the current Hash class renamed, and a new limited-key structure put in its place. The old class would still be available, of course, for those special cases when a key of any object type is required, but the new, more utilitarian Hash class would be the literally-constructed default. The end effect of this change would be simple:

  h['a'] == h[:a]
  h['1'] == h[1]

This means reducing all hash keys to a single *symbolic* index type. It does not matter what the actual reference is, a String, Symbol, Integer, etc. just so long as it has a predictable symbolic representation.

It may feel a bit strange to consider a suggestion that actually calls for the reduction of features. More often change requests call for just the opposite and YAGNI has to be peddled out on them. But, I think, we often underestimate the power of simplicity. Consider ideas such as convention-over-configuration and duck-typing –simplifications that are not necessarily intuitive at first. But in the end, they make our life as programmers a good bit more productive.

“Make everything as simple as possible, but not simpler.”
–Albert Einstein

Tags: ,

An Alley-OOP for If

digg del.icio.us TRACK TOP
By trans | Filed in ruby | Comments

Ruby takes a unique approach to conditional evaluation: All objects are equivalent to true except nil and false. No doubt this is a more object-oriented approach than, say, C++’s use of 0 as false, but it’s far from the ideal of OOP all the way down, as any Smalltalker can attest.

Consider the following case. For a while now I have wanted in my arsenal of Ruby classes a NullClass defined basically as:

  class NullClass < NilClass
    def method_missing(*a)
      self
    end
  end
 
  NULL = NullClass.new
 
  def null
    NULL
  end

This object would greatly benefit fluent interfaces. Instead of returning nil, such interfaces could return null, and no error would be thrown when invoking any method against it.

  obj = null
  obj.it.does.not.matter  #=> null

Unfortunately null is not very viable in Ruby because null still evaluates as true when used as the expression of a condition. The fact remains, Ruby is hardcoded to see only the singleton instances of NilClass and FalseClass as false.

I’ve requested that NullClass be added to core Ruby in the past (as of yet to no avail) and though I still would like to see it included, it may be better still to take an altogether object-oriented approach to conditions –in the spirit of Smalltalk. This would allow us to freely create “false” objects, like the NullClass, ourselves.

The adoption of such a capability does not require the odd syntax used by Smalltalk (ifTrue / ifFalse). Rather, it can take an approach more akin to Ruby’s own case statements. As with case’s use of #===, a particular method would be used to evaluate the “truthiness” of a value. This would apply for all types of conditions: while, until, etc.

To clarify, let’s say this special method is simply called #if, then…

  class IfExample
    attr :if
    def initialize(@if)
      @if = if
    end
  end
 
  x = IfExample.new(false)
 
  if x
    "Yes"
  else
    "No"
  end

The result of this condition would be "No".

While it may not be an earth shattering adjustment, the additional flexibility opens up some interesting doors. Not only would classes like the previously mentioned NullClass become possible, but conditions themselves become dynamically controllable.

For example, it would allow method probes to fully map method signatures (the Halting Problem not withstanding). This is not currently possible in Ruby because a probe cannot pretend to evaluate to false in order to walk through the false side of a condition.

The idea would require some getting used to –after all a simple if-statement would no longer do what we Rubyists presently take for granted. But then, that’s the nature of progress, is it not?

Tags: