JumpStart Live Day 3: Scope, Loops and Iterators

JSL Day 3 covers the following:

  • Scope
  • Loops
  • Iterators

Scope

Scope defines when something (usually a variable) is visible to something else in a program.

When we try to use a variable that isn’t visible, we’ll get an error in our code.

Here are four of the main types of variables in Ruby:

  • Class variable 
    • @@name
    • Visible to the class, and sub classes.
  • Instance variable 
    • @name
    • Visible to a specific object, and the instance methods of that object.
  • Global variable
    • $name
    • Visible to everything in the file
  • Local variable
    • name
    • The scope depends on the situation

Learn Ruby the Hard Way started introducing instance variables by Exercise 41 (and the concept of global variables earlier than that).

Even so…I’m used to dealing primarily with local variables.  (Plenty of people who do JSL are in the same boat.  So, that’s what this section mostly focuses on.)

>> Local variables are only visible inside the block in which they’re defined!! <<

Here are a few examples of what that means (in Ruby):

1. Local variables created outside of a block are visible to everything inside of that file.

For example, if we define a variable called name outside of a while loop, we’d be able to use name inside of the loop without any problems.

2. Local variables created inside ifstatements are visible outside of those ifstatements.

This is because if-statements aren’t considered blocks in Ruby, as far as scope is concerned.  (Note: That’s not true in other programming languages!!)

3. Local variables created inside of a block are NOT visible outside of those blocks.

Here’s an example of code that will give us an error…

undefine_local_variable
This is gonna give us an error.

In this case, we’re defining a new variable named last inside of an iterator, over the range 1 to 3.

This code is trying to print last outside of the block, but we can’t see it.

error_output
Error alert!

A simple way to fix this code is to initalize last outside of the block, like so:

undefined_local_variable_corrected
Defining “last” outside of the block

Loops

This section introduces four loop-related definitions:

  • Loop:  Repeats a sequence of statements.  It tells the program to do something a certain number of times, or until a certain condition is met.
  • Infinite loop:  A loop that runs forever…or until you kill the program.
  • Sentinel-controlled loop:  When the number of loops CANNOT be determined prior to loop execution (e.g. while, until)
  • Counter-controlled loop:  When the number of loops CAN be determined prior to loop execution (e.g. times)

Cool!  Let’s take a closer look as certain loops…

Sentinel-controlled Loops

while loop:  While condition is true, executes code over and over again.

while_syntax
Syntax for while loop

A boolean expression evaluates as either true or false.  We define a block with do and end.

Here’s a specific example:

 

while_example
Example of while loop

While rand_num is not equal to guess, the loop will continuously prompt the user to input a new number for guess.  It will keep repeating until rand_num and guess match.

Here’s another sentinel-controlled loop…

until loop:  Until condition is true, executes code over and over again.

until_syntax
Syntax for until loop

An until loop is basically the opposite of a while loop.  It executes over and over again UNTIL a condition is true.

Here’s a specific example:

until_example
Example of until loop

This is similar to our while example, but here’s the difference:

Until rand_num and guess are equal, this loop will keep repeating.

Counter-controlled Loops

Counter-controlled loops are used in other languages a lot more often than in Ruby.

In Ruby, you’d typically use an iterator.  However, .times without an iteration variable becomes a counter-controlled loop.

times_syntax
Syntax for .times

We’re saying, “Hey Ruby!  Do this code a certain number of times”.

Here’s what makes this a counter-controlled loop:  We know how many times this loop is going to run.

Let’s look at an example:

times_example
Example of .times

This is telling Ruby, “5 times, repeat this code”.  It prints “Hello” 5 times!

 

Iterators

This section talks about three types of iterators:

  • .each
  • range.each
  • .times

.each iterator:  Returns each value of the collection, one by one, to the block.  Iteration variable is optional (but usually used).

each_syntax
Syntax for .each

Here’s an example:

each_example
Example of .each

This block of code prints out each element in the array.

But wait!  THERE’S MORE.  We can also use a data type called range with .each.

range.each loops: A range is a set of values with a beginning and an end

