7

Is there any performance implications if I do either of these:

def do_something(user, article)
...
end

versus

def do_something(user_id, article_id)
  ..
end

I prefer passing objects as I might need other attributes down the road.

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
Blankman
  • 259,732
  • 324
  • 769
  • 1,199
  • 1
    Even if there are performance implications, don't optimize prematurely. If you think you'll need other object attributes, pass in the objects. – Michael Kohl Jun 29 '11 at 20:48
  • When you say `user_id`, do you mean the `object_id` provided for Ruby objects (even `nil` has an `object_id`), or the unique database id provided by ActiveRecord? – Andrew Grimm Jun 29 '11 at 23:28

5 Answers5

16

Yes

Both method calls will take about the same amount of time.

(It's good to be aware of performance consequences and you asked a reasonable question, but even so, the standard disclaimer1 about early optimization technically applies.)


1. First, make program work. Then, profile. Finally, and maybe, optimize.
Donald Knuth said: We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
4

Re: https://stackoverflow.com/a/6528257 (I didn't have enough reputation to comment at time of writing)

Ah, but Jörg, if you actually manipulate the argument, instead of assigning a new object to it, the method behaves differently. Using .replace instead of = gives you this:

def is_Ruby_pass_by_value_or_reference?(parameter)
  parameter.replace 'Ruby is pass-by-reference.'
end

var = 'Ruby is pass-by-value.'

is_Ruby_pass_by_value_or_reference?(var)

puts var
# Ruby is pass-by-reference.

In fact, let's elaborate just a little more, just to show the difference:

def is_Ruby_pass_by_value_or_reference?(parameter)
  parameter.replace 'Ruby is pass-by-reference.'
  parameter = "This assigns a whole new object to 'parameter', but not to 'var'."
  puts parameter
end

var = 'Ruby is pass-by-value.'

is_Ruby_pass_by_value_or_reference?(var)
# This assigns a whole new object to 'parameter', but not to 'var'.

puts var
# Ruby is pass-by-reference.
PJSCopeland
  • 2,818
  • 1
  • 26
  • 40
  • This should be the answer. It's awesome.. I wonder if fixed numbers are also passed by ref? They are not always "objects", so perhaps they are exceptional. – baash05 Nov 22 '12 at 02:46
  • 2
    -1. This is wrong. Pass-by-reference means that the callee can manipulate the caller's variable bindings that are being passed in. That is not the case in Ruby. In fact, your code even *shows* that this is not the case in Ruby, ergo your code shows that Ruby is *not* pass-by-reference. If it *were* pass-by-reference, then your last line would print `This assigns a whole new object to 'parameter', but not to 'var'.` instead of `Ruby is pass-by-reference.` What *your* code shows is that Ruby allows you to mutate shared mutable state. But that wasn't in dispute anyway, nobody claimed Ruby was a … – Jörg W Mittag Nov 22 '12 at 10:27
  • 2
    … pure functional language. Pass-by-reference means that the variable binding *itself* is passed into the callee and thus changes to that variable binding (in other words: assignments to the variable) become visible to the caller. Your code clearly shows that this is not the case, thus it shows that Ruby is not pass-by-reference. – Jörg W Mittag Nov 22 '12 at 10:29
  • 2
    Well that's all very convincing jargon, Jörg, but the fact is, when people ask "is this pass-by-reference", what they really mean is, "can a method change the value of a variable passed to it?" And the answer, as I demonstrated, is 'yes'. If you don't want your method to do that, you should assign `parameter.dup` or `parameter.clone` (shallow and deep copy, respectively) to something and work with that instead. – PJSCopeland Nov 23 '12 at 08:02
  • Very well demonstrated answer and very handy in every day ruby programming. Thanks !!! – Douglas Feb 19 '13 at 12:20
  • @baash05 Fixed numbers are not mutable - they don't have any methods that can actually change their values - so the question of whether they're passed by reference is moot. I've tried to use this, and ended up having to use a string instead and cast it to an integer when I needed the value. – PJSCopeland Nov 10 '13 at 20:58
1

No, Ruby never passes by reference. Ruby is pass-by-value. Always. No exceptions.

def is_Ruby_pass_by_value_or_reference?(parameter)
  parameter = 'Ruby is pass-by-reference.'
end

var = 'Ruby is pass-by-value. Always. No exceptions.'

is_Ruby_pass_by_value_or_reference?(var)

puts var
# Ruby is pass-by-value. Always. No exceptions.

If Ruby were pass-by-reference, this would print Ruby is pass-by-reference.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • can you please elaborate? It's been discussed a numerous times and declared ruby is pass-by-reference http://www.ruby-forum.com/topic/41160. The second entry in that link summarizes it all. – so_mv Jun 30 '11 at 00:56
  • 2
    @so_mv: The fact that the values that are being passed are pointers doesn't change the fact that Ruby is pass-by-value. – Jörg W Mittag Jun 30 '11 at 08:29
  • Jorg.. values passed are pointers, sort of defines the term pass by reference. Also Patrik's expansion of your code shows your error. – baash05 Nov 22 '12 at 02:44
  • 2
    @daveatflow: No, it does *not* "sort of define the term pass by reference". That term is not "sort of defined". It is *precisely* defined, and has been for decades. *What* is being passed is completely and utterly irrelevant. It could be an integer, it could be an object, it could be a pointer, it could even be the easter bunny. What *is* relevant is *how* it is being passed: is a copy of the *content* of the variable being passed (pb-value) or is the variable binding *itself* being passed (pb-reference). In the latter case, manipulating the variable binding is visible to the caller. – Jörg W Mittag Nov 22 '12 at 10:19
  • 2
    @daveatflow: @Patrick's code, in fact, precisely shows that Ruby is *not* pass-by-reference. If it *were*, then the last line would print `This assigns a whole new object to 'parameter', but not to 'var'.` instead of printing `Ruby is pass-by-reference.` – Jörg W Mittag Nov 22 '12 at 10:22
0

For example, I would go with the _id variant. I prefer to always be able to get the correct state of my objects. It's never fun to work with stale ones.

Senthess
  • 17,020
  • 5
  • 23
  • 28
-3

Well everything is an Object in ruby (everything inherits from Object) and ruby always passes objects by ref so both of your examples are passing by reference!

eggie5
  • 1,920
  • 18
  • 25
  • 2
    This isn't precisely true. A number of immutable constants such as small integers are in fact passed by value in Ruby. It doesn't really make any difference because they are still objects, and it doesn't really change the method call speed, but technically, there is a behind-the-scenes call-by-value for things called *immediates.* See: http://redmine.ruby-lang.org/issues/show/1844 – DigitalRoss Jun 29 '11 at 21:13
  • You are wrong! Ruby doesn't have any concept of passing a value around. Variables are always references to objects. If everything is an object passing by value is non-sensical. – eggie5 Jun 29 '11 at 23:10
  • Ruby does pass by reference for everything except the immediate value classes – eggie5 Jun 29 '11 at 23:15
  • Unfortunately the terms don't apply well to modern languages. The object is passed by reference but the reference is passed by value. It's both and neither. It's so rare in any language to pass an object "by value" (though this can be done with structs in C, but usually isn't, and is always done with certain small objects in Ruby) that I suppose one might reasonably discuss instead how the reference is passed. – DigitalRoss Jun 30 '11 at 01:26
  • 2
    @eggie5: Ruby is pass-by-value. The values that are being passed are pointers (or in some cases immediates, but those are also immutable, so it's actually impossible to observe the difference), but what the values are is irrelevant and doesn't change the semantics. – Jörg W Mittag Jun 30 '11 at 08:31