Permalink
Browse files

merging upstream

  • Loading branch information...
danman01 committed Jul 9, 2018
2 parents cbde68c + 8752b07 commit c60c9f3a376d3bb8330578503cd04a5539ce8097
@@ -0,0 +1,150 @@
## LESSON: [ruby-enumerable-builtins](https://git.generalassemb.ly/ga-wdi-boston/ruby-enumerable-builtins)

---

**2018-07-05**

### OBJECTIVES

By the end of this, developers should be able to:

- Define “list” and give two examples of lists in Ruby.
- Diagram the flow of Enumerable methods as invoked through concrete classes.
- Give two examples of methods defined in Enumerable and available on all
three of Range, Array, and Hash.

### VOCABULARY

**Namespace**: For a give scope, the collection of references (ie names) and associated values. For instance, when you make a variable `pet = "Inland Taipan"` in a script, the namespace of your script now has a `pet` name in it.

**Module**: A collection of methods and constants in a namespace. The methods in a module may be instance methods or module methods. Instance methods appear as methods in a class when the module is included, module methods do not. Conversely, module methods may be called without creating an encapsulating object, while instance methods may not. Modules are never used directly to instantiate objects. Instead, they are "mixed-in" to `class` declarations so that a given class can inherit properties and methods from the module. This concept of a **Ruby** module is somewhat distinct from the concept of a **Javascript** module.

**Mixin**: A way to include all of a module's properties and methods inside another class / module. In **Ruby**, we simply put a `include <Module name>` line directly in the class where we want to "mix-in" a module.

**List (*Abstract Data Type*)**: An ordered collection of values that can be set and get by index.

**Enumerable Mixin**: A **Ruby** `Module` that provides standard methods and properties that can be used by all list-type variables such as `Array`, `Range` and `Hash`, or even if your own custom classes that implement list-type objects.

**Array**: A list of objects who's values are defined at the time of instantiation using either `Array.new` or the `[<value_1>, <value_2>, etc]` syntax.

**Range**: A list of objects from some start value to some end value, of the form `(<start value>..<end value>)`, `(<start value>...<end value>)`, or `Range.new(<start value>, <end value>)`. A `Range` object does not actually calculate the values in the list until you run the `.to_a` method on it, convering the `Range` to an `Array`, which can help save memory such that values are only calcualted right when the `Range` is about to be used, as opposed to being calculated when they are declared as in an `Array`. *NOTE: ranges are `start value` inclusive and `end value` exclusive if you use `...`, but is `start value` inclusive and `end value` inclusive if you use `..`*

**Hash**: A list of key and value pairs where the keys are all unique. Also called associative arrays. You can use any type of value as the key but `symbol` types are reccomended as they allow for much faster lookup of associated values than using other types such as `String` type keys. `Hash` objects are declared using either `Hash.new` or `{ :<symbol name 1> => <value 1>, :<symbol name 2> => <value 2>, etc }` notation.



### NOTES

- In `class`ical object oriented patterns, objects inherit methods and properties from their class declaration, and classes themselves can inherit from other classes. This chain of inheritance can be quite deep and hard to follow the more layers of inheritance there are.
- Mixins allow for us to have "shallow inheritance", ie instead of a class inheriting from a class inheriting from a classs.... that gives our object some methods and properties, we can just make a new class and "mix-in" the properties and methods declared in a module.
- `Enumerable` is a built-in module in **Ruby** that is "mixed-in" to `Array`, `Range`, and `Hash` types. This provides those types with all of the expected list methos and properties, and avoids some kind of complex deep inheritance structure where say `Range` would inherit from `Array`.
- **Ruby** allows you to import values from the namespace of a module, script, or other closed block of code by using the `::` namespace operator (see below)

### EXAMPLES

#### Accessing Namespaces

- you can access namespace variables using the `::` operator:

- ```ruby
class MyClass
RANDOM_VAL = 300
def initialize(thing1, thing2)
@thing1 = thing1
@thing2 = thing2
end
# you can access the `RANDOM_VAL` value
puts MyClass::RANDOM_VAL
# RETURNS:
# 300
# => nil
```
- note than only constants (non-method variables) can be accessed in the namespace and constants must be declared in all caps, ie `RANDOM_VAL`

#### `Enumerable::each_with_object`

