Web Development

Five Ruby Hello World greetings

The Hello World program is the most common first example of how to write programs in a new language, even when they don't say Hello World. Five different ways to say hello in Ruby offer a gentle introduction to the language.

Examples of how to write many simple programs that are of little practical use litter the Internet for anyone to find. Among the most common are:

  • a Fibonacci number calculator, because it is the canonical example for recursion.
  • a FizzBuzz solver, because it has become a canonical example of a simple job interview coding question.
  • a Hello World greeter, because it is the canonical example used to introduce a language.

While teaching someone a new programming language in any depth requires a lot of discussion of syntactic forms, semantic design, and "best practices," it usually does not make much sense to the student until he or she gets to see a few examples of source code. This is where the Hello World program comes in: It is usually the first code example presented to a complete beginner, to give the simplest possible example of how the language looks in actual use. More complex examples follow, often involving the addition of more complexity and functionality to the Hello World program until it is nearly unrecognizable as a descendant of that first program.

It is easy to dismiss the Hello World as a meaningless toy, but it serves an important purpose that more experienced developers may forget later in their careers: With a little creativity, such programs can even demonstrate the flexibility and unique qualities of the language to some small extent. For those of you who have never used Ruby, the following Hello World examples in the Ruby programming language may serve that purpose. Each example includes a standard shebang line that tells the OS where to find the Ruby interpreter on a Unix system.

1. The simple example

#!/usr/bin/env ruby

puts 'Hello, world!'

There is not much to this. It consists of a grand total of two tokens -- the puts method and a string datum. Similar languages such as Perl and Python would use print instead. For instance, the same program in Perl might look like this:

#!/usr/bin/env perl

print "Hello, world!\n";

The double quotes and \n newline character are necessary here if you want a newline at the end of the program's output. Ruby has a print method that behaves the same way, but it also offers puts, which conveniently adds the newline character at the end of its output without having to be asked.

2. The input example

#!/usr/bin/env ruby

puts "Hello, #{ARGV[0]}!"

In this case, we are using double quotes for an interpolated string -- that is, a string that is actually parsed for executable code and special characters that should not be taken literally by the Ruby interpreter. Code that you want evaluated before passing the double-quoted string to the puts method can be wrapped in #{ }. In this case, we want the ARGV array -- where Ruby stores input from the command line -- to give us its first element. Because Ruby starts counting array elements at zero, that means we need ARGV[0] evaluated.

If you name this program hello.rb and feed it world as a command line argument when you execute the program, the output will say Hello, world!:

> ./hello.rb world

Hello, world!

3. The array example

#!/usr/bin/env ruby

greeting = ['Hello', ARGV[0]]

puts greeting.join(', ') + '!'

Here, we first create a two-element array and give its second element the value of the first element of the ARGV array so that the user, as in the previous example, can specify the target of a greeting. Next, the join method is passed to the greeting array object, telling it to join its elements together with a comma followed by a single space between any two elements. Finally, it adds (concatenates, in this context) an exclamation point to the end of the string, before the puts method finally attaches a newline to the end and sends the whole string to standard output.

If we run this program on a Monday, with a long, frustrating workweek ahead of us, we might be feeling less charitable than in the previous examples, and call the world something a bit less friendly:

> ./hello.rb 'cruel world'

Hello, cruel world!

This version uses a little unnecessary complexity to achieve the exact same effects as the previous example, but that complexity does demonstrate for us a couple of things:

  • It displays some of the convenient text-processing capabilities of Ruby, including two ways to connect separate strings together into a larger string.
  • It begins to show the object-oriented design of Ruby.

People who know object oriented programming from working with other languages might look at a lot of the code from before this example and wonder why everything in Ruby looks procedural, when it has a reputation as an object-oriented language. Prior to this, one could not tell just by looking at it that objects and methods infested the Ruby source code for a Hello World program. It turns out that puts is a method of the Kernel class, and strings are object instances of the String class. Array objects come with a join method, and while it looks like a procedural infix operator, + is actually being used here as a String object's method. In fact, the last line of this version of the Hello World program can be written like this, more explicitly revealing these methods for what they are:

Kernel.puts( greeting.join(', ').+('!') )

