Tuesday, March 29, 2011

Two ways to simplify Array blocks in Ruby

1. If you have a block of the form { |v| v.mtd }:

ary.each { |v| v.mtd }          # normal way
ary.each(&:mtd)                 # simpler way

# Example:
ary = %w(abc def ghi jkl)
ary.each(&:upcase!)             # same as ary.each { |v| v.upcase! }

That works for other Array methods, like map. More on it.

2. If you have a block of the form { |v| mtd v }, and the method mtd does the same thing with all parameters:
ary.each { |v| mtd v }          # normal way
mtd *ary                        # simpler way

#Example:
ary = %w(abc def ghi jkl)
puts *ary                       # same as ary.each { |v| puts v }

See more on it.

Monday, March 28, 2011

Why Ruby has rand(x) instead of x.rand

When I was choosing a new language to work with after PHP, I was considering Python and Ruby. Both claim to be pure object-oriented languages, but some argue that Ruby is "more" OO because Python has things like abs(-3), which in Ruby is -3.abs (ie, it makes more sense if abs is a method of numeric objects).

However, recently I was faced with rand(1000). "Gosh! Wouldn't it be 1000.rand?! Why Ruby could be so 'not-OO'?"

After thinking for a while and read the rand documentation, it becames clear to me that the original purpose of rand is to give us a (pseudo) random float number between 0 and 1. And that isn't a numeric method; there's no sense in saying 693.rand to get a random number between 0 and 1. So it was implemented in module Kernel, like a procedural function accessible anywhere. Then, to increase the usability of rand, they decided to take an optional parameter to return a random number between 0 and it, if it is supplied. IMHO, that's why Ruby has rand(x) instead of x.rand.

Anyway, you can easily implement x.rand in Integer class. ;-)

Sunday, March 27, 2011

Class Variable to increment Fixnum objects

Anyone who starts to play with Ruby Metaprogramming soon is faced with the Fixnum increment problem.

Fixnum has no pre/post self-increment/decrement operator/method.

Some nice day I innocently tried to do i.succ!, guessing "that obviously exists". I was surprised when I got an error. Well, I thought, in Ruby it's simple: it's just to code:

class Fixnum
  def succ!
    self.replace succ
  end
end

(I'd to use self.replace in String class recently.)

Then I was shocked: replace is not an Object method; it's a String (and some other classes') method, and it's not available to Fixnum (and some other classes).

But then, "how can we (or anyone) implement such methods into Fixnum?" A powerful language like Ruby could not be that restricted!

Since we see many magic codes using Ruby Metaprogramming, I was decided to find a way.

As I was learning Ruby, I understood that if Ruby hasn't something, you can implement it. E.g.: Ruby has not the "with" keyword, like Pascal. That's not a problem, as you can implement it. So I thought there would be a way to do a self-increment method for Ruby integers.

It isn't really necessary, since we can use i += 1. But then I had adopted the challenge. Now I wouldn't stop anymore. Oh, no!...

One argument for not having the ++ operator in Ruby is: a symbol refers directly to the object, and not to the variable which contains the object. So, if i is 1, trying to do i++ is the same as trying to do 1++, which would turn the value of the number 1 into 2, and 1 woudn't be 1 anymore.

Personally I don't agree with that argument, because you can do "i += 1" and you can't do "1 += 1"; so, I think would be possible to do "i++" not being the same as doing "1++". Anyway I agree with other arguments, like: it's not the Ruby way to code; it can obfuscate the code; it can cause confusion about what is going on in codes like "a[++i] = i++" etc.

I tried many things. The first try that worked was a lambda method to increment a variable through its symbol:

inc = lambda do |x|
  eval "#{x} += 1"
end

a = 5

inc[:a]

puts a       # => 6

(I'd tried "def inc" to do the same in main:Object and in class Symbol, but inside a "def" eval can't access external variables.)

But that is not like doing "a.inc". So I went on, and on, and on, and some other nice day I finnaly got it! And so I decided to create this blog! (Yes: this post is the reason for which I created this blog!) I used a class which I named "Variable", because it contains the object instead of being the object itself. Here's it:

class Variable

  def initialize value = nil
    @value = value
  end

  attr_accessor :value

  def method_missing *args, &blk
    @value.send(*args, &blk)
  end

  def to_s
    @value.to_s
  end

  # here's the increment/decrement part
  def inc x = 1
    @value += x
  end

  def dec x = 1
    @value -= x
  end

  # pre-increment ".+" when x not present
  def +(x = nil)
    x ? @value + x : @value += 1
  end

  def -(x = nil)
    x ? @value - x : @value -= 1
  end
end

a = Variable.new 5

# normal + operator
puts a + 3           # => 8
puts a               # => 5
puts a.inc 2         # => 7
puts a               # => 7
puts a.dec           # => 6
puts a.dec           # => 5