range_syntax
Syntax for range.each

We can pass a range into the code as a collection.  It’s similar to how we loop through an array.

Note: When two dots are used, the range includes the last value.

Here’s an example of actual code:

range_code

(Note: When three dots are used, the range excludes the last value.)

Next, let’s take a closer look at .times as an iterator!

Because it iterates over a range of values, .times might seem similar to range.each.  BUT! They’re actually quite different.

Here’s the syntax:

times_iterator_syntax
Syntax for .times iterator

The syntax is similar to our plain old .times loop from earlier — except it also includes a variable.

Another key difference:  The Integer refers to the number of elements inside the collection. 

In other words, 2.times would be a loop consisting of 0 and 1.  (It doesn’t include 2.)

An example of a .times iterator:

times_iterator_example
Example of .times iterator

In this case, there are 3 elements in the collection: 0, 1 and 2.

Loop vs. Iterator Comparison

Last, we take a look at a .times loop and a .times iterator.

loop_vs_iterator1
Loop example

This is how I typically use .times. (More often than I should, to be honest…)

Here’s what the same bit of code looks like as an iterator:

loop_vs_iterator2
Iterator example

All we’re doing here is printing “dance” two times.  We’re not using i for anything.

In other words, we don’t need an iterator.  Consequently, the first example is the better solution.

Like I said, though — I use .times as a regular loop more than I should.

For some reason?  I thought you had to initialize i outside of the block.  BUT NOPE!

GOOD TO KNOW.

Summary

This lesson introduced scope, loops and iterators.

 

Scope defines when something (usually a variable) is visible to something else in a program.  When we try to use a variable that isn’t visible, we’ll get an error.

In Ruby, there are four main types of variables.  They each vary in degrees of scope.

Local variables are only visible in the block where they’re defined.

When we define a variable inside a loop, we won’t be able to call that variable outside of that loop.  In that situation, we can initialize the variable outside of the loop — because local variables created outside of a block are visible to everything in the program.

 

Loops repeat a sequence of statements.  They tell the program to do something a certain number of times, or until a certain condition is met.

An infinite loop goes on forever — or until you kill the program.

Sentinel-controlled loops depend on certain conditions being met in order to end (while, until).  In other words, the number of times it’s supposed to run CANNOT be determined beforehand.

Counter-controlled loops know exactly how many times to run — because the number of times IS determined beforehand (.times without an iterator).

 

Iterators traverse over the elements in a collection (like an array).  They usually do something with those elements.

Three types of iterators are a) .each, b) range.each and c) .times.

.each returns each value of the collection, one by one, to the block.  Iteration variable is optional (but usually used).

range.each uses a range — that is, a set of values with a beginning and an end.

.times as an iterator uses Integer to refer to the number of items inside the collection.

 

Overall, this was a good review!

I was especially glad to get clarification on .times as a regular loop and .times as an iterator.  (For some reason, I thought you had to initialize an iterator outside of the block if you wanted to use .times, hahah!)

 

JumpStart Live Day 2: Exercises

First off, I made changes to my Candy Machine Assignment based on the lessons so far.  You can find the new code on Github.

Next, here are the exercises for Day 2:

In one Ruby file, write code to solve the problems below. Your code should print out each problem statement, followed by the output from the conditional statement(s).

(Note: I used a method to collect user input.)

1.  Prompt for a number. If the number is greater than 70, print PASSING; otherwise, print NOT PASSING.

exercise_1
Exercise 1 Code

Pretty straightforward.  We collect input from the user, and convert it to an integer with .to_i.

If number >70 evaluates as true, then it prints “PASSING”.  If number is less than 70, then the program executes the code under else.

exercise_1_output
Exercise 1 Output

 

2.  Prompt for a string. If the string is equal to green, print GO, otherwise, print STOP.

exercise_2
Exercise 2 Code

Since this input doesn’t requite any conversion, it’s arguably simpler than the first exercise.

If string == "green" evaluates as true, then the program prints “GO”.  Otherwise, the program executes the code under else.

exercise_2_output
Exercise 2 Output

 

