App Academy W3D2

Yizhe Wang
8 min readFeb 25, 2020

Things are getting more and more challenging these days.

We only get a taste of App Academy for the previous two weeks. The real thing is much more stressful and time consuming than I’ve expected.

Learned

  1. Fixnum like 1, 2, 1.0, 20.0 are immutable. No one can alter the value in the memory, but we can relink it to somewhere else, say var = 2, we can use “=” to reassign a mem location for it, but we can not change the value in the original mem location.
  2. symbols are also immutable, a = :string, a[0] = “k” won’t work, but we can use the getter a[0] to return the “s”, it’s just we cannot change it.
  3. Strings/Arrays are mutable, which means that we can shovel things into it. string = “this is interesting”, say it has a object_id = 0001, if we string << “?”, when we check string again, it’s mutated, it’s now “this is interesting?” and if we check the object_id, it’s gonna be the say as the original one. We are making changes in place. Same for array here. but one thing to put in mind is that the “=” in the most of the cases will assign new mem locations, which means not mutating the original mem slot, but reassign the pointer to somewhere else. x = “string1”, y = x, if we x << “100”, y will be “string1100”. but if we go with y = “string1”, x = y, y += “100”, now x is still “string1”, because y has been reassigned instead of change in place. ***concat do the same thing as +=, but it’s like shovel, mutating the original array/string. dup and clone are the same. ***a = [1,2,3] a.concat([4,5]) will be [1,2,3,4,5], but if we shovel into a, the result will be [1,2,3,[4,5]]
  4. dup only create a top level reference duplication
  1. “=” may not always mean relink to another mem location, because we have hash[:key] = :value, we are not making a new hash at all, we are making changes in place. This is related to the designed “[]=”funtion of hash, which is not the build in Object “=” function. Things might be different here. But for now I think the examples down there are not clear enough. We use “=” to allocate a new place in mem for the key value pair, makes perfect sense for me. And we use setter to give my_cat a new name, we are also saying that the @name instance variable is now reassigned to a different mem location, which also make sense.

4. “||” : a || b is a test, if a is not nil return a else return b, simple and easy

5. Array.new(default = 1) is creating a new empty array, equal to array = []. but we have to be very careful when we initialize multiple dimensional arrays. Say, we want to create a 2-d array, by using arr = Array.new(n, []), this could work, and will give a n subarray array. but the problem is all these subarrays are pointing to the same mem location, which will bring trouble if we use mutating functions like “<<” or push, or delete, so be more careful when dealing with this kind of cases, but we can always relink the subarrays by say arr[0] += [1,2,3], now the first element of the array has been unlocked from that exact mem location and assigned a new one, which won’t mess up other elements of the array *** the problem with this approach is that we are creating new stuff in mem if we use +=, this is gonna be a waste of mem.

6. Hash.new([]). Why this won’t work.

hash = Hash.new {[]}: for this one, when we hash[:new_element], ruby will search the hash and see there is no such a key, what would it do? it will run the things in the {}, and give you a [].

hash[:a] => []

hash[:a] << :a

hash[:a] => []

hash => {}

hash[:a] = :b

hash => {:a=>:b}

hash = Hash.new([]) basically is using a same reference of an empty array to be the value, when initialize all the future keys.

hash = Hash.new([])
hash[jack] # nil reasonable, we haven't add anything to it yet.
hash[jack] << ["is a guy"]hash # => {}
#but if we check hash[jack] it's gonna return ["is a guy"]
# but the problem is that if we try to see other values, say hash[will], it will be "is a guy", which definitely isn't what we expected.
#the reason for this is that the "<<" method is making change to the original empty array we use to initialize our hash, we change that, every key, even if the hash doesn't have the key, is gonna have a shoveled value. We don't want that. so we use hash = Hash.new {|hash_self, key| hash_self[key] = []}
now when we use the hash[key] it's actully calling the previous line to create a key for the hash, and even we didn't assign a value, the key => nil pair has been there. Interesting! has to remember this.

7. never use a global variable, $var_name is just not something good to implement in code. Will be very dangerous.

8. @, @@, CONST, $var_name

9. block scoping, block doesn’t have the scope gate thing, it will take in the variable “x” we defined earlier. things we created in the block, won’t be accessible outside of the block.

consider this one:x = 2def func    x *= 2endbut let's look into something else

funtions taking in strings will actually create a reference for the argument, and this argument is like x = “string” y = x, now we use y as our parameter. Frankly speaking the reason why computer scientist use this kind of tacnic I still don’t know. Maybe it’s to avoid unnecessary mutation of a variable. Anyway, we can see from the example up there, it’s pretty clear.

  • ** Even we use dup, we cannot be too sure, when we dup the matrix, we are just giving the **argv thing a new pointer, but we are actually not reassigning all the mem location of the granular level values. We tap into the dup, make changes there, it’s still gonna influence our own matrix.
this won't work, because we have the scope gate, and we cannot use the outside variables except for the global ones like $some_var, 
actually:
def func $some_var *= 2endwill make change to the global var.

if / while conditions will inherit the scope of the method that uses it, and the vars defined in the if condition or while loop can also be used in the method. it’s kind of shared.

10. regex for zip : /[1–9][0–9]{4}/

11. don’t modify the argument when unnecessary, users, other programmers won’t want you to mutate the original data, create a dup, make changes to it and return the dup, don’t make changes in place. That’s understandable.

12. Don’t chain too many code together, don’t let one class be used too many times. Let the classes be separate ones, and don’t let them know too much about each other. Just give necessary apis to the outside world.

13. in HTML, it might be hard to print things like “&” or French vowels, but there is definitely a walkround.

14. href can take a #top-of-page, which will be the anchor we created some where in the doc that’s called #top-of-page

15. Vscode

16. “==” checks the value. “.eql?” check the hash, which means 3.eql?(3.0) returns false. now we are not only checking the value but also the type. all the types has a .hash method, but will return different things.

“.equal?” checking if they are the same thing, same mem location?

“===” check if the left is a instance of the right

3 === Integer => true

“string”===String => true

other than this it works almost the same as “==”, and this one can be re-written into something more customized when we need to.

17. Interesting Hash

cat = Cat.new(“name”)

other_cat = Cat.new(“name”)

hash[cat] = “abc”

hash[other_cat] => nil

the reason why this happens is the hash check if cat == cat ?

no, because we don’t have a “==” method in our Cat class, ruby will use the Object level “==” to check their object_id, which are different, so hash will not recognize them as the same thing. but we can create one “==” for our Cat class by saying that if cat.name == cat.name then we return true to this cat ==other_cat comparison. if we do that

hash[other_cat] will be “abc”

def swap(x, y)

x, y = y, x

end

we are assigning new values, new mem locations inside of the func, but we are not making changes to the original ones.

18. We cannot swap in ruby, because we cannot manipulate in a memory level, what ever passed inside our swap won’t influence outside world because of the scope gate thing. Clang can.

19. interesting part :

hash save key by value not reference

but hash save values by reference

To do list

  1. understand the difference between “+=”, “<<”, “.concat”
  2. what is module
  3. when you define a method : def my_method(parameter1, parament2),
  4. arr = [1,2,3], arr[5] = nil, arr => [1,2,3,nil, nil, nil]
  5. when we print any object, there is an to_s function called on it. It’s from system Object class, but we can definitely change it for our own class.

--

--