# pre-increment + operator,
# (for those who doesn't like to type "inc")
puts a.+ * 2         # => 12: a turns into 6, which is doubled
puts a               # => 6
puts a.value.class   # => Fixnum

# puts a while a goes to zero
puts a while a.-> 0

(About the last line, see more on "goes to" operator. :)

I think it's not soooo useful, but if you can do something interesting with it, please tell me! :)

After doing that, I found an elegant way to do similar behavior by using delegation.

Enjoy!

Friday, March 25, 2011

How to make a class method private

If you want to make a class method private, you must put the private keyword inside the class << self section:

This works:
class Test
  class << self
    private

    def foo
      puts "bar"
    end
  end

  foo         #=> "bar"
end

Test.foo      #=> NoMethodError: 'foo' is a private method;
              #   That's we want!

This works, too:
class Test
  class << self
    def foo
      puts "bar"
    end

    private :foo
  end

  foo         #=> "bar"
end

Test.foo      #=> NoMethodError

And this:
class Test
  def self.foo
    puts "bar"
  end

  class << self
    private :foo
  end

  foo         #=> "bar"
end

Test.foo      #=> NoMethodError

Putting the private outside class << self doesn't work:
class Test
  def self.foo
    puts "bar"
  end

  private self.:foo     #=> Syntax error: unexpected tSYMBEG
  private :self.foo     #=> Error: undefined method "foo" for :self
  private :"self.foo"   #=> Error: undefined method "self.foo" for Test
end

And the following tests won't work, too:
class Test
  class << self
    private
  end      # by closing this block, the scope of "private" is also closed,
           # even if we reopen the block right next:

  class << self
    def foo
      puts "bar"
    end
  end

  foo         #=> "bar"
end

Test.foo      #=> "bar"

class Test
  class << self
    private
  end

  def self.foo
    puts "bar"
  end

  foo         #=> "bar"
end

Test.foo      #=> "bar"

Thursday, March 24, 2011

Ruby autoload like in PHP

(Disclaimer: this is a translation from Autoload do Ruby como no PHP, in Portuguese.)

Who has worked with OOP in PHP and starts to learn Ruby soon will miss the PHP __autoload.

In fact, Ruby has autoload, but it seems useless for a PHP programmer.

In Ruby, the autoload is for using less memory, leaving files to be loaded only when necessary. But then you need to type more than a simple require; besides specifying the filename, you need also type the constants (classnames) which are in the file. For example:

autoload :MyClass, "myclass.rb"

I guess the computers was made to help the people, and that includes the programmer. From the programmer point of view (and not from the machine's one), would be far easier to type:

require "myclass"

Unless resources are critical, the development/maintenance time is more important in this case.

In PHP, you define only once a function which will guess the filename from the classname, and then you don't worry ever more. You don't need to specify nothing!!! When a reference to "MyClass" appears, the function __autoload will convert it to a filename (e.g., "myclass.inc"; you can code __autoload with your needs) and will try to include that file. That's awesome useful!

Fortunately, Ruby is a very powerful language, and, following a tip, I made my version:

# autoload like in PHP
# (c) Sony Santos 2011
# License: Public Domain
# http://rubychallenger.blogspot.com/2011/03/ruby-autoload-like-in-php.html

# alters Object#const_missing
#
class Object

  # it's a class method, not an instance one
  class << self

    # preserves the original method
    alias_method :old_const_missing, :const_missing
    private :old_const_missing

    # redefine the method which is called on a missing const
    def const_missing(const)

      # guess a filename (use your favorite algorithm)
      filename = const.to_s.downcase

      begin
        # try to require it
        require filename

        # if it did, returns that missing const
        const_get(const)

      rescue LoadError => e
        if e.message.include? filename

          # that constant doesn't really exist; use the old method
          old_const_missing(const)

        else

          # other reason
          raise

        end
      end
    end
  end
end

About my Ruby experiences

Is Ruby easy to learn?

Er... No, it isn't.

First point: There isn't a main documentation/tutorial/reference center where you can learn step by step all the Ruby nuances, from basic to advanced techniques.

There are, in fact, many sites and books and blogs and tutorials on Ruby, and they're different from each other, and you don't know where should you start from. Only one book is not enough to read. That turns the learning by yourself into a hard task.

Second point: The basics of Ruby are easy. Classes, objects, methods... things you've seen in other languages. You can code a lot from the basics.

But what makes Ruby a powerful language, the main motivation to choose Ruby among other good languages, is not in the basics. The power of Ruby is in the Metaprogramming. It is the ability to reopen classes, even core ones, and adapt them to your suits. It is the ability to redefine methods and create methods on-the-fly, and use all flexibility of the parameters to make the best fit to your goals. It is the ability to use Ruby to create DSLs. And that is not easy.

In this blog I do not intend to teach Ruby. I will share my experiences. And, as a scientist who likes challenges, I'll make many experiments... 8^)