A question on style

Hi everyone,

Long time developer here, new to Ruby.

I have a simple, single file Ruby program that randomly chooses a
response to input text. I have a method to return the the array of
responses, which I call further into the file in my main routine. This
is the method:

def get_responses
[
“Got it.”,
“Interesting. I’ve made a note of that.”,
“Noted.”,
“Right.”,
“I see.”,
“As you say.”
]
end

Is this conventional? Is there any benefit in late acquisition of this
array, or would it be normal to just assign it to a variable up front?

Thanks in advance,

Joe

“From rivers of sorrow, to oceans deep with hope.
I have travelled them.
Now there’s no turning back.
The limit, the sky.”

  • Chuck Schuldiner (RIP)

On Mon, Aug 01, 2011 at 05:06:21AM +0900, Joseph P. wrote:

[
array, or would it be normal to just assign it to a variable up front?
All else being equal, I think I would just assign all that to an array:

get_response = [
  'Got it.',
  "Interesting.  I've made a note of that.",
  'Noted.',
  'Right.',
  'I see.',
  'As you say.'
]

Unless some other factors apply in context, the main difference is that
the method call version has a lot more overhead. With variable
assignment, you only have to construct the array once. With the method
call version, the method call itself has overhead, and the array is
constructed every time the method is called (unless you’re using a Ruby
implementation that does some aggressive optimization of which I’m not
aware right now).

There may be times that the method version would be more appropriate,
though.

On Sun, Jul 31, 2011 at 3:06 PM, Joseph P. <
[email protected]> wrote:

    "Got it.",

I wouldn’t have a problem doing it, though I usually start like [ "Got it.", Anyway, there are two nuances to doing it that way. Whether they
are
benefits or not depends on your program.

  1. Every time you call that method, the array it returns and the string
    contents, are all new objects. This can be beneficial in that you can
    mutate
    the array and it doesn’t matter. It can be a problem if you call it a
    billion times and use up a lot of memory on duplicate objects and
    processing
    power recreating existing objects.

  2. The method is globally visible (assuming you’re defining it at the
    top
    level, in main), whereas a local variable would only be visible within
    the
    same scope. It can be a benefit in that you may want to call it from
    other
    scopes, it may be a problem in that it is potentially possible (though
    highly highly unlikely) that making it visible everywhere could cause an
    error elsewhere in your program.

On Sun, Jul 31, 2011 at 10:06 PM, Joseph P.
[email protected] wrote:

“Noted.”,
“Right.”,
“I see.”,
“As you say.”
]
end

Is this conventional? Is there any benefit in late acquisition of this array, or
would it be normal to just assign it to a variable up front?

I find it inelegant to recreate a constant over and over again. It’s
also inefficient. Better assign to a instance variable, global var or
even constant. Note also that you can use Array#sample for automated
picking of a random element.

Kind regards

robert

Joseph P. wrote in post #1014043:

def get_responses
[
“Got it.”,
“Interesting. I’ve made a note of that.”,
“Noted.”,
“Right.”,
“I see.”,
“As you say.”
]
end

I would typically define a constant for this:

class Foo
GET_RESPONSES = [
“Got it.”,
“Etc.”,
]

end

Then only one object is created, and you use it over and over again. To
do this safely it’s better to freeze both the array and its members:

GET_RESPONSES = [
“Got it.”.freeze,
“Etc.”.freeze,
].freeze

Note: it’s possible to override GET_RESPONSES in subclasses, but if you
want a method defined in the superclass to dynamically pick the constant
from the subclass then you need to use dynamic resolution like this:

class Foo
GET_RESPONSES = […]
def response(n)
self.class::GET_RESPONSES[n]
end
end

class Bar < Foo
GET_RESPONSES = […]
end

Regards,

Brian.