3.  Prompt for a number. If the number is even, print EVEN, otherwise, print ODD.

exercise_3
Exercise 3 Output

I used two methods here — .to_i to convert input to an Integer, and .even? to check if the user’s input is an even number.

If number.even? evaluates as true, then the program prints “EVEN”.  Otherwise, it executes the code under else.

exercise_3_output
Exercise 3 Output

 

4.  Prompt for a number. If the number is evenly divisible by 5, print MULTIPLE OF 5, otherwise, print NOT A MULTIPLE OF 5.

exercise_4
Exercise 4 Code

Once again, I use .to_i to convert user input into an Integer.

After that, I use the modulus operator (%) to check whether number is evenly divisble by 5.

If number % 5 == 0 evaluates as true, then the program prints “MULTIPLE OF 5”.  Otherwise, the program executes the code beneath else.

exercise_4_output
Exercise 4 Output

 

5.  Prompt for a number. If the number is less than 10, print ONE DIGIT. If the number is 100 or greater, print THREE DIGITS, otherwise print TWO DIGITS.

exercise_5
Exercise 5 Code

Pretty much anytime we try to do math on user input, we’ve gotta use .to_i to convert the input from a string.  So, again, that’s what I’m doing here.

Like the exercise specifies, this if-elsif-else statement first checks whether number is less than 10.  If number < 10 evaluates as true, then the program prints “ONE DIGIT”.

If not, the program checks whether number is greater than or equal to 100.  If number >= 100 evaluates as true, then the program prints “THREE DIGITS”.

If not, then the code under else is executed instead.

(Note: This code will still print THREE DIGITS, even when you get into the thousands. :P)

exercise_5_output
Exercise 5 Output

 

6.  Prompt for a jersey number. If that number is 1271, or 80, print That number is retired from the Seattle Seahawks!, otherwise do nothing.

exercise_6
Exercise 6 Code

In this case, I used the || operator to check for multiple conditions.  Only one of the conditions need to evaluate as true for the code to be executed!

Since there’s no else statement attached, the program does nothing if you don’t enter 12, 71 or 80.

exercise_6_output
Exercise 6 Output

 

7.  Prompt for a state. If the state is WashingtonOregon, or Idaho, print This state is in the PNW, otherwise print You should move to the PNW; it’s great here!

exercise_7
Exercise 7 Code

This code has a similar structure to the jersey exercise above.  That’s because I use the || operator here too.

Here’s the main difference:  If none of the conditions evaluate as true, then the program will execute code underneath else.

exercise_7_output
Exercise 7 Output

(Note: I would love to move to the PNW :P)

8.  Prompt for a one of the following: SHORTTALLGRANDEVENTI. Print out the number of ounces that drink includes (8121620 respectively).

exercise_8
Exercise 8 Code

I use .upcase for user input because conditionals are case-sensitive.  (In other words, if the user types tall, then it will automatically convert to TALL.)

The program compares the value stored in drink_size to each size.  Once a statement evaluates as true, then the code beneath that statement will execute.

If the user inputs something other than the choices outlined above, then nothing happens.  That’s because there’s no else included.

exercise_8_output
Exercise 8 Output

 