Thank goodness for syntactic sugar; the version that does not use as many parentheses, does not explicitly name the Kernel class, and does not use as much dot-notation for methods was a bit easier on the eyes.

4. The custom method example

#!/usr/bin/env ruby

def greet(target)

return "Hello, #{target}!"

end

puts greet(ARGV[0])

With another bit of unnecessary complexity, this time we have separated the string-building process from the output process by constructing a method called greet. By creating the greet method without explicitly including it in any class definition, we have added it to the Kernel class. As with puts, we do not need to specify the class to which the method belongs. In fact, because greet is a private method of Kernel, it cannot be called like this:

Kernel.puts Kernel.greet(ARGV[0])

Actually, it can in irb (the interactive Ruby interpreter), but with standard executable files, this will not work.

Once again, even when we create a method, we are doing something that could easily be mistaken for using a programming paradigm other than object-oriented programming. In this case, it looks like functional programming, where we have defined a "function" that takes exactly one input, produces exactly one output, and has no side effects. That "function" is then used to provide its output as input for another "function", the puts method. It is only because we know that both of these supposed functions are in fact methods of the Kernel class that we know this is a purely object-oriented exercise.

If you want to develop code in a functional style, you may simply ignore what is going on behind the scenes and write your code in a manner calculated to give the impression it is purely functional, and not object oriented at all.

5. The custom class example

#!/usr/bin/env ruby

class Greeter

def initialize(greeting)

@greeting = greeting

end

def greet(subject)

puts "#{@greeting}, #{subject}!"

end

end

hail = Greeter.new('Well met')

hail.greet(ARGV[0])

farewell = Greeter.new('Goodbye')

farewell.greet(ARGV[1])

Finally, we are getting into the thick of object-oriented programming a little bit. A Greeter class is defined, and its initialize method (which automatically aliases to new) takes an argument for the type of greeting you want an instance of that class to use. Another method, greet, takes a single argument as well -- the subject, or target, of your greeting.

Two separate objects of this class are instantiated with the new method, each of them being assigned to a separate label at the time they are created: hail and farewell. Each object is then sent the greet message with the first and second elements of the ARGV array, respectively, so that the person running the program from the command line can specify who will receive each greeting.

Let us assume that the person running the program gets up happy and optimistic on a Friday morning, looking forward to a quick and painless day of work, followed by a long weekend (Monday will be a holiday for this user). As such, when the user says hello, it is with a smile and a friendly outlook for the world. By the end of the day, however, this user's entire department has been laid off. To top it off, our hapless user has just bought a new, expensive house that he simply cannot afford without that job, and the economy is in the toilet. As such, he has a very emo moment when it comes time to say goodnight.

Given such a turnaround in his day, the program is run thus, complete with a teenage angst filled spelling error:

> ./hello.rb 'fine world' 'crule world'

Well met, fine world!

Goodbye, crule world!

If you become an expert Rubyist, you will hopefully never have the problem of being laid off so suddenly. I also hope that this quick introduction to Ruby gives you an idea of the language's clarity and flexibility.

About

Chad Perrin is an IT consultant, developer, and freelance professional writer. He holds both Microsoft and CompTIA certifications and is a graduate of two IT industry trade schools.

30 comments
TrueDinosaur
TrueDinosaur

DISPLAY "HELLO WORLD" UPON CONSOLE. Sorry, could not help myself. :-)

JackOfAllTech
JackOfAllTech

It doesn't look an different than Perl, Java, or even Basic. Why should I invest any effort to learn another interpreted language?

Sterling chip Camden
Sterling chip Camden

You covered the essential point that makes Ruby special: it's multiparadigmatic (without scaring people off with such big terms). And it's not that Ruby is an OOP language where you can "pretend" its functional, or vice-versa: it actually is an FP-capable language and and OOP language -- it finds a magic place where those two paradigms (and the procedural one as well) not only overlap, but dwell together in harmony.

santeewelding
santeewelding

Thank you, Chad. That was like an early Christmas stocking-stuffer.

Justin James
Justin James

I like this as a way of showing off some Ruby basics. J.Ja

apotheon
apotheon

Was that COBOL? What is wrong with you? Don't you know there are kids looking at this site? You could scar them for life!

Justin James
Justin James

