Ur Archives

November 20, 2008

Rubyisms

Most rubyisms are convention based, meaning that they are not strictly enforced by the language/interpreter. Hear is my cheat sheet to help orient those new to ruby with some of these conventions without having to dig through the documentation.

Variables & Class Naming Conventions

  • Local Variables, Methods, and Parameters - always start with a lower case character or an underscore
  • Globals - prefixed with a $
  • Instance Variables - prefixed with a @
  • Class Variables - prefixed with a @@. These type of variables imply that there is only a single instance for the entire class. This does not however, imply public visibility.
  • Class Methods - prefix with class name class.method

Access Control

  • public - no access control; the default visibility applied. The only exception is the initialized method which is always private.
  • protected - limited visibility to an instance of the class and subclasses.
  • private - cannot be called with an explicit receiver. Visible only within the class.

Iterators

Code blocks can be dynamically associated with method invocations. The can be used to implement call backs, pass around chunks of code, and to implement iterators.

Code blocks are delimited by {} or the following key words :

do
   ...
   ...
end

The block is invoked in the receiver with a call to yield.

A callblock has the following form :

{|parameter1, .... parametern| argument1, .... argumentn}

The parameters are the values that will be used by the arguments.

Quirks

  • gets stores the input into a global variable $_
  • $_ is the default input for most cases.
  • don't create your own Observer class .... fucks things up.

Troubleshooting

  • Attribute setter not being called. Within an object, Ruby will parse setter= as an assignment to a local variable, not as a method call. Use self.setter= to indicate the method call.
  • A parse error at the last line of the source often indicates a missing end keyword.
  • Make sure that the type of the object you are using is what you think it is. If in doubt, use Object#type to check the type of an object.
  • Make sure that your methods start with a lowercase letter and that classes and constants start with an uppercase letter.
  • If you happen to forget a ``,'' in an argument list---especially to print---you can produce some very odd error messages.
  • Block parameters are actually local variables. If an existing local of the same name exists when the block executes, that variable will be modified by the call to the block. This may or may not be a good thing.
  • Watch out for precedence, especially when using {} instead of do/end.
  • Make sure that the open parenthesis of a method's parameter list butts up against the end of the method name with no intervening spaces.
  • Output written to a terminal may be buffered. This means that you may not see a message you write immediately. In addition, if you write messages to both $stdout and $stderr, the output may not appear in the order you were expecting. Always use nonbuffered I/O (set sync=true) for debug messages.
  • If numbers don't come out right, perhaps they're strings. Text read from a file will be a String, and will not be automatically converted to a number by Ruby. A call to to_i will work wonders. A common mistake Perl programmers make is:

    while gets
      num1, num2 = split /,/
      # ...
    end
    
  • Unintended aliasing---if you are using an object as the key of a hash, make sure it doesn't change its hash value (or arrange to call Hash#rehash if it does).
  • Use trace_var to watch when a variable changes value.
  • Use the debugger.
  • Use Object#freeze. If you suspect that some unknown portion of code is setting a variable to a bogus value, try freezing the variable. The culprit will then be caught during the attempt to modify the variable.

Performance

These idioms will help close the distance in performance between native code versus interpreted code generated by ruby:
  • Create locals outside of code blocks to prevent reinstantiation of iterator variables.
  • Use the included profiler. This feature can be invoked by either including the -r profile argument to the interpreter or adding the require 'profile' directive to your code.
Got your own Rubyisms? Just add them below.

One Language to Rule them All

Will machines think like human beings, or will human beings begin thinking like machines?

This is an interesting question with rather practical implications to a programmer. Although there are certain advantages understanding the low level mechanics of how computers work, I don't think the relationship between that kind of technical knowledge and being able to write a program are necessarily related. No doubt a relationship exists, but I don't think it follows that knowing one automatically leads to the other.

Perhaps an analogy would better explain what I'm getting at. Technical details are like the study of linguistics compared to programs which are like prose/poetry. Knowing linguistics allows you to describe languages and their components such as verbs, nouns, adverbs, the rules of grammatical correctness, etc. This knowledge however doesn't mean that familiarity with these structural elements will automatically allow you to write meaningfully or expressively. These elements provide the constraints of expression when attempting to articulate an idea, but the articulation of the idea lies outside the bounds of this domain of knowledge. This is the same in programming. Although understanding how a computer functions or a compiler works is useful, it does not follow that you can write useful or meaningful programs just as knowing linguistics won't necessarily let you write literature. So what exactly is the nature of the relationship?

At its core, I think that the relationship can be summed up as follows:

Programming, as an endeavor, is still an exercise in expression.

How you choose to express an idea is as important as the idea itself. Like great literature which is firmly rooted in the language chosen by the author, a program acquires this quality of expressiveness based on the language which forms the foundation of a program. Although great writers sometime "break the rules" when writing literature, it is no different than the clever hacks exploited by programmers to express the difference between constraint and convention.

This idea of language as a source the expression implies that certain languages are better suited to expressing different ideas. No one single language is capable of the full range of expression because, at the point of its creation, the range of future expression is completely unknown. It also follows that languages evolve to fill that gap in expression.

So what is it that programmers seek in languages that they choose to solve problems? Quite simply, languages with real longevity possess an expressive quality that is both aesthetic and technical. Although semantics may vary widely between languages, this "expressiveness" is what programmers implicitly recognize and use to build their conceptual framework on which to hang those semantics. For lack of a better word (and borrowing shamelessly from Neal Stephanson and his novel Snowcrash), this is the Ur quality that is the root of all programming languages.

This brings us back to the question at the beginning of this article. Implicitly, expression is still a very human endeavour. Until this changes, I'm inclined to believe that machines will evolve to express very human ideas which will be reflected in the language we choose to express our intentions to them.

I think in this regard, Ruby is a step in the right direction.

Addendum

Beauty Is Truth In Mathematical Intuition: First Empirical Evidence

I found this article a day after writing this tidbit. Interesting how much the aesthetic guides intuition to the truth.

About Ur

This page contains an archive of all entries posted to Z1R0 in the Ur category. They are listed from oldest to newest.

Many more can be found on the main index page or by looking through the archives.

Colophon

Creative Commons License
This weblog is licensed under a Creative Commons License.