Local variables cannot be accessed in a method, but can in a block.
ex. this is not possible
greet = 'hello!'
def greeter(str)
puts greet + str #greet is not accessible inside the method.
end
greeter('Joe')
NameError: undefined local variable or method `greet' for main:Object
however, inside a code block it is possible to access a local variable
greet = ['hello', 'hola', 'howdy']
name = 'Jon'
greet.each do |greeting| # greeting is a local variable only accesible to the block, however.
puts "#{greeting} #{name}"
end
# for reference, the `.each` method returns the array of greet
Ex. of a non destructive method
arry = [1, 2, 3, 4, 5]
new_arry = arry.select { |num| num > 3} # the select method is non destructive, it returns a new array with the values selected
puts arry # unaltered prints out 1,2,3,4,5
puts new_arry # only has the numbers of 4 and 5
# puts return nil
however, some methods are destructive, such as map!
arry = [1, 2, 3, 4, 5]
new_arry = arry.map! { |num| num + 1 } # map! returns the new array, also mutates the existing array
puts arry # prints 2,3,4,5,6
puts new_arry # prints 2,3,4,5,6
# for reference, map does not mutate the original array, only map! does.
It is generally a good sign that if a method has a ! or 'bang'
operator it is destuctive. And by destructive I mean that it will mutate the original array, or hash.
passing values into methods can also cause some odd, and adverse effects
def amethod(param)
param += " world" # this is going to return a new string object, NOT permanent, reassignment, outputs hello
# param = param + " world" (reassigning param to )
param + " world" # NOT permanent, string concatination, the + is a method, outputs hello
param << " world" # WILL mutate the calling object, which is param, << is a method call
# destructive, outputs hello world
end
str = "hello"
amethod(str)
p str
working with collections (Array, Hash, String), and popular collection methods (each, map, select, etc). Study these methods carefully.
.each
method iterates over an array and returns the original array, or hash
a = [1,2,3]
a.each { |num| puts num + 1}
# prints
# 2
# 3
# 4
# =>[1, 2, 3]
hash
a = {a: 1, b: 2, c: 3}
a.each { |key,value| puts "#{key}: #{value+1}"}
# prints
# a: 2
# b: 3
# c: 4
# returns {:a=>1, :b=>2, :c=>3}
Look above for .map
.map!
and .select
both .map
and .select
are non destructive and return new arrays, whereas .map!
both returns a new array and modifies a new array.
.each_with_index
a = ["a", "b", "c"]
a.each_with_index do |val, idx|
puts "#{idx}: #{val}"
end
# prints
# 0: a
# 1: b
# 2: c
# returns ["a", "b", "c"]
or creating a hash with each_with_index
hash = Hash.new
%w(cat dog wombat).each_with_index { |item, index|
hash[item] = index
}
hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
More of these can be found in the ruby enumeral section
pop
removes the last element in an array. returns the removed value, mutates original array.
shift
removes the first element in an array. returns the removed value, mutates original array.
any?
returns true or false based on block, indicated by ?
, does not alter original array.
all?
returns true or false based on block, indicated by ?
, does not alter original array
none?
only returns true if NONE
of the objects return true
find
returns the first value based on the block that returns true.
puts
are printed values, not returned values. see above when looking at .each
the method prints out what is specified by the block, but it still returns the original array or hash.
##false vs nil
true
and false
are not just simply keywords. Every object in ruby can be evaluated to a boolean value.
although nil
evaluates to false, it is not the same as 2 > 5
.
4 && 5 # This returns 5
nil && true # This returns nil
true && nil # This returns nil
true || nil # This returns true
nil || "" # This returns ""
0.nil? # returns false
some differences: -nil cannot be a value, whereas false can be a value -false is a boolean, whereas nil is not -nil is an object for NilClass, where false is an object of FalseClass -nil is not a data type