The up front look of a language is irrelevant, they all look just about the same from a brief code sample (other than, say, LISP or APL or a number of goofball languages). Instead, you look at the attributes. * Ruby is natively object oriented, unlike C, Perl or BASIC, and it is real OO, unlike PHP * Ruby fully supports functional programming paradigms; C# is inching in that direction, Python and Perl support a lot of it too, but Ruby really embraces it * Ruby is extremely expressive, unlike Java, C#, BASIC, and VB.NET * Ruby is extremely cross-platform compatible, unlike C# and VB.NET * Ruby supports procedural/imperative programming very nicely, unlike Java, C#, VB.NET If you are familiar with Perl, Ruby will feel like Perl with a lot of the little issues fixed (like hashes of hashes...), and the Perl "do what I mean, not what I say" taken out, but it is still easy to "say what I mean". If you know Python, Ruby will feel similar as well. J.Ja

bergenfx
bergenfx

satisfy the same characterization. It's been awhile since I looked at the language, but it seems the same could be said, (more of a question than an assertion). And then CLOS, flavors, SCOOPS (had to mention because I liked the play on flavors), halo scheme all seemed to accomplish, at least, the appearance of the "multi-paradigmatic" quality you ascribed to Ruby. Regardless, I liked the way you characterized it.

apotheon
apotheon

It seemed like a good approach.

AnsuGisalas
AnsuGisalas

Do it in fortran! I actually used to know a tiny bit of fortran... long lost to biological unlearning, I'm afraid. Basic too, even further back. And Pascal, as I recall. BTW; in finnish Pascal would mean "taking a dump" ;)

JackOfAllTech
JackOfAllTech

In that case, I'll stick with AutoIt which does everything you mentioned except cross-platform which I'm not interested in.

Jaqui
Jaqui

"Perl "do what I mean, not what I say" taken out" is Perl will do what you intended with your code, not what you typoed in, then isn't that a good thing? ;)

apotheon
apotheon

Python has some constructs that are specifically not object oriented, and it's a bit more difficult to write in a style that is solely functional or object oriented than in Ruby. The Python design philosophy seems to be that some things are just better in an FP style, others in an OOP style, and you should use each style for each set of tasks even if that means mixing them together in a single program, or embedding some of one style inside something of another style. Ruby's approach is more that sometimes you should use one approach or the other, and it gives you the option of using either depending on your own estimation of what is more appropriate at a given time. This difference between the languages' multiparadigmatic designs is largely chalked up to the fact that in Python there is a distinct difference between "functions", "objects", "methods", and certain types of "primitives", while in Ruby basically everything is an object or a method (except for a few keywords and the like that act something like punctuation). Ruby's objects and methods act like primitive tokens in functional programming languages if you want them to; Python's objects and methods mostly just act like objects and methods, and its non-OOP functions are not easily mistaken for either objects or methods. At least, that's my perspective on it. I suppose your mileage may vary.

Justin James
Justin James

From what I can tell (as someone who has read a ton about both, but not used either), Python is very similar to Ruby in the characterization. It has a lot of low level differences, from what I understand. J.Ja

Justin James
Justin James

I need to really spend some time working with Ruby. I've got a Web service written in C# that works just fine, but now that I saw the price of a Linux AWS instance compared to Windows, I am motivated to re-write it in Ruby, providing that Ruby's multithreading support can handle what I am doing. It's all algorithmic (zero local or DB storage), so the expressiveness of Ruby will be a big help. J.Ja

Sterling chip Camden
Sterling chip Camden

@bergenfx: yes, Algol68 was great -- there's now a port of it available for FreeBSD! @Justin: I don't think so, since I never attended a programming class. I taught myself these languages on my own time, and the order was based on demand. BASIC because I wanted to tweak the operation of some games, COBOL because the department wanted me to write an inventory program, Algol because that was the system programming language in Data General's AOS, assembler likewise, Fortran to port two projects from Stanford and Tektronix, DIBOL for a job, C when I first encountered Unix, etc.

Justin James
Justin James

BASIC was my first language, followed by COBOL, then EdScheme and next Pascal... :) J.Ja

bergenfx
bergenfx

