28 August, 2009

Update to Post Regarding Hacking & Ruby

This will be a very short entry as it is rather late and I'm looking forward to sleep. I would do but I do feel that I have to get some observations off of my chest after the past 6 hours of exploring ruby (for the third time).

#1. Ruby isn't as intuitive as one might suspect. Maybe python and others of similar influence (groovy) have raised the bar too high in terms of dynamic language syntax and expectations. The standard ruby idioms are inconsistent and ill-named in several cases, mostly involving native data sets.

#2. Namespaces in Ruby are an even bigger mess than perl. To some degree, perl's system seemed to make sense yet from what I've read, seen and with which I experimented, I find the namespace setup for Ruby to be subpar and dare I saw far from fluid in implementation details.

#3. Ruby is indeed very slow, especially when working with the Array types in combination with large datasets and continual pre-requisite 'include?' method calls for each datum in said set. I did find that I was able to achieve the same results wanted via Hash population followed by a dump of keys to an Array with a noticable speedup, removing the need for the very slow 'include?' method. Membership tests are a joy of high level languages, but a drain on some resources, ruby more than others though without a doubt.

#4. The novelty of mutable and immutable version of method calls (collect! vs. collect, slice! vs. slice) is just that. A novelty. This is an ambiguity which I believe does not help to further ease of readability and usability. It further necessitates that non-standard library code implement similar idioms and 'practices' for uniformity's sake with the downside being a snowball effect in this area.

#5. Ruby isn't sure if it wants to be perl, c, smalltalk or itself as can be determined by the mix and match of terms, keywords and standard method names. It doesn't feel like a concrete language that was purpose built, but more like an object system with various sources for tacking on the remaining pieces of the language so as to round out the feature range.

These experiences with Ruby (for the third time) may have been different had I not been spoiled by Python (most notably), or were I not coding in the field for the past 15 years. This is not the case nonetheless. I couldn't see myself coding in this language for anything mission critical or heavy duty and after looking at the problems many of the ruby back-ended software systems and/or websites vs. the other high-level dynamic languages have suffered, it becomes quite clear when industry giants such as Google and IBM throw their weight behind Python.
This isn't meant to be an argument starting post about Ruby vs. Python as they can be found elsewhere, though if the shoe fits...


Labels: , , , , ,

24 February, 2008

Quick Django Tip: Dynamic Application Object Retrieval

In my recent django adventures I needed to introduce site-wide search functionality and in the process of doing so, encountered a small roadblock towards doing so.  Apparently due to the nature of Django's API for db interaction (as of the last stable release version), there is a limitation as to the use of python variables in API calls.  I found this to be a hinderance, but only for so long.  

The follow code snippet was something I whipped together which by utilising Python's 'eval' built-in, overcame the aforementioned limitation regarding the API's ability to interpolate native Python (e.g. non-django explicit) varaibles.

Things to know to understand the following example:  

 search_input is a list of cleaned and pre-processed user-driven terms, split into separate expressions, (e.g. ["dynamic langauge", "agile", "programming", "paradigm"]). 

 search_schema is a dictionary in which the key is the django model/class through whose objects we are attempting to search, and the value is a list of specific model attributes to attempt said search.  (e.g.   User_Profile : ['firstname' , 'lastname', 'address_1', 'bio_info', 'favourite_books'])

container_xref is a simple alias mapping for the actual django application names to our internal references inside this search code base.  Obviously this whole bit could be written without said setup, but for readability given the scope of the actual application involved, and the fact that I was not searching simply a few static fields in one django application, but several dozen fields through about two dozen separate applications, this container_xref dict was appropriate.   It is through this mapping dict which we place any matched object results (so as to not waste any additional space via unnecessary list initialisations.) for eventual results generation.

Note: the key "total_results" in the container_xref was a simple means of keeping track of overall search matches, rather than relying upon the Django templating engine (view) from doing work responsible from the processing (controller) perspective.  In retrospect, there are better ways this could have been handled, and in future point revisions, this will be addressed.

------

for search_string in search_input:
  for application in search_schema.keys():
    for attribute in search_schema[application]:
code_to_eval = "%s.objects.filter( %s__icontains='%s' ).order_by('-id')" %       
                     (str(application), str(attribute), str(search_string))
        try:
          eval_results = eval(code_to_eval)
          for eval_result in eval_results:
            if eval_result not in container_xref[application]:
              container_xref[application].append(eval_result)
              container_xref['total_results'] += 1
        except Exception:
    ### Case specific exception handler types, assignments and resultant actions 
          ### specific to each application in which the above is implemented, go here.

-----

As can be seen from the above, simple inline substitution proceeded by evaluation of said string results in post-compilation dynamic search functionalities within django, addressing simple problems one might run into with the existing API which will most likely be addressed in future versions.  

Your results may vary.

Eric

Labels: , , , ,

19 February, 2008

Ruby: Somehow I overlooked this Gem of a Language

About 5 years ago I started looking into a language that prior to it's "Rails" fame, was lesser known and even lesser utilised.  I tried it a bit and found it leaving me wanting more.  I've kept tabs on it over the years, reading the tutorials and writing several quasi-AI experimental applications for my SimulaE research, but I ended up being enticed by Python, a language which I stand by, including the wonderful (but until recently unused by me) framework Django (Python's Rail's equivalent, focused on Publishing).   

I've programmed professionally using Python for several contracts/years now and find it quite enjoyable.  In fact, I'm currently coding specifically in Python for Inkedmagonline.com, but that doesn't mean that I don't continue my personal exploration and education for both personal and professional reasons.  I decided to re-experience Ruby by picking up the hallowed PickAxe book and giving it another honest chance.  I'm glad I did.  

I believe that Python, and the values espoused in Tim Peter's "De Zen van Python" (The Zen of Python) (my copy just happens to be in Dutch, otherwise I'd post it for others) have helped me to look at Ruby in a different light.  There are some key differences in the two languages, but I can see now the inherent power in Ruby that I was overlooking before.  In fact, some of those key pieces, syntactically as they were which make Ruby so enticing this time around are the very same 'features' I feel are missing in Python.  It only took me working in an environment with situations where said language features would prove the best solution to the problem(s) on hand for me to realise it.

I am not going to spend time detailing all of the specifics, though I may mention one or two nonetheless.  I'm more so bringing this point up so that others might be reminded that giving something new a single chance might be to your own disadvantage.  After all, I didn't like Python the first time I tried it either.  I think it is partially a matter of how we grow as developers that allow us to know what we're missing, that same spark of realisation that gives us the "a ha" of relief when we find it hiding in a new language, programming methodology, etc.  
What brought me back to looking into Ruby a second time is of all things, Smalltalk.  The whole "everything is an object" concept is nothing new to me, or to programming languages.  However in dynamic strongly typed languages, it is.  More importantly is manner of how even rudimentary objects such as integers, floats and strings are treated in Ruby.  They have methods which can be both called using the standard instance.methodname call format, and have their standard methods overridden.  The second being something far more wonky and kludgy in Python (and a non-option in perl).  

The fact that key methods are instance based such as "len" or "length" for example makes a world of difference for consistency.  It speaks to the overall design that "Matz" (Yukihiro Matsumoto creator of Ruby) had in mind during the planning phase.  In Python, a language in which everything is truly an object as well, this starts to get rather confusing.  While Python does treat every integer and string as an object, it mixes the traditional functional paradigm for calling items such as 'len' so that to find the value of 'a', one would type len(a), as opposed to the more object based a.len ..  This seems counter-intuitive and quite frankly a real surprise when you look at the overall design of Python.

I'm not ripping on Python as I do wholeheartedly enjoy the language, I'm just starting to feel aches and pains over decisions which are ingrained into the language, as well as not being seen as an issue or being addressed in py3k (or Python 3000/Python v3.0) as it were.  I just think that my eyes have been opened to Ruby again and I like what I'm seeing.  I am actively looking to find a future professionally as it were utilising it as nothing beats having fun while accomplishing what one would hope accounts to 'great' things.  We'll see what the future holds.

Next Step:  Migrate my SimulaE virtual world/real model object simulation from Python into Ruby as a test run.  Lather, rinse, repeat and then see what the side-by-side comparison's look like.

Until next time...


Labels: , , , , , , , , , ,