Showing posts with label function. Show all posts
Showing posts with label function. Show all posts

Thursday, October 13, 2011

Methods and attributes

As we've seen, methods are typically used with simple class instances and variables by separating the receiver from the method with a period (receiver.method). In the case of method names that are punctuation, the period is omitted. Methods can take arguments:
Time.mktime(2000, "Aug", 24, 16, 0)

Because every expression returns a value, method calls may typically be chained or stacked:
3.succ.to_s
/(x.z).*?(x.z).*?/.match("x1z_1a3_x2z_1b3_").to_a[1..3]
3+2.succ

Note that there can be problems if the cumulative expression is of a type that does not support that particular method. Specifically, some methods return nil under certain conditions, and this usually causes any methods tacked onto that result to fail. (Of course, nil is an object in its own right, but it will not have all the same methods that, for example, an array would have.)

Certain methods may have blocks passed to them. This is true of all iterators, whether built-in or user-defined. A block is usually passed as a do-end block or a brace-delimited block; it is not treated like the other parameters preceding it, if any. See especially the File.open example:
my_array.each do |x|
some_action
end

File.open(filename) { |f| some_action }

Named parameters will be supported in a later Ruby version like 1.9. These are called keyword arguments in the Python realm; the concept dates back at least as far as the Ada language. See here for named parameters.

Methods may take a variable number of arguments:
receiver.method(arg1, *more_args)

In this case, the method called treats more_args as an array that it deals with as it would any other array. In fact, an asterisk in the list of formal parameters (on the last or only parameter) can likewise "collapse" a sequence of actual parameters into an array:
def mymethod(a, b, *c)
print a, b
c.each do |x| print x end
end

mymethod(1,2,3,4,5,6,7)

# a=1, b=2, c=[3,4,5,6,7]

Ruby has the capability to define methods on a per-object basis (rather than per-class). Such methods are called singletons; they belong solely to that object and have no effect on its class or superclasses. As an example, this might be useful in programming a GUI; you can define a button action for a widget by defining a singleton method for the button object.
Here is an example of defining a singleton method on a string object:
str = "Hello, world!"
str2 = "Goodbye!"

def str.spell
self.split(/./).join("-")
end

str.spell # "H-e-l-l-o-,- -w-o-r-l-d-!"
str2.spell # error!

Be aware that the method is defined on the object, not the variable.
It is theoretically possible to create a prototype-based object system using singleton methods. This is a less traditional form of OOP without classes. The basic structuring mechanism is to construct a new object using an existing object as a delegate; the new object is exactly like the old object except for things that are overridden. This enables you to build prototype/delegation-based systems rather than inheritance based, and, although we do not have experience in this area, we do feel that this demonstrates the power of Ruby.

Named parameters in ruby

Ever forget whether the name or email parameter is first on a method like this?

signup(name,email)

Named parameters can help out so that you don't have to remember the order of parameters. As a fringe benefit the code can read a bit nicer and you can add in new optional parameters without breaking existing code.

Ruby as a language doesn't support named parameters to functions. But it does support converting named pairs into a hash if you provide an argument for it.


def signup(params)
name=params[:name]
email=params[:email]
...
end

This takes a little more work on the function declaration but it's not too bad. Now we can call the function like this:

signup(:name=>'Me', :email=>'me@net.com')

Suppose you wanted your name parameter to be optional and default to the email parameter. You can easily set default values for one or more of your expected parameters:

def signup(params)
email=params[:email]
name=params[:name]||email
...
end


With named parameters it often behooves you to do a bit more parameter checking.

def signup(params)
email=params[:email] || raise("email parameter is required!")
name=params[:name]||email
...
end

To make all parameters optional, set a default value for your parameter to {}.

def optional(params={})

Wednesday, October 12, 2011

Defining functions in ruby

Defining functions in ruby is quite easy:

def sayHello
puts "Hello world"
end

Calling the function:
sayHello()

Output: Hello world
The first line of the function defines the function called sayHello. The next line is the body of the method, the same line we saw earlier: puts "Hello World". Finally, the last line end tells Ruby we’re done defining the method. Ruby’s response => nil tells us that it knows we’re done defining the method.

Taking the arguments in functions:
def sayName(name)
puts "Hello #{name}"
end

Calling the function:
sayName("k2")

Output : Hello k2
(Note how name is printed with #{} in "" via puts)
Defining the function with default arguments:
def sayDefault(name = "Wolf")
puts "Hello #{name.capitalize}"
end

Calling the function:
sayDefault()

Output: Hello World

Calling with arguments:
sayDefault("k2")