that redeemed you. It influenced a whole generation of programming languages, and Algol68 may have bettered any of its derivative languages. Burroughs made an Algol machine, (way ahead of its time) ... stack architecture, no rendering down to assembler code. Of course, they were squashed by IBM and the attachment to and inertia of COBOL, fortran and PL/1. Our industry seems to continually make the wrong decisions. After that, Simula completely ignored, and then it was Ada over Modula-2, (while neither seemed to gain that much traction), and worse -- much, much worse -- C++ over Objective-C, an almost ridiculous and sublime comparison there. My first, fortran. Third a few short months later? Scheme. From brain damage to consciousness expansion.

Sterling chip Camden
Sterling chip Camden

I learned BASIC first, then COBOL. Then Algol, Assembler, Fortran, PL/1, DIBOL, C, C++, Pascal, ... ... Java, Perl, Visual Basic, C#, ... ... Ruby, JavaScript, Lisp, Python, Haskell... we'll see what comes next.

apotheon
apotheon

I've heard it said that people who first learned programming via BASIC are permanently brain damaged. There's at least a little truth in that -- and BASIC isn't the only such language. COBOL and anything that necessarily starts with Visual seem to be in the same boat. Luckily, the damage to my gray matter was quickly offset by being introduced to Logo and C shortly after BASIC.

AnsuGisalas
AnsuGisalas

Roses and embellishments! :D And user's choice of fonts!!! ]:)

Neon Samurai
Neon Samurai

Logo, Basic/Qbasic, Turing.. I used to rock those bad boys, each in there own time,.. long since lost them to natural memory loss. Offhand, is there a support group for people getting over VB/VC .net syntax and IDE? I've already got step one coveres; Hi, My name's NS.. and I have a problem..

Sterling chip Camden
Sterling chip Camden

PRINT *,"Hello World!" END (Make sure you indent that right). Of course, if you want to grab command line arguments and build/join an array, you're going to need a lot more code.

apotheon
apotheon

AutoIt doesn't look as expressive to me as Ruby -- and it does not appear to have quite so intimate a relationship with object oriented design as Ruby has, either. AutoIt doesn't look like it supports functional paradigm programming very smoothly. In fact, AutoIt looks like a domain-specific variant of VB, which is far from an elegant, pleasant language to use, in my experience. I suppose your mileage may vary.

Sterling chip Camden
Sterling chip Camden

It's that it's much easier for you to type what you meant instead of something else that's very close to it syntactically but horribly wrong semantically.

Jaqui
Jaqui

but the do what I mean not what I said" is the description of a perfect programming language, it knows what you were thinking. :D hmm, Perl is a full A.I. then ;)

Justin James
Justin James

... until you go to debug, and all you see is what you wrong, and have no recollection of what odd thoughts were going through your mind 6 months earlier. :D Besides, Larry Wall never showed up at my house with a pepperoni pizza and a Corvette when I ran my code. So "do what I mean" isn't really "do what I want" anyways! J.Ja

Sterling chip Camden
Sterling chip Camden

Both Python and Ruby allow you to mix paradigms, but in Ruby there's more of a basic concurrency of both paradigms, as far as I can tell. Bergenfx mentioned some Lisp object systems. I only have experience with CLOS, which does a fantastic job of combining functional and OOP. Actually, it makes objects an outgrowth of functional programming, which means that it doesn't have quite the same feeling of "everything's an object" that you get with Ruby.

apotheon
apotheon

There's a Ruby-like language currently in development called Reia. It's not production ready yet, but it looks like it will be quite good for multithreaded concurrency when it's ready for prime time. Erlang is about as good as it gets for concurrent programming at the moment (though Reia is being built on top of Erlang, so it will hopefully be as good for such purposes). Ruby 1.9 is supposed to have good threading support, but Ruby 1.8.x is a bit deficient in that area, with support only for "green" threads rather than OS native threads. Since I haven't really worked with 1.9, nor much with threaded development anyway, you'll have to judge that for yourself, I suppose (as I mentioned in an email to you).

Neon Samurai
Neon Samurai

There are one or two changes I'd like to see in metasploit. Eventually, I'm also going to run out of things to learn from the superficial user level and want to understand how the modules work. This'll be going on the top of my ruby pile for the introduction step also.

Editor's Picks