Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Tuesday, 12 June 2012

Ruby: regex

The Ruby operator =~ matches a string against a pattern. It returns character offset into the string at which the match occurred, or returns nil if match fails. Your can put the regex first or the string first. Either way is ok. Because nit is equivalent to false in a boolean context, you can use the result as a condition in if or while statements.

Regular expression also defines === as a simple pattern match:
case line
when /title=(.*)/
  puts "Title is #$1"
when /track=(.*)/
puts "Track is #$1"
when /artist=(.*)/
puts "Artist is #$1"
end

Regular expression options

  • i Case insensitive.
  • o Substitute once. Any #{...} substitutions in a particular regular expression literal will be performed just once, the first time it is evaluated. Otherwise, the substitutions will be performed every time the literal generates a Regex object.
  • m Multiline mode. Normally, "." matches any character except a newline. With the /m option, "." matches any character.
  • x Extended mode. Complex regular expression can be difficult to read. The x option allows you to insert spaces and newlines in the pattern to make it more readable. You can also use # to introduce comments.
Reference: Programming in Ruby 1.9: The Pragmatic Programmer's Guide

Thursday, 24 May 2012

Ruby vs Python: threads

Prior to Ruby 1.9, threads were implemented at green threads - threads were switched within the interpreter. In Ruby 1.9, threading is now performed by the operating system. This means that threads can now take advantage of multiple processors. However, there's major catch. Many Ruby extension libraries are not thread safe, so Ruby compromises: it uses native operating system threads but operates only a single thread at a time. You'll never see two threads in the same application running Ruby code truly concurrently. (You will, however, see threads busy doing, say I/O while another threads executes Ruby code. That's part of the point.)

This is also similar in Python. Due to the Global Interpreter Lock, in CPython only one thread can execute Python code at once (even though certain performance-oriented libraries might overcome this limitation). To make better use of the computational resources of multi-core machines, it is advised to use multiprocessing. However, threading is still an appropriate model if you want to run multiple I/O-bound tasks simultaneously.

Reference: Programming Ruby 1.9: The Pragmatic Programmers' Guide (Facets of Ruby)

Monday, 27 February 2012

Ruby: yield statement

A method can invoke an associated block one or more times using the Ruby yield statement. You can think of yield as being something like a method call that invokes the block associated with the call to the method containing the yield. Whenever yield is executed, it invokes the code in the block. When the block exits, control picks back up immediately after the yield. Here's a trivial example:
def three_times
  yield
  yield
  yield
end
three_times { puts "Hello" }
produces:
Hello
Hello
Hello

Saturday, 4 February 2012

Ruby: calling a method

Collecting hash arguments
Ruby doesn't have keyword arguments. But you can achieve the same effect by using hashes. You can place key => value pairs in an argument list, as long as they follow any normal arguments and precede any splat and block arguments. All these pairs will be collected into a single hash and passed as one argument to the method. No braces are needed. There is also the new hash literal syntax in Ruby 1.9: 
class SongList
  def search(field, params)
    # ...
  end
end 

list.search(:title, genre: 'jazz', duration_less_than: 270)

Friday, 2 December 2011

Ruby IO

Output
puts writes its arguments with a newline after each; print also writes its arguments but with no newline. printf works similar as C. The p method prints out an internal representation of an object.

Saturday, 22 October 2011

Update ruby to 1.9.2 on Ubuntu 11.10

$sudo apt-get remove ruby rubygems ruby1.8 ruby1.8-dev ruby1.8-full
$sudo apt-get install ruby1.9.1-full
$sudo update-alternatives --set ruby /usr/bin/ruby1.9.1
$sudo env REALLY_GEM_UPDATE_SYSTEM=1 gem update --system

Sunday, 18 September 2011

Ruby and Python boolean expressions compared

Ruby:

Only false and nil are treated as being false in a boolean context. All other values are treated as being true.

and, &&, or, and || all return operands. Bot and and && return their first argument if it is false. Otherwise, they evaluate and return their second argument. Similarly, both or and || return their first argument unless it is false, in which case they evaluate and return their second argument.

The word forms of the logical operators (and, or and not) have a lower precedence than the corresponding symbol forms (&&, ||, and !).

Equality testing:
Ruby has three main equality test methods, ==, eql? and equal?. They are defined in the Object class and in the Object class, all three methods do exactly the same thing, they test if two objects are exactly the same object. However, in other classes, they are usually redefined with different semantics:
  • == Test for equal value
  • eql? True if the receiver and argument have both the same type and equal values. 1 == 1.0 returns true, but 1.eql?(1.0) is false.
  • equal? True if the receiver and argument have the same object ID.
Ruby also has a case equality operator ===, which is used to compare each of the items with the target in the when clause of a case statement. The === operator is defined in Class to test whether the argument is an instance of the receiver or one of its superclasses. So you can use it to test the class of objects.

Python:

More values are considered false in Python:
  • None
  • False
  • zero of any numeric type, for example, 0, 0L, 0.0, 0j.
  • any empty sequence, for example, '', (), [].
  • any empty mapping, for example, {}.
  • instances of user-defined classes, if the class defines a __nonzero__() or __len__() method, when that method returns the integer zero or bool value False.
Python only has word forms of the logical operators. They return their operands in the same way as in Ruby.

In Python, == is similar to == in Ruby for numeric types and different string types (str and unicode) in that it only compares the values, but not the types, e.g. 1 == 1.0 returns True. But for objects of other types, == is similar to eql? in Ruby because both types and values have to be equal for it to return True. The object identity test is is the same to equal? in Ruby.

To check if an object is an instance of a type (class), use isinstance(object, type_name).

Tuesday, 30 August 2011

Ruby: strings

Single-quoted strings only support two escape sequences: two consecutive backslashes are replaced by a single backslash, and a backslash followed by a single quote becomes a single quote.

Double-quoted strings support more escape sequences, like "\n". It also allows string interpolation #{expr}. If the code is just a global variable, a class variable, or an instance variable, you can omit the braces.

%q and %Q start delimited single- and double-quoted strings as well.
%q/general single-quoted string/
%Q!general double-quoted sting!
%{Seconds/day: #{24 * 60 * 60}} # => Q can be ommitted.


You can also construct a string using a here document:
string = <<END_OF_STRING
    The body of the string
    is the input lines up to 
    one starting with the same
    text that followed the '<<'
END_OF_STRING

Normally, the terminator of the here document must start in the first column. However if you put a minus sign after the << characters, you can indent the terminator:
string = <<-END_OF_STRING
    The body of the string
    is the input lines up to 
    one starting with the same
    text that followed the '<<'
    END_OF_STRING

To initialize an array of strings, you can use %w:
%w(foo bar) # => ["foo", "bar"]

Installing rubygems

Installing rubygems on Ubuntu 11.04 takes several steps:

$ sudo apt-get install rubygems rubygems-update
$ gem env | grep EXECUTABLE
// cd to the executable directory
$ update_rubygems 
// now rubygems will be installed in the correct directory.

Sunday, 10 April 2011

Ruby: metaprogramming

Definitions
Singleton method: a method defined on a particular object
Singleton class: the anonymous class created in which a singleton method is defined

Object Model
  • Instance variables live in objects, and methods live in classes.
    • You can get a list of object's methods by calling obj.methods.
    • For a class, you can call klass.methods to see what class methods are available, and klass.instance_methods to know the instance methods. klass.instance_methods(false) returns methods defined by the class and not inherited.
  • Classes themselves are nothing but objects, and have their own class called Class.
    • All classes ultimately inherit from Object.
      "hello".class # => String
      String.class # => Class
      Class.instance_methods(false) # => [:allocate, :new, :superclass]
      # :superclass is only a method a class, not an object. 
      String.superclass # => Object
      
  • The methods of an a class are the instance methods of Class.
Self
  • Every line of Ruby code is executed inside an object - the so-called current object. The current object is also known as self.
  •  In a class or module definition, the role of self is taken by the class or module.
Singleton Methods
  • Class methods are Singleton Methods of a class.
  • Introspection methods:
    • singleton_methods returns all the singleton methods for the object (also the ones in included modules).
    • singleton_methods(false) returns all the singleton methods for the object, but not those declared in included modules.
    • methods(false) supposedly returns the singleton methods by calling singleton_methods, but it also passes the parameter false to it.
      String.methods(false) == String.singleton_methods(false) # => true

Monday, 21 March 2011

Ruby: block

Blocks can be closures
In computer science, a closure is a first-class function with free variables that are bound in the lexical environment. Blocks are closures, which means variables in the surrounding scope that are referenced in a block remain accessible for the life of that block and the life of and Proc object created from that block.

Example:
def n_times(thing)
  lambda {|n| thing * n}
end

p1 = n_times(23)
p1.call(3) # => 69
p1.call(4) # => 92

Compare with Python closures:
def generate_power_func(n):
  def nth_power(x): 
    return x**n
  return nth_power
end

raised_to_4 = generate_power_func(4)
raised_to_4(2)
Blocks can be objects
Block can be converted to an object of class Proc. There are several ways where blocks are converted to objects.
  • If the last parameter in a method definition is prefixed with an ampersand (such as &action), Ruby looks for a code block whenever that method is called. 
  • Use lambda or its alternative -> form. For example:
    bo = lambda { |param| puts "You called me with #{param}" }
    bo.call 99
    bo.call "cat"
    # produces:
    # You called me with 99
    # You called me with cat
    
    lam = ->(p1, p2) { p1 + p2 }
    lam.call(4, 3) # => 7
    Compare this with the "bound function operator" in CoffeeScript:
    callback = (message) => @voicement.push message
    
  • Use Proc.new

  • The call method on a proc object invokes the code in the original block.

The Symbol.to_proc trick
Ruby implements the to_proc for objects of class symbol.
names = %w{ant bee cat}
result = names.map {|name| name.upcase}
result = names.map {&:upcase}
The last line means: apply the upcase method to each element of names. This works by relying on Ruby's type coercion. When you say names.map(&xxx), you're telling Ruby to pass the Proc object in xxx to the map method as a block. If xxx isn't already a Proc object, Ruby tries to coerce it into one by sending it a to_proc message. If it was written Ruby, it would look something like this:
def to_proc
  proc { |obj, *args| obj.send(self, *args) } # same as lambda
end
It's an incredibly elegant use of coercion and of closures. However, the use of dynamic method invocations mean that the version of code that uses &:upcase is about half as fast as the more explicitly coded block. This doesn't matter so much unless in the performance-critical section of your code.