
goruby
Ruby not concise enough? In the source code, you’ll find a file called golf_prelude.rb. Include it in the compilation and you get goruby where each method has its own abbreviation, the String class behaves like an Array, … to be as concise as possible!
There’s also the casecmp method for comparing 2 strings without taking case into account, but it returns -1, 0 or 1 (or nil if incompatible) which can be used to sort, for example.
casecmp
Case insensitive comparison
casecmp? compares 2 strings without taking case into account. When it comes to unicode characters, there are a few subtleties! With a non-compatible type, the method returns nil rather than an exception.
||= vs defined?
Cache false/nil
||= is the most common way of caching. Except that it doesn’t handle false and nil! defined? can be a solution by checking whether the variable is defined. ⚠️ Be sure to take into account when the parser defines the variable!
A more interesting example highlighting the parser step. In the 1st if, the parser sees and creates the a variable after the condition, which will therefore be false at runtime. In the 2nd case, it sees and creates b before! (A if inline is therefore not equivalent!)
local variable, a detail on how they work
They are created when the parser encounters them, not dynamically at runtime! Furthermore, a if does not create a new scope, making variables accessible after the scope has ended. This is also the case for unless, while, until and for.
The main benefit is to be able to alter the object in the method chain. Another use case is to be able to inspect an intermediate state without having to rewrite everything.
tap
For method chaining
The tap method, defined in Kernel, returns self which is passed as a block argument. To be distinguished from then, which returns the result of the block.
⚠️ There is a subtle difference with the splat operator. It doesn’t handle nil. Well, not yet, because after more than 10 years, it will in Ruby 3.4.0 (see Issue 20064: bugs.ruby-lang.org/issues/20…).

!["a".casecmp "B" # => -1
"b".casecmp "B" # => 0
"c".casecmp "B" # => 1
%w[C E B d a f].sort(&:casecmp)
# => ["a", "B", "C", "d", "E", "f"]](https://pbs.twimg.com/media/Gc60jnhXcAAx9mM.jpg?name=small&format=webp)




![3.times.to_a.tap { _1[1] = 5 } # [0, 5, 2]
# vs
a = 3.times.to_a
a[1] = 5
a # [0, 5, 2]
3.times .tap { p _1 } # #<Enumerator: 3:times>
.map { _1 * 2 } .tap { p _1 } # [0, 2, 4]
.filter(&:positive?) # [2, 4]](https://pbs.twimg.com/media/GabJw57XsAASvOm.jpg?name=small&format=webp)

![[*nil] # []
{**nil} # TypeError (< 3.4.0)
{**nil} # {} (>= 3.4.0)](https://pbs.twimg.com/media/GZgpdUAXsAMCUK5.jpg?name=small&format=webp)