- [`each_with_object`](https://ruby-doc.org/core-2.1.0/Enumerator.html#method-i-each_with_object) allows you to iterate through an enumerable variable and for each value, accumulate som change in an object of your choosing. Let's break down what is happening in each step of this method:

- ```ruby
range = 5..115
altogether = range.each_with_object(Hash.new(0)) do |el, hash|
hash[:even] += el if el.even?
hash[:odd] += el if el.odd?
hash[:div3] += el if (el % 3).zero?
hash[:all] += el
end
```
1. `each_with_object` takes a single argument, the object you want to accumulate values within (called `memo` short for **memory** in **Ruby**). In this case, it's a `Hash` which will provide a default value of `0` for new keys

2. We also pass a block to `each_with_object` using the `do` keyword, and the block recieves to arguments from `each_with_object`:
- the current element in the utterable - we called it `el`
- the object / `memo` we are accumulating on - we called it `hash`

3. Inside the block, we have 4 conditions for adding values to keys in `hash`. It is important to note that each key does not exist at first in our empty `hash`, and when they are first added, they have a value of `0`.

- if `el` is even, add it's value to `hash[:even]`
- if `el` is odd, add it's value to `hash[:odd]`
- if `el` is divisible by 3, add it's value to `hash[:div3]`
- add every single value to `hash[:all]`
4. Finally, the `hash` is returned from the method with keys `even`, `odd`, `div3`, and `all` where values for `range` have accumulated sums according to the rules above.


#### `Enumerable::reduce
- `reduce` allows you to also accumulate values in an object while iterating through an enumerable type. The syntax is very similar to `each_with_object` with some key differences. Let's break down what is happening in each step of this method:
- ```ruby
alphabet = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
h: 8,
i: 9,
j: 10,
k: 11,
l: 12,
m: 13,
n: 14,
o: 15,
p: 16,
q: 17,
r: 18,
s: 19,
t: 20,
u: 21,
v: 22,
w: 23,
x: 24,
y: 25,
z: 26
}
reduced_hash = alphabet.reduce({keys: [], values: []}) do |memory, (key, value)|
memory[:keys] << key
memory[:values] << value
memory
end
```

1. `reduce` takes an initial value that will be accumulated in, in this case a hash with two keys that have empty arrays as values: `keys`, `values`
2. the block for `reduce` gets passed two positional arguments: the `memory` object which is being accumulated on, and the current value of the enumerable object that is being iterated. In a `Hash`, iteration returns `key` `value` pairs, which can be directly broken into two variables in the arguments of the block using `(keys, value)`
3. we then push the values of the current `key` and `value` to the approriate `memory` hash keys
4. **REMEMBER that you must return the accumulator hash `memory` at the end of the block or else it's changed values won't actually be saved for the next iteration**

- let's compare the `reduce` implementation to using `each_with_object` for the same task:

- ```ruby
reduced_hash_two = alphabet.each_with_object({keys: [], values: []}) do |(key, value), memory|
memory[:keys] << key
memory[:values] << value
end
```

- notice how the input arguments are in reverse order in `each_with_object`
- also, you don't need to return `memory` at the end of the block for it to be saved!
Binary file not shown.
@@ -13,7 +13,7 @@ By the end of this, developers should be able to:

### VOCABULARY
**module**: a collection of methods encompassed in the Module keyword. Can also be used as a namespace (`Math::PI` will return the constant `PI` in the `Math` module / namespace. Why not put `PI` in the global namespace?)
-
-

**mixin**: adding functionality to a class by including a module
### NOTES
@@ -115,4 +115,3 @@ s4.between?(s1, s3) #=> false
s4.between?(s3, s5) #=> true
[ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
```

Binary file not shown.
@@ -0,0 +1,36 @@
## LESSON: [ruby-object-inheritance](https://git.generalassemb.ly/ga-wdi-boston/ruby-object-inheritance)

---

**2018-07-06**

### OBJECTIVES

By the end of this, developers should be able to:

- Diagram the Ruby method lookup chain
- Write a class which inherits from another class.

### VOCABULARY

**Inheritance**: They way objects inherit methods and properties from their parent classes.

**Superclass**: Classes themselves can inherit from other classes, and these parents classes of classes are called superclasses.

**Method Lookup Chain**: When a method is called on an object, it will look within it's own instance for methods with that name, and if not found, will go to the parent class and try to find the method, and if not found, go to that class' parent and try to find the method etc until either the method is found, and then run, or it is not found, returning `nil` / `undefined` .

**Overriding:** When a class inherits from a superclass and the superclass has a method that is also named in the child class, the child class is the method that gets called on objects, ie it overrides access to the superclass method and uses it's own method of the same name instead.

### NOTES

- note about lesson

### EXAMPLES

#### Code Topic

- description of code block:
- ```js
// code goes here
```

Binary file not shown.
@@ -0,0 +1,23 @@
## LESSON: [ruby-object-model](https://git.generalassemb.ly/ga-wdi-boston/ruby-object-model)

---

**2018-07-06**

### OBJECTIVES

- Give two reasons why inheritance and Mixins are desirable.
- Write a mixin.
- Describe the difference between inheritance, composition, and mixins.

### VOCABULARY

* Inheritance - When one classes gains functionality from another
* Composition - Complex objects being built from less complex objects
* Mixin - Reusable blocks of code

### NOTES

* If an object `is-a`nother object, you want inheiritance
* if an object `has-a` object, you want composition
* if an object `behaves-as` other objects you want a mixin
Binary file not shown.
@@ -0,0 +1,124 @@
## LESSON: [ruby-object](https://git.generalassemb.ly/ga-wdi-boston/ruby-object)

---

**2018-07-05**

### OBJECTIVES

By the end of this, developers should be able to:

- Define a class for an object in Ruby that assigns attributes in the `initialize` constructor.
- Create an instance of an object in Ruby using `.new`.
- Write setter and getter instance methods for Ruby objects.

### VOCABULARY

**Abstract Data Type**: A description of a data type that is abstracted away from how it is implemented in any language in particular ie a logical representation of a data type that can be implemented in a language-independent way. For example, a **list** is an Abstract Data Type which is defined as a collection of values that are ordered by Index. In **Javascript** and **Ruby**, lists are implemented as `Array` types with particular properties and methods, albiet **Javascript** and **Ruby** `Array`s have different properties and methods, but share basic structure as defined in the Abstract Data Type. In **Python**, a **list** is implemented as a `List` type, again with somewhat unique properties and methods, but sharing the same basice structure as well.

**Object**: An **object** is an Abstract Data Type that consists of a collection of properties and methods that are indexed by key, ie key-value pairs. Objects can be used to model real world objects.

**Object Constructor:** A function / method that runs when you instantiate a new Object either from a class (**Ruby**), or from a Constructor Function (**Javascript**), giving the new instance particular initial properties and methods.

**Class:** A blueprint for an object, defining the properties it receives on instantiation, as well as instance methods. Some language such as **Ruby** fundamentally use classes to define objects. In fact in **Ruby**, objects can only be defined using classes and instantiation from classes. In **Javascript**, objects are fundamentally built using Constructors and Protoytypes, but recently, the `class` keyword as syntactic sugar was added to **Javascript** to allow people from languages that use classes to feel more comfortable with **Javascript**, however under the hood, **Javascript** fundamentally uses Constructors and Prototypes.

**Setter:** An instance method that allows you to set values of properties in a class. In **Javascript**, you can directly set existing properties on an object or make new one. In **Ruby**, object properties are private, so you need to define a setter method if you want to set them.

**Getter:** An instance method that allows you to get values of properties in a class. In **Javascript**, you can directly get existing properties on an object. In **Ruby**, object properties are private, so you need to define a getter method if you want to get them.

**Mutability:** A variable is mutable if it's value / shape can be changes after it's created.

### NOTES

- **Ruby** does not allow for object literal notation. Objects are only created by first creating classes, then using `<ClassName>.new`
- Object-oriented langauges such as **Ruby** strictly use classes to generate objects, and usually have objects representing nearly every type of value. Other language may not be strictly Object-oriented, but can support object-oriented programming styles, such as **Javascript**, which uses Constructor Functions and Prototypes under the hood, but provide the `class` keyword to create objects as well
- There are two ways to interact with **Ruby**
- running script files using `ruby <script file name>`
- you can use `binding.pry` inserted into scripts to define a debugging breakpoint in your code, where you can access all of the scope of the script up until that point and run **Ruby** commands interactively.
- `binding.pry` cannot be the last line in a script. Add `""` to the end of the script after `binding.pry` if you want `binding.pry` at the end.
- you can exit out of a `binding.pry` breakpoint and keep running the code in a script using the `continue` keyword
- running a **Ruby** REPL:
- `irb` the built-in REPL for **Ruby**
- `pry` the more modern REPL for **Ruby** with some [updated features](http://pryrepl.org/)

### EXAMPLES

#### Javascript Supports Classes (*but they are syntactic sugar*)

- in **Javascript**, we normally make Objects using Constructors:

- ```js
function Dog(name, breed) {
this.name = name
this.breed = breed
}
```

- and Prototypes to add instance methods:

- ```js
Dog.prototype.bark = function () {
console.log('bork.')
}
```

- you can also use the `class` keyword to achieve the same thing:

```js
// this is how you make a class definition
class Dog {
// notice how the contents of the Constructor
// function go in this class method called
// `constructor`
constructor() {
this.name = name
this.breed = breed
}
// instead of adding instance methods using
// `prototype`, you can add them directly
// in the class defintion as class methods
bark () {
console.log('bork.')
}
}
```

- both work **exactly the same** as far as the end result. You can instantiate a `Dog` object in both cases using:

- ```js
const fido = new Dog('Fido', 'Dobberman')
```

#### Javascript Classes vs Ruby Classes

- **Javascript** class:

- ```js
class Rectangle {
constructor(length, width) {
this.length = length
this.width = width
}
area () {
return this.length * this.width
}
}
```
- **Ruby** class:
- ```ruby
class Rectangle
def initialize(length, width)
@length = length
@width = width
end
def area
@length * @width
end
end
```

- Notice how similar the **Javascript** class syntax is to the **Ruby** class syntax. In fact, they are almost directly translatable from one to the other, simply by replacing keywords and block demarcations.
Binary file not shown.
Oops, something went wrong.

0 comments on commit c60c9f3

Please sign in to comment.