Last active
October 13, 2021 14:46
-
-
Save jules27/3668380 to your computer and use it in GitHub Desktop.
Revisions
-
jules27 revised this gist
Apr 7, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ ## Introduction After working through exercises for learning Ruby as part of preparation for the upcoming Dev Bootcamp (note: no longer exists), we had a friendly discussion about the exercise to implement a Reverse Polish notation calculator. At the end of discussion, one of the staff members, Jesse, posted his solution to students. The solution is well-designed, clean, and easy to read. However, one line of code caught my eye: -
jules27 revised this gist
Sep 7, 2012 . 1 changed file with 16 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -35,7 +35,7 @@ p some_other_value # => [13, 12, 11] This is pretty straightforward. `some_value` is constructed as expected, and `#reverse` does its job of reversing the resulting array. `some_other_value` contains `end.reverse`, and we see that line does essentially the same thing as `some_value.reverse`. It appears that you can call array methods on the `end` keyword, or more accurately, call methods on the object returned by the `end` keyword, and that method gets called once at the end of the loop. Let's try some more things. ```ruby first_element = [1,2,3].each do @@ -57,7 +57,7 @@ middle_element = [1,2,3].each do p middle_element # => 2 ``` Hey, that's pretty neat. So does `end` actually return an array? ### Calling Object methods @@ -80,24 +80,28 @@ This confirms that `end` is an array in this definition, and that it's also poss What about `?` and `!` methods? (for lack of better word) ```ruby a = [1,2,3] reversed = a.each do end.reverse p reversed # => [3, 2, 1] p a # => [1, 2, 3] reversed_again = a.each do end.reverse! p reversed_again # => [3, 2, 1] p a # => [3, 2, 1] am_i_empty = a.each do end.empty? p am_i_empty # false ``` While it seems that `end.reverse` and `end.reverse!` have the same result, the `reverse` method has left the variable `a` untouched, and the `reverse!` method has modified it. ### Daisy-chaining of calling methods using `end` It's also possible to continuously call methods using the object returned by `end` in a daisy-chain fashion. ```ruby chained_map = [1,2,3].map do |int| @@ -110,13 +114,13 @@ chained_map = [1,2,3].map do |int| p chained_map # => [33, 32, 31] ``` In this example, each iteration increases each value in the array by 10, so at the end of the third iteration, we get `[31, 32, 33]`. The last `end.reverse` reverse that result, so by the last iteration, we get `[33, 32, 31]`. ### Checking the returned class type Most of what I've written so far has been applying the `end` keyword to the Array object, but we can certainly do the same for other objects. When I first raised the question, I wondered if the reason that you can call Array methods on the object returned by `end` is because the starting object (`inject([])`) is an array. The correct answer is that methods called on the object returned by `end` operates on the **ending object**, not the starting object. ```ruby type_test = [1,2,3].inject(Hash.new(0)) do |result, element| @@ -139,6 +143,6 @@ In the first definition, `type_test` has the resulting value of `{}`, an empty h ## Conclusion I never imagined that you can call methods on the `end` keyword, or more precisely, on the object returned by the `end` keyword. Jesse says: every valid Ruby expression returns something. You can assign that something to a variable, call methods on it, etc. I hope this gist was helpful to some of you. Thanks for reading! -
jules27 revised this gist
Sep 7, 2012 . 1 changed file with 12 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,8 @@ ## Introduction After working through exercises for learning Ruby as part of preparation for the upcoming <a href="http://devbootcamp.com">Dev Bootcamp</a>, we had a friendly discussion about the exercise to implement a <a href="http://socrates.devbootcamp.com/exercises/31">Reverse Polish notation calculator</a>. At the end of discussion, one of the staff members, Jesse, posted his solution to students. The solution is well-designed, clean, and easy to read. However, one line of code caught my eye: ```ruby tokenize(array).inject([]) do |stack, token| @@ -57,7 +57,7 @@ middle_element = [1,2,3].each do p middle_element # => 2 ``` Hey, that's pretty neat. So does `end` essentially behave like an array? ### Calling Object methods @@ -73,7 +73,7 @@ my_id = [1,2,3].each do p my_id # => 70236355699360 (result is different every time) ``` This confirms that `end` is an array in this definition, and that it's also possible to call methods from its parent class. ### Calling `?` and `!` methods @@ -95,7 +95,7 @@ p am_i_empty # false It seems that `end.reverse` and `end.reverse!` have the same result, which makes sense because the methods are called at the end of the loop, and the resulting array is returned. ### Daisy-chaining of calling methods using `end` It's also possible to continuously call methods using `end` in a daisy-chain fashion. @@ -114,7 +114,9 @@ In this example, each iteration increases each value in the array by 10, so at t ### Checking the returned class type Most of what I've written so far has been applying the `end` keyword to the Array object, but we can certainly do the same for other objects. When I first raised the question, I wondered if the reason that you can call Array methods on `end` is because the starting object (`inject([])`) is an Array. The correct answer is that methods called on `end` operates on the **ending object**, not the starting object. ```ruby type_test = [1,2,3].inject(Hash.new(0)) do |result, element| @@ -129,9 +131,11 @@ p type_test_again # => Fixnum ``` Here we see that even though both definitions have the same starting object `Hash`, the resulting classes are different. In the first definition, `type_test` has the resulting value of `{}`, an empty hash, and thus returns the class `Hash`. The second definition `type_test_again` has the resulting value of `3`, so it returns the class `Fixnum`. (Thanks to Arne for pointing this out!) ## Conclusion -
jules27 created this gist
Sep 7, 2012 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,140 @@ ## Introduction After working through exercises for learning Ruby as part of preparation for the upcoming <a href="http://devbootcamp.com">Dev Bootcamp</a>, we had a friendly discussion about the exercise to implement a <a href="http://socrates.devbootcamp.com/exercises/31">Reverse Polish notation calculator</a>. At the end of discussion, one of the staff members, Jesse, posted his solution to show the students. As expected, the solution is well-designed, clean, and easy to read. However, one line in his code caught my eye: ```ruby tokenize(array).inject([]) do |stack, token| <...> end.pop ``` You can do *what* with the `end` keyword? I was given some pointers to ponder about, so I spent some time playing with what we can do with `end`. ## Exploring the `end` keyword ### Calling Array methods First, compare these two array definitions: ```ruby some_value = [1,2,3].map do |int| int + 10 end p some_value # => [11, 12, 13] p some_value.reverse # => [13, 12, 11] some_other_value = [1,2,3].map do |int| int + 10 end.reverse p some_other_value # => [13, 12, 11] ``` This is pretty straightforward. `some_value` is constructed as expected, and `#reverse` does its job of reversing the resulting array. `some_other_value` contains `end.reverse`, and we see that line does essentially the same thing as `some_value.reverse`. It appears that you can call array methods on the `end` keyword, and that method gets called once at the end of the loop. Let's try some more things. ```ruby first_element = [1,2,3].each do end.first p first_element # => 1 last_element = [1,2,3].each do end.last p last_element # => 3 ``` These results are also pretty straightforward, as `#first` and `#last` are both array methods. Let's try a different notation: ```ruby middle_element = [1,2,3].each do end[1] p middle_element # => 2 ``` Hey, that's pretty neat. So `end` essentially behaves like an array now? ### Calling Object methods Let's try some methods that are not specific to the `Array` class. ```ruby my_class = [1,2,3].each do end.class p my_class # => Array my_id = [1,2,3].each do end.object_id p my_id # => 70236355699360 (result is different every time) ``` This confirms our hypothesis that `end` is an array, and that it's also possible to call methods from its parent class. ### Calling `?` and `!` methods What about `?` and `!` methods? (for lack of better word) ```ruby reversed = [1,2,3].each do end.reverse p reversed # [3, 2, 1] reversed_again = [1,2,3].each do end.reverse! p reversed_again # [3, 2, 1] am_i_empty = [1,2,3].each do end.empty? p am_i_empty # false ``` It seems that `end.reverse` and `end.reverse!` have the same result, which makes sense because the methods are called at the end of the loop, and the resulting array is returned. ### Daisy-chaining calling methods using `end` It's also possible to continuously call methods using `end` in a daisy-chain fashion. ```ruby chained_map = [1,2,3].map do |int| int + 10 # => [11, 12, 13] end.map do |int| int + 10 # => [21, 22, 23] end.map do |int| int + 10 # => [31, 32, 33] end.reverse p chained_map # => [33, 32, 31] ``` In this example, each iteration increases each value in the array by 10, so at the end of the third iteration, we get `[31, 32, 33]`. The last `end.reverse` reverse that result, so at the very end, we get `[33, 32, 31]`. ### Checking the returned class type When I first raised the question, I wondered if the reason that you can call Array methods on `end` is because the starting object (`inject([])`) is an Array. The correct answer is that methods called on `end` operates on the **ending object**. ```ruby type_test = [1,2,3].inject(Hash.new(0)) do |result, element| result end.class p type_test # => Hash type_test_again = [1,2,3].inject(Hash.new(0)) do |result, element| result = element end.class p type_test_again # => Fixnum ``` Here we see that even though both definitions have the same starting object `Hash`, the resulting classes are different. In the first definition, `type_test` has the resulting value of `{}`, an empty hash, and thus returns the class `Hash`. The second definition `type_test_again` has the resulting value of `3`, so it returns the class `Fixnum`. Thanks to Arne for pointing this out! ## Conclusion I never imagined that you can call methods on the `end` keyword. Jesse says: every valid Ruby expression returns something. You can assign that something to a variable, call methods on it, etc. I hope this gist was helpful to some of you. Thanks for reading!