Variable Scope in Ruby

Resolving a name to either a local variable or method

What happens when you refer to a name which is not yet defined ?

 square_of_sum
 => NameError: undefined local variable or method 'square_of_sum'

 defined? square_of_sum
 => nil

There are two things which I found surprising about defined?.

At first, I expected it to be a method, while it turned out to be an operator. Then on seeing the ? suffix, I expected a boolean response. Which is a common ruby convention. But then defined? is an operator.


defined? 11
=> "expression"

defined? Math::PI
=> "constant"

defined? $_
=> "global-variable"

defined? sum = 1 + 2 + 3 + 4
=> "assignment"

product = 1 * 2 * 3 * 4
defined? product
=> "local-variable"

defined? "never odd or even".reverse
=> "method"

But what about nil itself ?


defined? nil
=> "nil"

Notice that the output is the String “nil”. At this point, except for square_of_sum everything else has been defined.

if false
  square_of_sum = sum * sum
end
=> nil

square_of_sum
=> nil

defined? square_of_sum
=> "local-variable"

Very Interesting! The value of square_of_sum has become nil. We see no NameError like earlier and the square_of_sum is defined as a local-variable.

An expression whose value is nil, is still defined.

But if the assignment will never be executed, how is that square_of_sum is defined ?

You just witnessed lexical scoping in action. Ruby creates the references to variables in code during the compilation step and not during code execution. It sees the assignment and defines square_of_sum as a local-variable.

Resolving a name to variable is independent of the run time call stack and requires only knowledge of the static program source code.

Let us define a lambda which computes the cube of x.

cube = -> { x * x * x }

cube.call
=> NameError: undefined local variable or method 'x'

This looks familiar. We have not yet defined x. Let us define x and try again.

x = 9

cube.call
=> NameError: undefined local variable or method 'x'

The same old error. But isn’t x defined ?

defined? x
=> "local-variable"

Ruby is lexically scoped. When cube lambda was defined, x was undefined. So x is definitely not a local variable. If x was not defined as a local variable then is it a method ? Let us define x as a method which returns the value 9.

def x
  9
end

cube.call
=> 729

This time when we call the lambda it works, which is significant.

In the lexical scope of the lambda cube, the name x is not defined as a local variable. Ruby then makes the distinction that the name x must resolve to a method.

Let us define another variable y and a new lambda for computing cube of y.

y = 11

new_cube = -> { y * y * y }

new_cube.call
=> 1331

This works as expected because when new_cube is defined y is already defined as a local-variable.

Sources

  1. The defined? operator
  2. Ruby Forum: Lexical vs Dynamic Scope
  3. Ruby Forum: Undefined local variable ?
  4. Understanding defined? in lexical scope
  5. Ruby variable scope tutorial

CodeJam 2011 – The Finale

We have finally dropped the curtain on the MobME CodeJam 2011; after 2 weeks of interesting problems and a grand finale at our Kochi office. We finally have a winner – Karthik R; who walks away with the grand prize of Rs 100,000. It was indeed tough to pick one winner from the 200 odd entries we had recieved. But in the end; Karthik had his nose just ahead with the way he approached the problem and how he went about designing the solution. Congrats to him for making it through all these rounds, amidst the tough competition.

And for making that choice tough; the kudos goes not just to the winner and the 12 finalists; but also for every single one of you who participated. We enjoyed reading through all your code. What more can techies like us ask for? :)

What impressed us the most was how people came up with elegant solutions to some tough problems. As explained by Vishnu in an earlier post we had intentionally given all our daily problems vague edges. The reasoning behind that was to see how the participants coped with real world engineering requirements that are often vague high-level statements. This made some of the submissions quite interesting to us – to see how people approached the question in different ways. A succesful engineer is someone who can do the same; and I’m happy to say that the current crop of young engineers seem ok. We are in safe hands!

What I probably didn’t like so much about most of the entries in general was the lack of quality documentation and the lack of automated tests. In college, students are still taught on how to write programs for machines. In an enterprise what’s needed is the ability to write code for other human beings. That’s a skill that requires some training and experience; but I am a firm believer that the first steps must be taught during the formative years of an engineer.

Let’s get into some statistics then. We recieved a total of 259 valid submissions over the 14 days. The highest number of submissions were for the first day for which we got around 30 solutions. The language of choice for the participants seemed was Python. Python also took away the crown most number of daily winners. PHP was a distant second; followed closely by Java and Ruby. C had even fewer submissions and we got no submissions written in Clojure.

