An Array is just a list of items in order (like mangoes, apples, and oranges). Every slot in the list acts like a variable: you can see what object a particular slot points to, and you can make it point to a different object. You can make an array by using square brackets In Ruby, the first value in an array has index 0. The size and length methods return the number of elements in an array. The last element of the array is at index size-1. Negative index values count from the end of the array, so the last element of an array can also be accessed with an index of -1. If you attempt to read an element beyond the end of an array (with an index >= size) or before the beginning of an array (with an index < -size), Ruby simply returns nil and does not throw an exception. Ruby's arrays are mutable - arrays are dynamically resizable; you can append elements to them and they grow as needed. Let us look at the following examplep018arrays.rb. Please go through the program carefully.
- # p018arrays.rb
- # Arrays
- # Empty array
- var1 = []
- # Array index starts from 0
- puts var1[0]
- # an array holding a single number
- var2 = [5]
- puts var2[0]
- # an array holding two strings
- var3 = ['Hello', 'Goodbye']
- puts var3[0]
- puts var3[1]
- flavour = 'mango'
- # an array whose elements are pointing
- # to three objects - a float, a string and an array
- var4 = [80.5, flavour, [true, false]]
- puts var4[2]
- # a trailing comma is ignored
- name = ['Satish', 'Talim', 'Ruby', 'Java',]
- puts name[0]
- puts name[1]
- puts name[2]
- puts name[3]
- # the next one outputs nil
- # nil is Ruby's way of saying nothing
- puts name[4]
- # we can add more elements too
- name[4] = 'Pune'
- puts name[4]
- # we can add anything!
- name[5] = 4.33
- puts name[5]
- # we can add an array to an array
- name[6] = [1, 2, 3]
- puts name[6]
- # some methods on arrays
- newarr = [45, 23, 1, 90]
- puts newarr.sort
- puts newarr.length
- puts newarr.first
- puts newarr.last
- # method each (iterator) - extracts each element into loc
- # do end is a block of code
- # we shall talk about blocks soon here -
- # /satishtalim/ruby_blocks_and_procs.html
- # variable loc refers to each item in the array as it goes through the loop
- locations = ['Pune', 'Mumbai', 'Bangalore']
- locations.each do |loc|
- puts 'I love ' + loc + '!'
- puts "Don't you?"
- end
- # delete an entry in the middle and shift the remaining entries
- locations.delete('Mumbai')
- locations.each do |loc|
- puts 'I love ' + loc + '!'
- puts "Don't you?"
- end
The method each (for any object) allows us to do something (whatever we want) to each object the array points to. In the example, we are able to go through each object in the array without using any numbers. Here are a few things to remember:
- The variable loc inside the "goalposts" refers to each item in the array as it goes through the loop. You can give this any name you want, but make it memorable.
- The do and end identify a block of code that will be executed for each item. Blocks are used extensively in Ruby.
Here's an interesting example of a method that returns an array. Example p019mtdarry.rb
- # p019mtdarry.rb
- # if you give return multiple parameters,
- # the method returns them in an array
- # The times method of the Integer class iterates block num times,
- # passing in values from zero to num-1
- def mtdarry
- 10.times do |num|
- square = num * num
- return num, square if num > 5
- end
- end
- # using parallel assignment to collect the return value
- num, square = mtdarry
- puts num
- puts square
The output is:
- >ruby p019mtdarry.rb
- 6
- 36
- >Exit code: 0
The times method of the Integer class iterates block num times, passing in values from zero to num-1. As we can see, if you give return multiple parameters, the method returns them in an array. You can use parallel assignment to collect this return value.
Parallel Assignment
To explain this, we'll use the terms lvalue and rvalue. An lvalue is something that can appear on its own on the left-hand side of an assignment (a variable, constant, or attribute setter method). An rvalue is something that can appear on its own on the right hand side. Ruby lets you have a comma-separated list of rvalues. Once Ruby sees more than one rvalue in an assignment, the rules of parallel assignment come into play. First, all the rvalues evaluated, left to right, and collected into an array (unless they are already an array). This array will be the eventual value returned by the overall assignment. Next, the left hand side (lhs) is inspected. If it contains a single element, the array is assigned to that element.
- a = 1, 2, 3, 4 # => a == [1, 2, 3, 4]
- b = [1, 2, 3, 4] # => b == [1, 2, 3, 4]
If the lhs contains a comma, Ruby matches values on the rhs against successive elements on the lhs. Excess elements are discarded.
- a, b = 1, 2, 3, 4 # => a == 1, b == 2
- c, = 1, 2, 3, 4 # => c == 1
Environment Variables
An environment variable is a link between our program and the outside world. An environment variable is essentially a label referring to a piece of text; and can be used to store configuration information such as paths, usernames, and so on. You can access operating system environment variables using the predefined variable ENV. ENV is simply a hash.
- ENV.each {|k,v| puts "#{k}: #{v}"}
Ruby sets ENV to the environment variables. After that, iteration proceeds with each. This time, the block takes two parameters: k (key) and v (value). Blocks are a completely general mechanism and can take any number of arguments.
The values of some environment variables are read by Ruby when it first starts. These variables modify the behavior of the interpreter, as shown below.
A Ruby program may write to the ENV object. On most systems this changes the values of the corresponding environment variables. However, this change is local to the process that makes it and to any subsequently spawned child processes. A subprocess changes an environment variable, and this change is inherited by a process that it then starts. However, the change is not visible to the original parent. (This just goes to prove that parents never really know what their children are doing.)
- ENV["course"] = "FORPC101"
- puts "#{ENV['course']}"
As of Ruby 1.9, setting an environment variable's value to nil removes the variable from the environment.
Command-line arguments
If you're starting a program from the command line, you can append parameters onto the end of the command and the program processes them.
You can do the same with your Ruby application. Ruby automatically places any parameters that are appended to the command line when you launch your Ruby program into a special array called ARGV. If your program is:
You can do the same with your Ruby application. Ruby automatically places any parameters that are appended to the command line when you launch your Ruby program into a special array called ARGV. If your program is:
- f = ARGV[0]
- puts f
You can execute this program from the command line as:
- ruby tmp.rb 23
The program should display 23.
Library GetoptLong
Class GetoptLong supports command-line option parsing. Options may be a minus sign (-) followed by a single character, or two minus signs (--) followed by a name (a long option). Options may be given in any order. A single internal option may have multiple external representations. For example, the option to control verbose output could be any of -v, --verbose, or --details. Some options may also take an associated value. Each internal option is passed toGetoptLong as an array, containing strings representing the option's external forms and a flag. The flag specifies how GetoptLong is to associate an argument with the option (NO_ARGUMENT, REQUIRED_ARGUMENT, or OPTIONAL_ARGUMENT).
Suppose I want to call a Ruby program as:
Suppose I want to call a Ruby program as:
- ruby tsftpc.rb -hftp.ibiblio.org -n21 -uanonymous -ps@s.com
Here's the code to do so:
- require 'getoptlong'
- # Call using "ruby tsftpc.rb -hftp.ibiblio.org -n21 -uanonymous -ps@s.com"
- # The parameters can be in any order
- unless ARGV.length == 4
- puts "Usage: ruby tsftpc.rb -hftp_site_url -nport_no -uuser_name -ppassword"
- exit
- end
- host_name = port_no = user_name = password = ''
- # specify the options we accept and initialize
- # the option parser
- opts = GetoptLong.new(
- [ "--hostname", "-h", GetoptLong::REQUIRED_ARGUMENT ],
- [ "--port", "-n", GetoptLong::REQUIRED_ARGUMENT ],
- [ "--username", "-u", GetoptLong::REQUIRED_ARGUMENT ],
- [ "--pass", "-p", GetoptLong::REQUIRED_ARGUMENT ]
- )
- # process the parsed options
- opts.each do |opt, arg|
- case opt
- when '--hostname'
- host_name = arg
- when '--port'
- port_no = arg
- when '--username'
- user_name = arg
- when '--pass'
- password = arg
- end
- end
require gives you access to the many extensions and programming libraries bundled with the Ruby programming language-as well as an even larger number of extensions and libraries written independently by other programmers and made available for use with Ruby. We shall be studying require in more detail, later on. Also, later on, we shall study how to access constant using ::
How do I convert objects into an Array? If you want to wrap objects in an Array, you can use a special Kernelmodule Array method (that starts with a capital letter and looks like a class). This special method converts its one argument into an array. For example:
- str = 'hello'
- print Array(str).class # Array
Another example:
- str = 'hello\nworld'
- print Array(str) # ["hello\\nworld"]
What are the ancestors of Array? Run the following program, to find that out:
- a = [1,2,3,4]
- print a.class.ancestors
You should see:
- [Array, Enumerable, Object, Kernel, BasicObject]