RB 101 - joselondon/ls_ruby_track Wiki

Ruby 101


Lesson 1

booleans Question: What is being evaluated by:

if true
  puts 'hi'
else
  puts 'goodbye'
end

and

if false
  puts 'hi'
else
  puts 'goodbye'
end

Is it self/main ?

CONDITIONALS short-circuiting chained conditional &&/||'s - ruby evaluates chained AND/OR's from the left and stops evaluating as soon as the result is guaranteed

TRUTHINESS Ruby considers everything other than nil or false to be truthy

Lesson 2

to_i and to_f be aware the both are non destructive and to_f will never raise and exception. So "foo".to_f will return 0.0 not an exception

FORMALISED PSEUDO CODE - KEYWORDS

keyword meaning
START start of the program
SET sets a variable we can use for later
GET retrieve input from user
PRINT displays output to user
READ retrieve value from variable
IF / ELSE IF / ELSE show conditional branches in logic
WHILE show looping logic
END end of the program

FLOW CHARTS FOR MORE COMPLEX PROBLEMS#

flow_chartcomponents

STEPS TO DEBUGGING

modify the data or code to get an idea of the scope of the error. For example, the stack trace earlier was generated by this code post.categories << news. Does calling post.categories cause issues? What about just calling post? What happens if we try to append a different object, like this: post.categories << sports? How does modifying the data affect the program behavior? Do we get expected errors, or does a new error occur that sheds light on the underlying problem?


PRECEDENCE Use PEMDAS and Ruby docs An operator that is higher in precedence is said to bind more tightly to it operands Ruby's tap method very useful for debugging code, especially return values and precedence issues. Passes the calling object into a block argument and returns the block, as the example below: -

mapped_array = array.map { |num| num + 1 }

mapped_array.tap { |value| p value }              # => [2, 3, 4]

To avoid precedence issues an make things easier for people following your code USE PARENTHESES WHEN USING MIXED OPERATORS CODE TIPS

a = "hi there" # a => 'hi there'
b = a # a => 'hi there' , b => 'hi there'
a = "not here" # a => 'hi there', b => 'not here'
a = "hi there" # a => 'hi there'
b = a  # a => 'hi there' , b => 'hi there'
a << ", Bob" # b => 'hi there, Bob'

Code snippet 1

snippet_1

code snippet 2

snippet_2

The line of code a << ", Bob" did not result in reassigning a to a new string. Rather, it mutated the caller and modified the existing string, which is also pointed to by the variable b. This explains why in this code, b reflects the changes to a - they're both pointing to the same thing.

This is the major point of this section: some operations mutate the address space in memory, but others simply change the variable to point to a different address space.

This also applies to variables that point to arrays, hashes, or any data structure that has methods that mutate the caller. If you call a method that mutates the caller, it will change the value in that address space, and any variables also pointing there will be affected. Therefore, always pay attention whether your variables are pointing to the same object (space in memory) or if they are dealing with copies that occupy different address space in memory.

OBJECT EVALUATION STRATEGIES Every computer programming language uses some sort of evaluation strategy when passing objects. This strategy determines when expressions are evaluated, and what a method can do with the resulting objects. The most common strategies are known as strict evaluation strategies. With strict evaluation, every expression is evaluated and converted to an object before it is passed along to a method. Ruby uses strict evaluation exclusively.

The two most common strict evaluation strategies are pass by value and pass by reference. Collectively, we will refer to pass by value and pass by reference as object passing strategies.

SHOULD A METHOD HAVE SIDE EFFECTS OR RETURN SOMETHING Side effects means a method mutates an object or displays something to output. In general a method should either return something or have a meaningful return value - it should not do both

SINGLE CONCERN FOR METHODS Don't write a method that mutates, outputs and returns a meaningful value. Make sure your methods just do one of those things.

DON'T MUTATE THE CALLER DURING ITERATION You can however mutate individual elements of an Array just not the Array object itself (eg removing or adding elements)

USE UNDERSCORE FOR UNUSED PARAMETERS Suppose you have an array of names, and you want to print out a string for every name in the array, but you don't care about the actual names. In those situations, use an underscore to signify that we don't care about this particular parameter.

names = ['kim', 'joe', 'sam']
names.each { |_| puts "got a name!" }

or in the case of multiple parameters

names.each_with_index do|_, idx|
  puts "#{idx+1}. got a name!"

end

Lesson 4 - Collections

LOOPING Looping comprises four basic elements: a loop, a counter, a way to retrieve the current value, and a way to exit the loop. It's important to understand how to manually loop over collections with nothing more than these 4 tools. It's often tempting to go "method hunting" to search for a method to iterate over a collection, but if you master the basics of looping, you'll find that you can perform nearly any operation you need with the simple techniques in this assignment. Methods can be useful, but they shouldn't be used as a crutch.

Introduction to PEDAC process

P - [Understand the] Problem E - Examples/Test cases D - Data Structure A - Algorithm C - Code P - [Understand the] Problem 3 steps: -

  1. Read the problem description.
  2. Check the test cases, if any.
  3. If any part of the problem is unclear, ask the interviewer to clarify the matter.
# PROBLEM:

# Given a string, write a method change_me which returns the same
# string but with all the words in it that are palindromes uppercased.

# change_me("We will meet at noon") == "We will meet at NOON"
# change_me("No palindromes here") == "No palindromes here"
# change_me("") == ""
# change_me("I LOVE my mom and dad equally") == "I LOVE my MOM and DAD equally"

example of analysis of problem:-

# input: string
# output: string (not the same object)
# rules:
#      Explicit requirements:
#        - every palindrome in the string must be converted to
#          uppercase. (Reminder: a palindrome is a word that reads
#          the same forwards and backward).
#        - Palindromes are case sensitive ("Dad" is not a palindrome, but "dad" is.)

#      Implicit requirements:
#        - the returned string shouldn't be the same string object.
#        - if the string is an empty string, the result should be an empty
#          string

Data Structure / Algorithm

Data structures influence your algorithm, and for that reason, these two steps are often paired. Deciding what data structure to use is generally easy for students: use cases for arrays and objects, for instance, are generally easy to identify. However, designing the right algorithm is far more challenging. The biggest problem that students have when writing algorithms is providing sufficient detail.

each, select, and map method reference table

Method Action Considers the return value of the block? Returns a new collection from the method? Length of the returned collection?
each Iteration No No, it returns the original Length of original
select Selection Yes, its truthiness Yes Length of original or less
map Transformation Yes Yes Length of original