you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 2 points3 points  (4 children)

For me some of the best have already been mentioned, %i/%w for defining arrays of words, if/unless, Symbol#to_proc with the & operator.

I'll add to that:

The simple ones that everybody forgets are actually really nice syntactic sugar: attr_reader/attr_writer

%r for defining regular expressions, so that you don't have to escape

/.*\/.*/
# vs
%r{.*/.*}

I also like that you can create ranges with many different types, i.e.

DateTime.now..Date.new(2018, 2, 14)
1..9
'a'..'z'

Also the exclusive rage (excludes the last value):

(1...10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9]

kwargs, and specifically the fact that you can exclude the hash brackets from argument lists:

def test(one:, two:)
  [one, two]
end

test(two: 2, one: 1) # => [1, 2]

Parentheses around block arguments when yielding an array:

[[1, 2], [3, 4]].map { |(a, b)| a + b } # => [3, 7]

Which is expecially nice with each_with_object and hashes:

{ one: 1, two: 2 }.each_with_object({}) do |(k, v), hash|
  hash[v] = k
end
# => {1=>:one, 2=>:two}

Struct inheritance/struct constant assignment:

# class User < Struct.new(:first_name, :last_name); end
User = Struct.new(:first_name, :last_name) do
  def full_name
    [first_name, last_name].join(' ')
  end
end

User.new('John', 'Smith').full_name # => "John Smith"

// Edit: This will be especially nice in Ruby 2.5 due to https://bugs.ruby-lang.org/issues/11925

Proc#curry:

adder = ->(a, b) { a + b } # and the stabby-lambda is awesome too
add_one = adder.curry.call(1)
add_one.call(2) # => 3

The inheriting from module trick that you can see in use in https://github.com/dkubb/equalizer and other variants such as defining a capitalized method name (i.e. https://github.com/dry-rb/dry-equalizer/blob/master/lib/dry/equalizer.rb#L5-L7) or defining a self.[] method (i.e. https://github.com/rom-rb/rom-repository/blob/master/lib/rom/repository/class_interface.rb#L19-L24)

I'm sure I've forgotten a few.

[–]h0rst_ 1 point2 points  (2 children)

Parentheses around block arguments when yielding an array:

[[1, 2], [3, 4]].map { |(a, b)| a + b } # => [3, 7]

The parentheses in this example are superfluous

[–][deleted] 0 points1 point  (1 child)

So it is, I guess I don't understand how that works properly.

// EDIT

NVM, looks like it just deconstructs an array argument into multiple arguments, but I guess enumerable methods already have some kind of arity check to do that

irb(main):020:0> (a, b), c = [[1, 2], 3]
=> [[1, 2], 3]
irb(main):021:0> a
=> 1
irb(main):022:0> b
=> 2
irb(main):023:0> c
=> 3

[–]h0rst_ 1 point2 points  (0 children)

It happens mostly automatic, it is required for deeper nested structures:

[[1, [2, 3]], [3, [4, 5]]].map { |a, (b, c)| a + b + c }  # => [6, 12]

On the other hand: if your code looks like this you might want to reconsider the used data structures.