The beauty of Ruby through examples

Hey all,

I’m about to introduce Ruby to a group of people that is not familiar to
the
language, and the approach i’d like to take is simply by distilling out
a few
sample codes. I’ve been collecting some from around the internet, but
i’d
appreciate your suggestions as well.

I’m looking for code snippets that represent some of the beauty of Ruby
actually, such as:

Simplicity

Expressiveness

Productivity

Flexibility

Dynamism

Freedom

Happiness

Just to clear things up, here are few examples:

Simplicity

vowels = %w(a e i o u)
alfabet = (‘a’…‘z’).to_a
cons = alfabet - vowels
p cons

Expressiveness

hello = ‘Hello Ruby’
5.times { puts hello }

Productivity

class Person

def name

@name

end

def name=(other)

@name = other

end

def age

@age

end

def age=(other)

@age = other

end

attr_accessor :name, :age
end

john = Person.new
john.name = ‘John’
john.age = 25
p john

Flexibility

class Array
def pick
self[rand(self.size)]
end

alias :choose :pick
end

puts %w(1 2 3 4 5).pick
puts %w(1 2 3 4 5).choose

Dynamism

Padawan = Class.new

class Jedi
def train(padawan)
def padawan.control_the_force
puts “Now i’m ready to become a Jedi!”
end
end
end

skywalker = Padawan.new
yoda = Jedi.new
p skywalker.respond_to? :control_the_force # => false

yoda.train skywalker
p skywalker.respond_to? :control_the_force # => true
skywalker.control_the_force# => Now i’m ready to become a Jedi!

…and so on.

Any more examples?

Thanks in advance,

Adriano

I take it rand() gets pseudorandom numbers from computer and as such
could be improved in one respect at least if ruby can be made to sleep
or wait for random numbers of milliseconds. One complication with
random number generation is that two numbers can come off the belt in
the same millisecond. However making ruby wait a random number of
milliseconds between each sample draw sample draw is the random numbers
to provide the user would solve that problem. I just found the Pickaxe
book the other day and am reading through it and learning. The thing I
don’t know is how much solving this problem with pseudorandom numbers
would improve quality of samples.

Adriano F. wrote:

Any more examples?

For wow factor, I think you can’t beat a 4-line webserver written in
Sinatra.

require ‘sinatra’
get ‘/’ do
‘Hello, world!’
end

On Sep 29, 2010, at 9:07 PM, Brian C. wrote:

For wow factor, I think you can’t beat a 4-line webserver written in
Sinatra.

What about a one-line HTTP server written in Lua? :stuck_out_tongue:

HTTP[ ‘/’ ] = function() return ‘Hello world’ end TCPServer(
‘127.0.0.1’, 1080 )( HTTP )

F. Senault wrote:

end
It’s worth mentioning this, too:

puts grep -i ruby script.rb

I guess you should show irb explicitly.

Another thing worth pointing out: the Ruby source tarball is about 1/3
of the size of Perl, but you get a whole load more libraries by default:
openssl, https, md5/sha1 digests, readline, tk, dbm, …

On Thu, Sep 30, 2010 at 3:30 AM, Petite A.
[email protected] wrote:

What about a one-line HTTP server written in Lua? :stuck_out_tongue:

HTTP[ ‘/’ ] = function() return ‘Hello world’ end TCPServer( ‘127.0.0.1’, 1080 )( HTTP )

yes, it’s a one-liner, but, you’ll have to read it many times…
cheers -botp

Le 29 septembre 2010 à 20:40, Adriano F. a écrit :

Hi.

I’m about to introduce Ruby to a group of people that is not familiar to the
language, and the approach i’d like to take is simply by distilling out a few
sample codes. I’ve been collecting some from around the internet, but i’d
appreciate your suggestions as well.

In a presentation I made sometime ago, I used these at the beginning :

File.open(“script.rb”) do |fichier|
fichier.each do |ligne|
if ligne.downcase.include? “ruby”
puts ligne
end
end
end

File.open(“script.rb”) do |f|
f.each { |l| puts l if l=~/ruby/i }
end

The Lottery here is 7 out of 36 balls.

(1…36).sort_by { rand }.slice(0,7).join(', ')