9.  Prompt for rate of pay and hours worked. Calculate gross pay. Provide time-and-a-half for hours worked beyond 40 (e.g., if you get paid $10/hr and work 45 hours in a week, you would gross $475 (40 x 10 + 5 x 15).

exercise_9
Exercise 9 Code

First, my code checks if the value stored in hours_worked is less than or equal to 40.  If the statement evaluates as true, then it calculates gross_pay as normal.

If it evaluates as false, then the program looks at elsif.

If the value stored in hours_worked is greater than 40, then it includes overtime in its gross_pay calculation.

 

exercise_9_output
Exercise 9 Output (without overtime)
exercise_9_output
Exercise 9 Output (with overtime)

 

 

10.  Rewrite the solution to the previous problem adding this modification: do not process any employee if their hours worked is greater than 60, instead display the message Please see manager.

exercise_10
Exercise 10 Code

For the initial if-statement, you just need to check whether hours_worked is greater than 60.

If the condition evaluates as true, then the program prints “Please see manager”.  It then exits out without checking the other elsif-statements.

exercise_10_output
Exercise 10 Output

 

Summary

These exercises had me practice boolean expressions and conditionals in Ruby.

I also made changes to my Candy Machine program.  These changes include better whitespace and indentation…as well as a more effective use of an if-elsif-else statement to account for multiple options the user can enter.

Some cool things I learned from JSL Day 2:

In no particular order:

  • By default, everything (except nil) returns true in Ruby.
  • A non-boolean value that evaluates as true is called a “truthy”.
  • Meanwhile, nil is a “falsey”.
  • If we write x == false || 2 || 48, 2 and 48 will always evaluate as true. (That’s why the code won’t behave how we want it to.)
  •  A second argument will only be evaluated if the first argument isn’t enough to determine the overall value of the expression (short circuit evaluation).
  •  Postfix conditionals are a way to shorten our code if we only have one test to perform. (e.g. puts "You're rad" if name == "Issa")

 

JumpStart Live Day 2: Assignment Statements, Boolean Expressions & Conditionals

JSL Day 2 covers the following:

  • Assignment statements
  • Boolean expressions
  • Conditionals.

Assignment Statements

Mostly review, but it doesn’t hurt to go over these concepts again.  (Notes here.)

We read English from left to right.  BUT!  We read assignments statements from right to left!

(Just like Japanese manga, amirite…….)

In other words, we read  x = 5 like this:  The value of 5 is assigned to the variable named x.

Likewise, x = x + 1 translates as:  The current value of x (5) is added with 1.  That sum is then assigned to variable x.

If I then write y = x, I’m saying:  The value stored inside x (6) is assigned to y.  (However, this DOESN’T mean x and y will always store the same value!)

We’ve also got a nifty thing called compound assignment statements.

Simply put, I can write x = x + 1 a shorter way — that is, x += 1 .  (This syntax can also be used for subtraction, multiplication and division.)

Boolean Expressions

These expressions evaluate as either true or false.  We commonly use them in if-elsif-else statements and while loops.

When working with booleans, it’s important to understand the order-of-operations.

I use the acronym PEMDAS to remember most of them:  Parentheses Exponents Multiplication Division Addition Subtraction.

(Although, it would probably be more accurate to write it as PE(M&D)(A&S) since M&D and A&S share the same priority.)

What Zed Shaw calls “Truth Terms” come after in the following order:

  • less than, less than or equal to, greater than, greater than or equal to
  • equal to, not equal to
  • and
  • or

We compare two values with relational operators.  They’re used on numbers and strings in Ruby.

By default, everything except nil returns true.  When a non-boolean value evaluates as true, it’s called a “truthy”.  If a non-boolean value evaluates as false (like nil), then that’s called either a “falsey” or “falsy”.

Logical operators let us combine boolean statements.   These operators are and (&&), or (||) and not (!).

(I made some flashcards to memorize Zed Shaw’s Truth Tables way back when.  So the stuff about true || false evaluating as true, true && false evaluating as false, and so on was review.)

DeMorgan’s Laws dictate that !(p && q) can also be described as !p || !q, and !(p || q) can be described as !p && !q.  In Ruby, we tend to use !p || !q and !p && !q for readability.

This lesson also touched on Short Circuit Evaluation — that is, a second argument will only be evaluated if the first argument isn’t enough to determine the overall value of the expression.

When combining relational operators with logical operators, the proper syntax looks like:
if x == false || x == 2 || x == 48
statement
end

In other words, we can’t write if x == false || 2 || 48 .

Well…we could.  It won’t give us an error, anyway.

But because objects evaluate as true in Ruby, the code won’t behave like we want it to.

Conditionals

Conditionals allow our programs to make decisions through branching.

They often take the form of if-elsif-else statements. (We can use if statements alone, but elsif and else must be paired with if.)

If a conditional includes else, then the program will execute 1 block.  If the conditional only includes if and elsif (or just if), then the program will either execute 1 block — or no block at all.

At most, the program can only execute 1 block before exiting out.

Postfix conditionals are a way to shorten our code if we only have one test to perform.

postfix_conditionals
Postfix conditional examples

 

Meanwhile, case statements only make sense to use if we’re only checking the content of a single variable.

case_example
Checking contents of grade variable and printing a message

You can also combine things together using commas, like so:

case_example_2
Combining conditions together with commas

 

Practice Problems

1. Single if-statement

Here’s the code for the first question:

question_1

1.  What is the boolean expression?  

The boolean expression is test_score > 90 — because it evaluates as either true or false.

2. Provide a value of test_score that will cause the code to print You got an A!

question1_output
A value of 91 makes the code print “You got an A!”

3. Provide a value of test_score that will cause the code to not print anything.

question1_output2
A value of 90 makes the code not print anything.

 

2. if/else statement

Here’s the code for the next set of questions:

question_2_ex_1
Example 1
question_2_ex_2
Example 2

1. What is different about the examples?

In the first example, the boolean statement evaluates as true if test_score does NOT EQUAL 90.

In the second example, it evaluates as true if test_score is GREATER THAN 90.

2. Will they work the same, even though the code is different?

No, they don’t work the same.

The first example prints You got an A! if test_score equals literally anything except 90.

In other words, a test_score of 100 or 50 or even roflcopter makes the program print You got an A!  However, if test_score equals 90, then it will print You did not get an A!

The second example only prints You got an A! if test_score is GREATER THAN 90.  If test_score is equal to or less than 90, then it prints You did not get an A!

Simply put, the second example is much better.

3. if/else statement

Here’s the code for the next set of questions:

question_3_ex_1
Example 1
question_3_ex_2
Example 2

1. What is different about the examples?

In the first example, the boolean statement evaluates as true if test_score is GREATER THAN 90.

In the second example, it evaluates as true if test_score is LESS THAN 90.

The printed messages are also swapped to reflect this.

2. Will they work the same, even though the code is different?

They work mostly the same — except for one crucial difference.

The first one prints You got an A! if you enter 90. (Because 90 is not less than 90.)

Meanwhile, the second one prints You did not get an A! if you enter 90. (Because 90 is not greater than 90.)

In other words, neither of these examples are checking whether test_score is also equal to 90.

question_3_output
Neither are checking whether test_score also equals 90

Let’s change the first example.  If we change < to <=, then the program will check whether test_score is greater than or equal to 90.

question_3_ex_1_revised
Is test_score greater than or equal to 90?
question_3_output_2
Same output!

 

4. if/elsif/else statement

Here’s the code for the next set of questions:

question_4

1. What will the output be if the user enters FedEx?

The output will be Federal Express.

2. How about usps?

The output will be Mail!  This is because conditionals are case sensitive, and carrier == "USPS" does not evaluate as true.

To get an output of United States Postal Service, you must specifically enter USPS — in all uppercase.

3. What about mailing?

The output will be Mail!  None of the other conditionals evaluate as true — consequently, the program will execute the block under else.

question_4_output
Output if variable carrier equals “FedEx”, “usps”, “USPS” or “mailing”.

Summary

This lesson covers assignment statements, boolean expressions and conditionals.

Unlike English, we read assignment statements from right to left.  We can assign the value stored in one variable to another, separate variable.  But that doesn’t mean those two variables will always have the same value.

Boolean expressions, meanwhile, evaluate as either true or false.  (Non-boolean values that evaluate as true or false are called “truthy” or “falsey” respectively.)

When working with boolean expression, we must remember the order-of-operations.  PE(M&D)(A&S) is a good way to remember the first three priority-levels.

We compare two values with relational operators.   Logical operators let us combine boolean statements.

A second argument will only be evaluated if the first argument isn’t enough to determine the overall value of the expression (short circuit evaluation).

Lastly, conditionals allow our programs to make decisions through branching.  They often take the form of if-elsif-else statements.  At most, they’ll execute 1 block before exiting out.

 

 

JumpStart Live Day 1: Exercises

First off, we’re supposed to discuss the bad style Madlibs example.

Welp…I don’t have anyone to talk about it with.

Good thing I can just type down my thoughts here, eh?  EH?  🙂

Exercise 1

Issues I see in the code linked above:

1. No comments explaining what the code does

I’d label three things: a) the initial greeting, b) the prompts asking for words, and c) the printing of the Madlib itself.

