API style preference? a.b=c or a(:b=>c)

I’m writing a number of lines lately that look something like this:

DocRootNames = [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’].freeze unless
const_defined? :DocrootNames

So, in my pre-cup-of-tea stupor this morning, I was thinking about ways
to
reduce the number of keystrokes to achieve that effect.

I came up with two slightly different approaches:

constant.DocRootNames = [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’]

or

constant(:DocRootNames => [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’])

I’m vacilating about whether I actually want to do either of these or
whether
I should just drink my cup of tea and not worry about rewriting the
“.freeze
unless const_defined? :Foo” boilerplate over and over again, but putting
that
whole consideration aside, which API style do you all like better, and
why?

Kirk H.

I’m curious as to why you’re in a position to check whether a constant
is defined in the first place.

I’d just stick with

DocRootNames = [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’].freeze

Or, if you’re paranoid

DocRootNames = [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’].each {|x|
x.freeze}.freeze

Although freezing nil may have undesirable effects. No you need that
nil in there? If not you could even do

DocRootNames = %w{docs doc htdocs htdoc}.freeze

robert

I’m writing a number of lines lately that look something like this:

DocRootNames = [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’].freeze unless
const_defined? :DocrootNames

Knowing that you can do:
@@class_state ||= ‘initial_value’

Even though you can’t do:
@@class_state = @@class_state || ‘initial_value’

I was going to suggest using

Constant ||= [‘stuff’].freeze

But that doesn’t work - it gives an uninitialised constant error (in the
same way I’d expect @@class_state ||= … to, although it doesn’t).

:slight_smile:

constant(:DocRootNames => [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’])

I’m vacilating about whether I actually want to do either of these or
whether
I should just drink my cup of tea and not worry about rewriting the
“.freeze
unless const_defined? :Foo” boilerplate over and over again, but putting
that
whole consideration aside, which API style do you all like better, and
why?

I don’t like either :slight_smile: If you only set up a constant in one place, and
you use require to make sure that file’s only parsed once, then why
would you want that behaviour? … There’s probably a good reason, but
maybe there’s a better solution to the problem?

Cheers,
Benjohn

On Jun 16, 2006, at 7:06 AM, Kirk H. wrote:

constant(:DocRootNames => [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’])

I like that one better.

James Edward G. II

On Friday 16 June 2006 6:29 am, Robert K. wrote:

nil in there? If not you could even do
I actually do need that nil there, though the freezing is arguably
superflous
for my needs. However, the whole point in that boilerplate is that I am
checking const_defined? and not redefining the const if it is already
defined. If I eliminate the boilerplate, I eliminate typing the same
same
thing thing over and over again, but then the code generates piles of
warnings that I don’t care to generate, either.

But really, that’s neither here nor there. I mostly curious about
people’s
stylistic preferences (and why the preference):

constant.Foo = :bar

or

constant(:Foo => :bar)

Thanks,

Kirk H.

On Jun 16, 2006, at 7:25 AM, Matthew H. wrote:

I’m curious as to why you’re in a position to check whether a constant
is defined in the first place.

To avoid the warnings Rails spits out is my best guess. :wink:

James Edward G. II

On Friday 16 June 2006 6:30 am, [email protected] wrote:

I don’t like either :slight_smile: If you only set up a constant in one place, and
you use require to make sure that file’s only parsed once, then why
would you want that behaviour? … There’s probably a good reason, but
maybe there’s a better solution to the problem?

:slight_smile:

Because the class definition is not required, and may indeed be
evaluated
multiple times. And there isn’t really a better solution because the
point
of the reloading is to pick up changes to the code dynamically, without
restarting a long running process.

So, getting back to the point of the question, you’d prefer multiple
lines all
with the const_defined? check explicitly attached. Fair enough.
However,
what if the api in question weren’t dealing with constants, but was
something
else entirely?

zoom.Foo = :bar

zoom(:Foo => :bar)

Preference?

Thanks,

Kirk H.

On 6/16/06, Kirk H. [email protected] wrote:

zoom.Foo = :bar

zoom(:Foo => :bar)

Preference?

I prefer the zoom(:Foo => :bar) interface.

The reason I prefer it is because you can more easily define your
constants in a config file (e.g. YAML) and because it lets you define
multiple constants at the same time.

BTW, I don’t think you ~can~ freeze nil. At least, it seems to have no
effect.

Here’s a quickie implementation (with deep_freeze paranoia):

class Object
def deep_freeze
if self.respond_to? :each
self.each do |i|
i.deep_freeze
end
end
self.freeze
end
end
class String
def deep_freeze
freeze
end
end
class Object
def constant(hash)
target = self.kind_of?(Module) ? self : self.class
hash.each do |key, value|
target.const_set(key, value.deep_freeze) unless
target.const_defined? key
end
end
end

constant(:DocRootNames => [nil,‘docs’,‘doc’,‘htdocs’,‘htdoc’])
constant(:DocRootNames => [‘something’, ‘else’])

constant :DocRootNames => [‘again’],
:Other => 42,
:AndAgain => (1…42)

p DocRootNames
p Other
p AndAgain

module Foo
constant :Bar => :Baz
end
module Foo
constant :Bar => :Boo
end
p Foo::Bar

class Moo
constant :Cow => 42
end
class Moo
constant :Cow => 24
end
p Moo::Cow

END
[nil, “docs”, “doc”, “htdocs”, “htdoc”]
42
1…42
:Baz
42

(Apologies for the appalling names! :slight_smile:

Regards,
Sean

Would `Constant ||= “value”’ be a possible remedy?

On Friday 16 June 2006 6:25 am, Matthew H. wrote:

I’m curious as to why you’re in a position to check whether a constant
is defined in the first place.

Because the class(es) may be reevaluated, and I don’t want to generate a
pile
of warnings about “Already initialized constant Foo”.

Kirk H.