The CodeJam Language Pie

The CodeJam Language Pie

All said and done; it was a wonderful experience for the team here at MobME to construct all those questions, read the solutions and finally to meet some of the young breed here. We ourselves learnt a lot in the whole process. So on behalf of Nanda, Sherin, Vishnu and the rest of the team in MobME – Thank you for participating and keep coding!

Anoop SankarAnoop Sankar is VP, Engineering at MobME Wireless Solutions. He serves as a key interface between engineering and management, responsible for developing strategic planning for direction and control of engineering activities.

Anoop is an engineering graduate from Trivandrum. Prior to working at MobME he served as a software engineer at Robert Bosch working on automotive technology.

MobME Code Jam and the Craft of Programming

I’ve always been of the strong opinion that we don’t write programs just for computers to understand: we write them for other programmers too, the ones who come after us, who maintain the code that we chug out, but also the ones who read our programs to understand how to approach a problem, how to design reusable components or perhaps even how to frame thoughts about a problem domain. Programmers are craftsmen: the good ones amongst us are artisans and the best of us are artists.

This is why I’m amazed at how much emphasis programming contests place on the correctness of a program or its time and space complexity (for the non-programmers amongst us, this is how long it takes to run and how much memory it uses). Are these the only measure of a good program that contests can evaluate? While framing questions for MobME CodeJam, we wanted to test out the other bits of what makes a good programmer too: how fast your program runs and how much memory it uses are important, yes, but there are several other criteria that we think deserves more merit.

Again, this is an area where we differ strongly from other contests. Let’s compare with Google’s Code Jam (whose name we unabashedly borrowed):

  1. Questions are strictly timebound.
  2. Questions are algorithmic.
  3. A clear input and output format is provided.
  4. A computer looks at your program correctness.

In contrast, for MobME Code Jam:

  1. The time available is a relaxed 24 hours to solve a single question. Having done questions of these nature ourselves, we estimate that it would take a good programmer just about 2 or 3 hours to correctly compute a question.
  2. Questions are exploratory.
  3. We leave it to the programmer to design and describe input and output formats.
  4. A human looks at your program correctness and clarity.

So why these differences? What are we trying to gauge here? To describe this, I’ve worked on a solution for our sample question (title “hollywood”):

Write a program that ranks Hollywood actors based on the number of their appearances in a list of top 100 top movies. There are a number of top movie lists on the Internet and it’s up to you to choose one. We prefer you choose one that has an open API.

So you have to:

  1. program a correct solution within 24 hours.
  2. explore and find out an open API.
  3. design a clear and efficient solution, and,
  4. write a program that we can understand (because we have to figure out how well it works)

The codejam-hollywood-mobme repository illustrates what we consider a good solution to the problem. The code is idiomatic ruby, is well tested, has clear generated documentation as well as a concise README and defined RESULT, and runs reasonably fast.

Let’s go over that again. So at MobME, what we prioritise are these things in order:

Code is Idiomatic

A programming language has a definite well-defined syntax that its compiler or interpreter understands. The language also however has lots of conventions, evolved (and often changing) over the course of time that most programmers who use the language adopt. We consider adopting these the first test of a well-written program. This doesn’t in any way constraint your originality, but it provides a strong structure for framing your solution.

In my hollywood solution for e.g., a lot of such conventions are followed that are adopted from the parent language (Ruby):

For naming:

  1. Underscores separate variable_names and file_names.
  2. Classes are CamelCased.
  3. Constants are ALL_UPPERCASE.

For documentation:

  1. There are inline comments in code.
  2. A clear README is provided.
  3. Rdoc is used

For writing code “the Ruby way”:

  1. Using a functional construct inject instead of less elegant methods for a custom sort.
  2. Using Ruby modules for namespacing.
  3. Code folder structure: all code in lib/, all documentation in doc/ and all tests (or rather, specifications) in spec/

Do note that these conventions are different for every language. This is why we allow people to submit multiple solutions in several different languages: writing one in Ruby for example lets a programmer explore a completely different approach that writing a solution in Java.

Code should be Well Tested

Having good test coverage and writing testable code is a fundamental need. The virtues of writing tests have been covered extensively in several other places, so I’m not going to go over them again. We encourage people to program using TDD, but any tests are better than none, and it’s up to you how to write them.

In my Ruby solution, we use RSpec for doing TDD. Do note all the specs available in spec/. Let’s take an example:

And the beginnings of the corresponding code:

Read up on BDD for more, but please be aware: do test the behaviour, not your implementation and mock away all your dependencies. Assume your libraries work: we’re only interested in the code you write yourself.

Code should be Well Documented

Good programmers document their code well. Great ones write self documenting code. This means choosing good variable and function names, styling your program flow into small, composable (and easily understandable) functions, and writing comments when necessary. Useful comments are those that add meaning and structure to your composition. If you are an author, you would think of them as footnotes: nobody wants to read a story full of them, but for dense material, it sometimes helps to have them around.

In our Ruby example, we have:

  1. Good documented code
  2. Small functions composed to form the solution. (There are places where this can be improved.)
  3. Generated documentation from our code comments.

Code should be Efficient

Note that this is our last evaluation criteria. We would definitely like your code to be efficient—in both time and space utilisation. We would love it if it runs like a whiz-bang rocket. But if your corresponding code is horribly written and not understandable, you will not win our Code Jam.

I initially developed our Ruby solution in Ruby 1.9.2. Ruby is a slow language, not known for its terribly efficient computation or speed. 1.9 does make it better, but my program does run faster by leveraging another Ruby implementation: JRuby 1.6.2 runs on the JVM and can be as fast as Java, but more importantly for this particular problem, has real native threads that allow you to parallelise the dozens of API calls that need to be made.

Because it’s an elegant language, and because you’ve written code in a modularised way, you end up with an addition of 6 lines of code to make your program considerably faster. And of course, since we have good test coverage, it’s easy to find regressions.

In Short

For MobME Code Jam, we value code that is clear and concise, idiomatic, well tested and documented and finally, efficient. I hope this clears up a lot of questions we have been getting about how to submit answers for Code Jam. We realise it’s not the usual run-of-the-mill programming contest, but do give it a try. Programming while keeping just efficiency in mind is so terribly single dimensional. Do not constrain your creativity, come up with solutions that are worthy of a true artist.

Vishnu Gopal is CTO, MobME Wireless Solutions Pvt. Ltd. He leads MobME’s vibrant and growing engineering division from Kochi, Kerala.

Vishnu is an engineering graduate and has worked in startups all his life. MobME is his most recent venture after stints at SlideShare Inc. and a course in HCI from UCLIC, London.

Who We Are and What We Do

A warm welcome to our MobME Engineering blog. We’re the engineering brains behind MobME Wireless Solutions and we are pretty passionate about the craft of programming, design, all things geeky and squishing all bugs great and small.

We’re a small team and this is how we’re organised right now:

As you can see, we are a very small team with the bulk of our personnel spread out in a horizontal division that deals with development and operations—DevOps—that is spread across the company. DevOps also does our most exciting infrastructure work—we’re the first engineering team in India to start work on our own cloud infrastructure.

Enterprise is our division that makes custom developed products and solutions for the eGovernance and mGovernance sector in India. We have two products in here: Fast Alerts—our oldest product—is a bulk SMS solution and its counterpart Bulk Voice is an IVR and OBD solution for Enterprise customers. We also have two service delivery platforms: Kerala 537252 and Goa 56468 that are co-developed with these state governments.

VAS is our mobile Value-Added-Services division that develops applications for telecom operators. This is our most successful division and we have four vibrant products here: Airtel Picture Post, which is a photo news service on Airtel, its counterpart Vodafone Photo Alerts, Airtel IndiaTweets which is a Twitter service on SMS and Cricket on Demand—a simple SMS service for Cricket Alerts.

NetSol is one of our oldest divisions and it makes core telephony solutions for mobile operators. We make a very intelligent SMS centre—ZULO—that increases delivery percentages for campaigns quite a lot, an integrated promotion engine called Campaign Manager, OBD and IVR solutions based out of mobile operator data centres and our most recent offering: solutions for Mobile Number Portability.

Except for a few of us who oversee everything, everybody who works in MobME Engineering works in one of these four exciting divisions. And we’re hiring talented people across the board. If you’ve got an interest in programming, do send your resume in.

Coming up next instalment: the programming languages and software that we use to build applications at MobME.

Vishnu Gopal is CTO, MobME Wireless Solutions Pvt. Ltd. He leads MobME’s vibrant and growing engineering division from Kochi, Kerala.

Vishnu is an engineering graduate and has worked in startups all his life. MobME is his most recent venture after stints at SlideShare Inc. and a course in HCI from UCLIC, London.