2. Inconsistent whitespace

Specifically, no whitespace around certain operators…and too much whitespace around others.The code also runs together into a single “thought” — making it difficult to read.  If we separate the code based on its function, it’d make sense to divide into three sections: a) Printing a greeting for the user, b) Collecting input from the user, and c) Printing the Madlib based on the user’s input.

Finally, the Madlib itself is crammed onto a single line, which makes it a headache to edit.  I’d separate it into multiple lines.

3. Crummy variable names

No snake_case means they’re harder to read.  Also, names like var1 don’t give any indication of what that variable contains!  Better alternatives would probably be names like name, adjective, noun, noun_2, and so on.

(Note:  There’s also a syntax error on Line 17.  It’s being triggered by the stray - hanging around at the end of Line 16.)

Exercise 2

Next, we’re asked to modify the code below for readability:

Style-Exercise
Original code we’re supposed to modify

You can see my modifications below:

Style-Exercise-After
My changes include variable names, comments, indentation and whitespace.

First, I added comments explaining what each block of code does.

Next, I changed items to number_of_foods.  That’s because the latter does a better job describing its value.  I also changed y to list_item for the same reason.

After that, I indented the if-elsif-else statement using the style outlined in the lesson.

Then, I got rid of the concatenation in the .times loop.  Instead of combining multiple strings, I interpolate the a) list number and b) list item inside one string.  (I do this by incrementing i by 1 and calling list_item.)