fct1 = lambda { |v| v.split(/ /).
collect { |z| z.capitalize }.join(’ ‘) }
fct2 = lambda { |v| v.split(//).
collect { |c| c.ord }.join(’,') }

fct1.call(“this is a nice string.”)
fct2.call(“this is another nice string.”)

require “open-uri”
open(‘http://www.google.com/’) { |f| puts f.read }

HTH,

Fred

Le 29 septembre à 21:50, Joel VanderWerf a écrit :

f.each { |l| puts l if l=~/ruby/i }
end

It’s worth mentioning this, too:

puts grep -i ruby script.rb

Yep, nice addition !

Fred

Le 29 septembre à 21:26, F. Senault a écrit :

And I forgot a simple, classic, one :

def factorial(n)
(1…n).inject(1) { |p, f| p * f }
end

def factorial(n)
(1…n).inject(1, :*)
end

(I don’t like much the second one, it’s a bit less legible.)

Fred

On Thu, Sep 30, 2010 at 9:35 AM, F. Senault [email protected] wrote:

end

(I don’t like much the second one, it’s a bit less legible.)
You see, that depends, it is more readanble to me. Probably totally
depends on the context.
For folks coming from functional languages the simple fact of using
inject’s synonym might also add to readability

(1…n).reduce 1, :*

In conclusion I prefer naming things, but the downside is that one has
to communicate names and agree about them. The explicit code block
does not have that disadvantage. However it does not trigger the
information in the brain as quickly as names do, once they are
understood.
This might indeed be one of the forces and beauties of Ruby and it
might be a good idea for OP to show that to his audience.

Cheers
Robert

On Thu, Sep 30, 2010 at 3:35 PM, F. Senault [email protected] wrote:

def factorial(n)
(1…n).inject(1, :*)
end
(I don’t like much the second one, it’s a bit less legible.)

lose the 1.
on my case, i do like the second very much. more idiomatic. less prone
to typo. less to think (convention ie).

i am referring of course, not to the factorial, but of the idiom,

enum.inject :operator
enum.inject factor, :operator

eg,

multiplying

(1…5).inject :*
=> 120
(2…5).inject :*
=> 120
(3…5).inject :*
=> 60

adding

(4…5).inject( :+ )
=> 9

multiply w factor

(3…5).inject 5, :*
=> 300

adding w initial,

(4…5).inject( 100, :+ )
=> 109

powers,

(2…3).inject :**
=> 8

(2…4).inject :**
=> 4096

and more fun using blocks…

best regards -botp

On 30 September 2010 10:32, botp [email protected] wrote:

On Thu, Sep 30, 2010 at 3:35 PM, F. Senault [email protected] wrote:

def factorial(n)
(1…n).inject(1, :*)
end
(I don’t like much the second one, it’s a bit less legible.)

lose the 1.

-botp

Except if you want factorial of 0 to be right.

While showing a cool example, I would go to:

class Integer
def !
(1…self).inject 1, :*
end
end

0.! # => 1

On Thu, Sep 30, 2010 at 4:58 PM, Benoit D. [email protected]
wrote:

Except if you want factorial of 0 to be right.

my bad. i must review my math now :slight_smile:
best regards -botp

def printTree(tree,indent)
if (Array === tree)
tree.map { |child| printTree(child,indent+"| “) }
else
puts(indent.gsub(/\s+$/,”–")+tree.to_s)
end
end
printTree([1,2,[11,22,[111,222,333,444],33],3,4],"")

this give :
|–1
|–2
| |–11
| |–22
| | |–111
| | |–222
| | |–333
| | |–444
| |–33
|–3
|–4

On 09/30/2010 07:48 AM, Regis d’Aubarede wrote:

def printTree(tree,indent)
if (Array === tree)
tree.map { |child| printTree(child,indent+"| “) }
else
puts(indent.gsub(/\s+$/,”–")+tree.to_s)
end
end
printTree([1,2,[11,22,[111,222,333,444],33],3,4],"")

IMO this is more idiomatic:

class Object
def recursive_print indent = “”
puts indent.gsub(/\s+$/,"–") + to_s
end
end

module Enumerable
def recursive_print indent = “”
map { |child| child.recursive_print indent+"| " }
end
end

[1,2,[11,22,[111,222,333,444],33],3,4].recursive_print

How about some more simple ones like

'Do Re Mi Fa So La Ti ’ * 3

[125, 450, 250, 1000, 675].sort.reverse.collect{|e| “$#{e}”}.take(3)

’ hello there '.strip.center(30, ‘-’)

Threading is light in ruby, so here a try show works in paralleles :

require ‘thread’
require ‘socket’
require ‘timeout’

############### Send a file by socket to www server

def send_file(hostname,filename)
timeout(3+File.size(filename)/10000) { # timeout, in seconds
socket=TCPSocket.open(hostname,80)
socket.write( “POST /upload/#{filename} HTTP/1.1\r\n\r\nContent=” )
socket.write( IO.read(filename) )
print “\n#{filename} transfered”
}
rescue Exception => ex
puts “ERROR on transfert #{filename} to {hostname} : #{ex}”
ensure
socket.close rescue nil # anyway, try to close
end

################### MAIN : send *.rb in //

threads= Dir["*.rb"].map do |file|
sleep(0.1) while Thread.list.size>20
Thread.new { send_file(ARGV[0],file) }
end
threads.each {|thread| thread.join} # wait all finish before exit

end

skywalker = Padawan.new
yoda = Jedi.new
p skywalker.respond_to? :control_the_force # => false

yoda.train skywalker
p skywalker.respond_to? :control_the_force # => true
skywalker.control_the_force# => Now i’m ready to become a Jedi!

Wow, these are fantastic, especially this last one. I don’t know if
this syntax (def padawan.control_the_force) has always been available
but I have long been doing that in a much more complicated way.

Please post your full list or your slides when you are finished! So
often people ask me “what’s so great about Ruby” and I can’t put it
into just a few sentences!

On Sep 29, 1:40 pm, Adriano F. [email protected] wrote:

actually, such as:

5.times { puts hello }

end

end
self[rand(self.size)]
Padawan = Class.new
yoda = Jedi.new
Thanks in advance,

Adriano

In comp.lang.lisp, this elisp code was posted as an example
of how to shuffle a vector:

(defun emms-shuffle-vector (vector)
“Shuffle VECTOR.”
(let ((i (- (length vector) 1)))
(while (>= i 0)
(let* ((r (random (1+ i)))
(old (aref vector r)))
(aset vector r (aref vector i))
(aset vector i old))
(setq i (- i 1))))
vector)

Ruby:

(9…20).sort_by{ rand }
==>[15, 14, 12, 18, 16, 10, 9, 13, 11, 20, 17, 19]