Last Updated: September 09, 2019
·
1.865K
· dickeyxxx

Thank you Ruby 2. You're better than Python.

Like many, I am excited about Ruby 2's keyword parameters. It allows you to default arguments to your method like so:

def foo(x, y: 2)
  p "#{x}, #{y}"
 end

foo(1) #=> 1, 2
foo(2, 3) #=> 2, 3
foo(5, y: 9) # => 5, 9

This is a very natural way to write code without resorting to the old splat/hash techniques.

Python also has this functionality, but there is a subtle quirk that bit me in the ass really badly once. The default objects passed in are shared:

def foo(arr=[]):
    arr.append('x')
    print arr

foo() #=> ['x']
foo() #=> ['x', 'x']
foo() #=> ['x', 'x', 'x']

It's definitely subtle, but this really isn't how I would expect this code to work. I would expect the function to reset back to an empty array every time, not share it globally.

Thankfully, Ruby 2 acts the way I want it to:

def foo(arr: [])
  arr << ('x')
  print arr
end

foo() #=> ['x']
foo() #=> ['x']
foo() #=> ['x']

4 Responses
Add your response

This is not a design flaw, it's a feature.

For this kind of situation you might consider this:

def foo(arr=None):
    if arr is None:
        arr = []
    arr.append('x')
    print(arr)

A little more verbose but still very readable :)

over 1 year ago ·

def foo(x,y=2): print("%d,%d" % (x,y)) </code>

over 1 year ago ·

@doganaydin I don't think you read my post

over 1 year ago ·

Like @caioariede said, it's "feature". I often use this in my code, and find it very useful.

over 1 year ago ·