Lastly, I separated the foods array, the if-elsif-else statement, and the .times loop from each other.  They all have different functions within the program, so it made sense to divide them into different “thoughts”.

Exercise 3

Now I’m supposed to make modifications to my own Madlibs program.

You can see my original code on Github.

Here’s my new code:

Madlib-Modified
Revised Madlib based on JSL Day 1

First, some basic simplification:

I realized my original use of concatenation in the ask method wasn’t strictly necessary.  So, I nixed that…and added an extra space to prompts through the program.  I also deleted return answer, since Ruby automatically returns answer regardless.

After that, I changed the while loop.  Instead of comparing number to number.to_i.to_s, I convert the user’s input to an integer right away…and then check if number equals 0.

Why?  Because, if the user enters the number as a string, it’ll get converted to 0.

ALRIGHT.  Now that’s done.   Let’s get ~stylish~.

To make better use of whitespace, I divided the code into four sections:

  1. Initial ask method
  2. Printing prompts and collecting info
  3. while loop
  4. Printing the Madlib

Basically, I separated “thoughts” into their own “paragraphs”.  (Hopefully, it’s easier to read this way.)

After that, I changed a couple of variable names.  Variable plural_noun is now noun_plural (to match the naming convention I used for the other variables).  In the ask method, question is now prompt (since that’s a better descriptor of the argument).

My while loop was already indented, so I left that alone.

Finally, I added comments to each section.  These comments are simple explanations of what the code does (and not how it does it).

I admit, Learn Ruby the Hard Way makes me want to go into excruciating detail sometimes.  But if I’m writing for someone else’s benefit, then simple is better.

Exercise 4 – Bio Program

Finally, I’m supposed to create a program that:

  • Accepts input from the user
  • Prints that information in bio form
  • Uses up to five attributes about the person
  • Outputs a paragraph based on the user’s input
  • OPTIONAL: Uses some calculations to make your program more interesting.

Here’s what I did.

Bio_Program_Code
Bio Program Code

Here’s what it looks like:

Bio_Program_Output
Bio Program output!

Summary

These exercises had me practice Ruby style.  I corrected bad examples, modified my own Madlibs code and wrote a short Bio Program.

The main things I paid attention to were: whitespace, indentation, variable names and comments.

Some cool things I learned from JSL Day 1:

In no particular order:

  • You can actually open files with Atom through the terminal
  • For string concatenation, use << when working with lots of data
  • % notation lets you make arrays of strings
  • We should use snake_case for directories and files too
  • As of Ruby 2.4.0, we use Integer instead of Fixnum

 

JumpStart Live Day 1: Keyboard Input & Strings

Today, I looked over the videos/lessons about Keyboard Input and Strings.

It’s mostly review, but I want to truly internalize these fundamentals.  So, I’m summarizing them here!

This section touches on collecting input from the user.

  • gets – Takes a line of data from the keyboard (stands for “get string”).  Anything the user enters (including numbers) are stored as a string.  Note: Lines end with a newline (\n) by default.
  • chomp – Removes the \n at the end of a line.

So, what if you don’t want the data stored as a string?  You convert it!

A couple of examples:

  • .to_i – Converts a string into an integer.  If there is NO valid integer at the beginning of a string (e.g. a21), then it converts to 0.  Characters at the end of an integer are ignored (so 21a converts to simply 21).
  • .to_f – Converts a string to a float (aka a decimal value).  If there is NO valid float at the beginning of a string (e.g. a21), then it converts to 0.0.  Extra characters at the end of the float are ignored (so 21a converts to 21.0).

 

Meanwhile, this section talks about strings in Ruby.

Strings are objects that hold a sequence of characters.  We create strings with either double of single quotes (e.g. "hello" and 'hello').

  • Double quotes
    • String interpolation:  YES
    • Escape sequences: YES
  • Single quotes
    • String interpolation: NO
    • Escape sequences: NOT REALLY (\\ is the only exception)

Hey!  Speaking of escape sequences…here are a few common ones:

  • \n – Newline (moves to the next line)
  • \\ – Single backslash
  • \" – A double quote
String-interpolation3
Escape sequences with double and single quotes!

 

What about string interpolation?  Well, that lets us tell Ruby to read bits of code inside a string.

String-Interpolation4
Double quotes interpolate strings.  But…Single quotes do not!

Now, let’s touch on string concatenation.

That’s a fancy-pants way of saying “we can combine strings together”.  To do that, we use the + or << operators.

Couple of things to remember:

  • + – Ruby creates a new string in memory when we use this.
  • << – Ruby modifies the original string.

In other words, you want to use << when working with lots of data.  (The + operator will slow things down, since it’s making a bunch of new strings.)

Concatenation-1
Concatenation with +
Concatenation-2
Concatenation with <<

Meanwhile, the output is the same:

Concatenation-output
Same output!

The last thing this lesson summarizes is % notation.

It’s a method that lets you make arrays of strings.

  • %w – Creates a non-interpolated array of strings
  • %W – Creates an interpolated array of strings

 

Notation
Making arrays of strings with % notation

Summary

We can collect and modify a string from the user with gets.chomp.  Anything the user enters is automatically stored as a string.  Certain methods (like .to_i and .to_f) can convert strings into other data types.

Strings are objects that store a sequence of characters.  Escape sequences let us encode characters that are otherwise difficult to type.

We can interpolate (have Ruby read code inside) and concatenate (add) strings.  Double quotes enable interpolation and escape sequences  Single quotes do not.

Creating arrays of strings can be done with % notation.  %W enables interpolation.  %w does not.

JumpStart Live Day 1: Ruby Types

This section details Ruby types.

Everything in Ruby is an object!

And these are the 7 data types covered in the lesson. (Note: I’ve included links to each type’s documentation.)

Data Type Description Example
String Anything surrounded by single or double quotes "hello"'hello'
Integer A number with no decimal 10-7
Float Real value (decimal) 0.5
Array An ordered list [5, 0, 1]
Symbol A named object :apple
Hash A set of key, value pairs { A: 2, B: 3, C: 1}
Range A set of values with a beginning and an end* (2..6)

*Reminder: (2..6) is inclusive, (2...6) is exclusive.

If we’re not sure about an objects class, the .class method can tell us.  Like so:

Types
Identifying data types with the .class method!

I’m using Ruby version 2.2, so 32.class returns Fixnum.

