Collections: Working with Hashes in Ruby

Collections: Working with Hashes in Ruby

Hashes are data structures that contain key => value pairs and are denoted by curly braces {}

hash = {:key => value}  # old syntax
hash = {key: value} #new syntax

They can have multiple key value pairs.

hash = {:key1 => value1, :key2 => value2, :key3 => value3}

To add onto a hash:

hash[:key4] = value4
hash[:key5] = value5
hash   
# => {:key1 => value1, :key2 => value2, 
      :key3 => value3, :key4 => value4, :key5 => value5}

To delete a key and its value:

hash.delete(:key1)
hash = {:key2 => value2, :key3 => value3, :key4 => value4, :key5 => value5}

To retrieve a value of a specific key:

hash[:key5] 
# => value5

hash.merge(other_hash) merges hash with other_hash and creates another hash.

hash.merge!(other_hash) is a mutating version that modifies the calling hash object.

Iterate with .each method

hash.each { |key, value| puts #{key} #{value} }

 

Advertisement
Collections: Working with Arrays in Ruby

Collections: Working with Arrays in Ruby

DISCLAIMER: I’m a noob to programming. This is not a guide or something that you should use to learn how to be a programmer. Some of it might be incorrect. This is just for me, John Gamboa, to record my progress in learning Ruby. Now that’s out of the way, on the to the article.

This is an array for a refresh:

array = [1, 2, 3, 3, 4, 5, 5]

Looking for something?

array.first   # returns the first element
              # => 1
array.last    # returns the last element
              # => 5
array[4]      # returns the element in that index (index starts at 0)
              # => 4

Looking for a change? These methods will change the array.

array.pop       # removes last element and mutates
array.push      # add element to the end and it mutates
array << object # "shovel" is the same as push and it mutates

More changes coming.

array.map       # iterates over each element, applies block, returns new array
array.delete_at # deletes value at an index and mutates
array.delete    # deletes all instances of a value and mutates
array.uniq      # returns a new array of all unique values, doesn't mutate
array.uniq!     # mutates array, only unique values are left.

Let me re-iterate with “each” and “select”:

The “each” method iterates through each element of an array (we are still talking arrays here) and applies a block of code to each element.

The “select” method is similar in that it loops through each element but it returns a new array and that new array includes elements that return true to the expression provided. If the return is nil or falsey, then nothing is entered into the array for that element.

select – returns a new array based on the block’s return value. If the return value evaluates to “true” (or checks if it’s truthy) then the element is selected.

Common array methods

array.include?(value) checks if value is in the array.

array.flatten takes an array with nested arrays and turns it into a one-dimensional array.

array.flatten! is flatten that mutates

array.each_index iterates through the index and passes the index of each element into the block.

array.each_with_index iterates through the array passes two parameters into the block, value and index.

array.sort returns a sorted array.

array.product(array2) combines two arrays like this:

[1, 2, 3].product([6, 7]) # => [[1, 6], [1, 7], [2, 6], [2, 7], [3, 6], [3, 7]]

each vs map: use each for iteration and it returns the original array, use map for transformation returns a new array

map – returns a new array based on the block’s return value. Each element is transformed based on the return value.

Changing Objects Passed Into Methods – Ruby

Changing Objects Passed Into Methods – Ruby

When a variable is passed into a method, it may or may not be changed based on the operation that takes place inside the method.

For example:

def no_mutation(str)
  str + ", John?
end

words = "How are you"
no_mutation(words)

puts words    # => "How are you"

Notice how the “+” operator doesn’t change or mutate the “words” variable? That’s because “+” is not destructive. It concatenates “How are you” and “, John?” but that complete string isn’t assigned to anything nor the original object “How are you” changed by the “+” operator. If the line were changed to str = str + “, John?”, the str variable would then point to a new string object “How are you, John?” but it would not change the original string object that was passed into the method.

Now let’s look at the following code.

def mutation(str)
  str << ", John?
end

words = "How are you"
mutation(words)

puts words    # => "How are you, John?"

This time string object that “words” points to is changed by the method. That’s because the << in the method is destructive and mutates the object that is referenced by the variable.

Conclusion:

Depending on the operation going on in the method, the object passed in may or may not be changed. It’s a good reason to use irb to test your code and see what is happening to the objects in your methods.

Local Variable Scoping Rules in Ruby- Part Two

Local Variable Scoping Rules in Ruby- Part Two

Continuing on the topic of local variable scoping rules, we come to the scoping rules for methods.

Check this code:

a = 5

def some_method
  a = 3
end

puts a # => 5 (Why 5 and not 3?

When the code executes “puts a”, it displays 5 and not 3. The reason is our 2nd rule.

Rule #2 – Methods create their own scope outside of execution flow.

We’ll visit methods a little more later in the blog.

Blocks and Nests

Rule #3 – A block creates a new scope for local variables, nested blocks created nested scopes, and the scope of a variable is determined by where it is initiated.

Let’s take a look at the following code for illustration.

2.times do
  a = 'hello' # a is initialized inside the 2.times block.
  puts a
end

loop do
  puts a     # => uh oh NameError
  break
end

puts a      # => man! another NameError

The variable “a” is initialized in the first block and therefore can’t be accessed the second block or the last “puts a” line. That also means that peer blocks cannot access variables initialized in other blocks. Which also then means we could reuse “a” for another variable in the second block. We really shouldn’t use letters for variable names since they should be a lot more descriptive.

Nested blocks create nested scopes. If you initiate a variable outside of any blocks it will be accessible by blocks and inner blocks. If a variable is initiated in a block it is accessible by blocks created inside the block it was created in. Confused? I guess this concept is better served with actual code.

a = 1            # first level variable accessible by blocks and nested blocks

loop do
  b = 2          # second level variable

  loop do
    c = 3        # third level not accessible to first or second level
    puts a       # => 1
    puts b       # => 2
    puts c       # => 3
    break
  end
  
  puts a         # => 1
  puts b         # => 2
  puts c         # => NameError because c is on 3rd level
  break
end

puts a          # => 1
puts b          # => NameError because b is on 2nd level
puts c          # => NameError because c is on 3rd level

Variable Shadowing

Basically if you have an outer variable and an inner variable with the same name, you prevent the outer variable from being modified by the code where the inner variable exists.

n = 10
[1, 2, 3].each do |n|
  puts n    # will use the block 'n' and ignore the outer scoped 'n'
end
n = 10
1.times do |n|
  n = 11
end
puts n    # => 10 because the outer scope 'n' isn't changed

Rule #4 – The simplest way to avoid variable shadowing is to use descriptive variable names.

Variables and Methods

In contrast to blocks that leak from outer to inner blocks, methods are self contained.

a = 'hello'

def some_method
  puts a
end

# invoke the method
some_method     # => NameError because puts can't access 'a'
  
  def some_method(a)
    puts a
  end

  some_method(5)   # => 5

Rule #5 – Variables can’t leak into a method from outside the method, they have to be passed in explicitly.

Blocks Within Methods

Rule #6 – The rules of block scope remain in full effect inside of a method.

Constants

  USERNAME = 'Boss'

  def welcome
   puts "Welcome, #{USERNAME}!"  end

  welcome     # => Welcome, Boss!

Rule #7 – Constants are accessible by methods and can be initiated in an inner scope.

Local Variable Scoping Rules in Ruby – Part One

DISCLAIMER: At the time of this post, I, John Gamboa, was not a Ruby or programming expert. A total noob and I wrote this more to familiarize myself with the rules than anything else. What flows through sticks to you.

A scope of a local variable determines if it is accessible or not. For instance, if you were to code this:

var1 = 1
loop do
  puts var1
  var1 = var1 + 1
  break
end
puts var1

Run the code and you’ll find that the last line “puts var1” results in 2 being displayed. Why? Because the variable var1 in the first line is accessible and there can be modified by the loop block.

Rule #1 – Outer scope variables are accessible by the inner scope.

But what about block of code? What does the last line produce?

array = [6, 5, 4]
for i in array do
  var1 = 5
end
puts var1

It produces 5. Even though var1 was initiated inside the do/end block, var1 is accessible outside it. For a variable to be inaccessible in a do/end block, the do/end block needs to immediately follow a method invocation. “for” in the code above is not a method invocation, in contrast to the following code:

loop do
  var1 = 1
  puts var1
  var1 = var1 + 1
  break
end
puts var1

Since “loop” is a method invocation, the do/end loop following it creates a new block which prevents var1 from being accessed by “puts” in the last line. It results in an error with “undefined local variable or method…” in it. That’s because var1 was initialized inside the loop block, or in the inner scope, and the “puts var1” is outside the block and can’t access var1.

Which means…

Inner scope variables are NOT accessible outside of the block

First Web Dev Journal Entry

First Web Dev Journal Entry

So for the last few weeks I’ve been learning a web programming language called Ruby at launchschool.com. I decided to delve into web programming because it is a growing industry with lots of demand for skilled developers. With the advent of iPhone and the whole smartphone, mobile, slash always-connected phenomena, demand for web developers and software engineers has skyrocketed and with my background in IT, I figured I’d give it a go and maybe in a couple years be able to add software programming and web development to my repertoire of computer related skills.

Many years ago, I took a class in Visual Basic 6 at a local community college and did fairly well but it was super basic. I had no need for my job at the time nor was I looking to get into programming but I thought it would be good to learn. Not having to use the knowledge I learned back then, needless to say, I knew almost nothing coming into learning and had zero background when I decided to seriously study web development.

After a few weeks, I’m enjoying the process of learning again. I am always challenged by subject matter, because it’s all new to me and it feels like my brain is getting a workout daily. At times my mind feels like mush and other times it feels empowered from having learned AND understood new concepts.

The course encourages starting a blog and so I started this blog as a part of my IT Experiences site. It’s related, right? So, why not? I’ll occasionally post some updates. Not sure what they’ll be about – technical, experiential, both, who knows? Keep checking back to see how I’m doing.

My current plan is to finish the course that in 2 years I can say I have the skills to write a full-stack software program. Full-stack means front-end and back-end programming. Think front end as your smartphone and back-end as the servers in the cloud. What does it mean for me if I can complete this course successfully in 2 years? God only knows.Code