If I were using at least 2.4.0, it would return Integer instead.  They mean the same thing — that is, a number with no decimal.

JumpStart Live Day 1: Workflow

First, I learned about workflow.  The lesson included a short video explaining certain concepts:

WORKFLOW

  • Splitting your screen
    • If you own a Mac, Moom lets you work with a split screen.
    • (Note: Other alternatives are listed here.)
    • A split screen lets you easily jump between writing and running code.
  • Opening terminal
    • Teaches how to open terminal
  • Terminal basic commands
    • Some basic terminal commands, such as pwd and cd.
    • (Note: I studied the commands in LRTHW’s Appendix A.)
  • Using irb
    • irb is basically a sketch pad that lets you safely test Ruby code
    • You activate it by typing irb in the terminal
  • Atom + Terminal
    • You can actually open files with Atom through the terminal.
    • Just type “atom” plus the file name.
    • Like so:
Atom-Terminal
Telling Atom to open a Ruby file via the terminal!

I legitimately didn’t know about this.  Mind = Blown.

…WHAT A TIME TO BE ALIVE.

Atom-Terminal-2
Atom went straight to it!  NEAT.

 

 

JumpStart Live Day 1: Ruby Style

The next video talked about Ruby Style.  Here are the basics:

  • File naming
    • Use snake_case when naming directories and files
  • Whitespace
    • Code should be separated into “thoughts”.
      • If you have two, unrelated blocks of code — put a line between them!
    • Single space on both sides of most operators
    • Single space after all commas and colons
    • Use spaces around { and } (except for string interpolation)
    • All code between do and end should be indented.
    • All code inside an if, elsif, or else should be indented.
  • Variable Names
    • Use snake_case (similar to file naming)
    • Should clearly describe what they hold
      • No single-letter variables (except for iterators)
  • Comments
    • Use comments to describe your code.
    • Describe what the code does, not how it does it.
  • Style Guides

 

Bad Style vs. Good Style:  Examples

Style-1
Example 1

Good style changes:

  • Variable names (from i to num)
  • Indentation between do and end block
  • Comments
Style-2
Example 2

Good style:

  • Adds whitespace before and after operators
  • Adds indentation to if-elsif-else statements
  • Changes variable names (from x to animal)
  • Includes comments
Style-3
Example 3

Good style:

  • Adds whitespace
    • before and after operators
    • between unrelated blocks
  • Adds indentation
    • to if-elsif-else statements
    • between do and end block
  • Changes variable name (from i to num)
  • Includes comments
Style-4
Example 4

Good Style:

  • Indents if-elsif-else statements, including nested ones
  • Adds whitespace
    • before and after operators
    • between unrelated blocks
  • Includes comments for each block

JumpStart: Madlibs

Alright, how about some MadLibs today?

Let’s break down my code, starting from the top!

MadlibCode1
Defining method to collect user input, and printing a string.

First, I defined an ask method.  This method accepts a question (in the form of a string) as an argument.  It prints the question and an extra blank space.  Then, it assigns user input to local variable answer.  After that, it returns answer so we can use it outside of the method.

MadlibCode2
Collecting user input with the ask method, and checking if “number” is an integer.

Next, I collected user input with my ask method.  Prompts (as strings) are entered as arguments.  The user’s input is assigned to its respective variable.

For fun, I made a while loop that checks whether the value assigned to number is an integer.

Basically, as long as the input assigned to number does NOT equal an integer that’s been converted to a string, then the MadLib program will keep prompting the user to input a numerical value.

Here’s what it looks like:

MadlibWhileLoop
While loop in action.  It breaks when the user enters an integer.

And now for the MadLib part:

MadlibCode3
MadLib that substitute’s answers with user’s input.

I printed variable strings.  These strings include alll variables assigned to the user’s input.

Here’s an example of what that looks like:

MadlibOutput
MadLib output. It collects input from user, then prints a MadLib based on the user’s answers.

Since this assignment comes from an earlier chapter, it’s a lot simpler than things like the candy machine or account generator.

I’ll be revisiting it soon, though.  See you then! 🙂