# Hygienic startup file

**URL:** <https://www.ruby-forum.com/t/hygienic-startup-file/166230>\
**Category:** Ruby\
**Created:** [April 23, 2009, 12:43am UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230 "2009-04-23T00:43:11Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 23, 2009, 12:43am UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/1 "2009-04-23T00:43:11Z")

</div>

Hello,

a startup file to be loaded by RUBYOPT should have minimal side  
effects. I guess, this pattern will do it:

class \<\< Object.new  
FOO = … # will not override FOO if defined before  
BAR = … # will introduce BAR intermediately  
…  
# Use the constants above to do some wanted side effect on an  
# object hold by a global variable, e.g. $LOAD\_PATH :  
$:.unshift(FOO, …)  
end

# no more BAR visible here

Is there a canonical way to achive this kind of hygiene?

Regards  
Thomas

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 23, 2009, 5:02pm UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/2 "2009-04-23T17:02:32Z")

</div>

Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Can’t you use local variables to do the same thing?

I can. That’s it, thanks!

Thomas

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 23, 2009, 12:51am UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/3 "2009-04-23T00:51:23Z")

</div>

Thomas H. wrote:

> ```
> # object hold by a global variable, e.g. $LOAD_PATH :
> $:.unshift(FOO, ...)
> 
> ```
> 
> end
> 
> # no more BAR visible here
> 
> Is there a canonical way to achive this kind of hygiene?
> 
> Regards  
> Thomas

Can’t you use local variables to do the same thing?

foo = …  
$:.unshift foo

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 23, 2009, 6:35pm UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/4 "2009-04-23T18:35:51Z")

</div>

On 23.04.2009 16:50, Thomas H. wrote:

> Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > Can’t you use local variables to do the same thing?
> 
> I can. That’s it, thanks!

Now you made me curious: why?

robert

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 24, 2009, 9:16am UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/5 "2009-04-24T09:16:11Z")

</div>

2009/4/24 Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I guess that using local variables is not exactly the same thing like  
> class constants,

Of course it’s not the same, but it always depends on the use case.

> but it’s close enough that I don’t (yet) notice the  
> difference when writing Ruby programs which load that startup file:

Does this mean you switched to local variables?

> Neither are the variables from outside visible to the loaded startup  
> file, nor are local variables of the startup file visible from  
> outside. (That wasn’t the case for uppercase names (constants!), and  
> so I had to enclose them in a dummy class - or whatever - do you know  
> a simpler solution to hide constants, BTW?)

The question is: why do you need constants if you want to hide them?  
Now it is even less clear to me what you want. All I’ve understood is  
that you want to require a file (even if it’s autorequired) and make  
sure that particular information does not leak. OTOH I am sure you  
want some information to leak so why don’t you use constants for the  
things (classes, modules) that need to be known outside and use local  
variables for the rest?

Cheers

robert

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 24, 2009, 12:01am UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/6 "2009-04-24T00:01:02Z")

</div>

Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> On 23.04.2009 16:50, Thomas H. wrote:
> 
> > Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> > 
> > > Can’t you use local variables to do the same thing?
> > 
> > I can. That’s it, thanks!
> 
> Now you made me curious: why?

I guess that using local variables is not exactly the same thing like  
class constants, but it’s close enough that I don’t (yet) notice the  
difference when writing Ruby programs which load that startup file:

Neither are the variables from outside visible to the loaded startup  
file, nor are local variables of the startup file visible from  
outside. (That wasn’t the case for uppercase names (constants!), and  
so I had to enclose them in a dummy class - or whatever - do you know  
a simpler solution to hide constants, BTW?)

Regards  
Thomas

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 25, 2009, 12:10am UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/7 "2009-04-25T00:10:48Z")

</div>

Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> The question is: why do you need constants if you want to hide them?

First I defined constants rather than variables simply because each of  
them actually is constant rather than variable: the value never  
changes after assignment. In C++ I would add a const qualifier to the  
local variables, e.g. to prevent from unintentionally overriding it.  
In Haskell ther’s no need for a const keyword, because all definitions  
are immutable per se, which is regarded a feature in this purely  
functional programming language.

But in Ruby there are no local constants analogical to local  
variables, so when I simply define constants I unintentionally export  
them, too. (Freeze is no option, because it freezes the object hold by  
the variable, not the variable itself.)

Every alternative has its own tradeoff:

1. If I define simple constants, I pollute the namespace of the  
loading code.
2. If I define constants within class \<\< Object.new, the code is  
somehow ugly.
3. If I define local variables, I don’t benefit from the fact that  
they are actually constant.

So currently alternative #3 is best for me, but if somebody shows me a  
way to make #2 less ugly (get away from class \<\< Object.new), that  
would probably my favorite.

Regards  
Thomas

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 25, 2009, 10:20pm UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/8 "2009-04-25T22:20:49Z")

</div>

Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > EOF  
> > Test is 123  
> > Is there TEST?  
> > -:6:in `': uninitialized constant TEST (NameError)

Interesting: for ruby1.8 there’s still TEST. If I replace Module.new  
by Class.new, it’s OK. Seems that I need an anonymous class for ruby  
1.8.

Regards  
Thomas

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [April 25, 2009, 10:12am UTC](https://www.ruby-forum.com/t/hygienic-startup-file/166230/9 "2009-04-25T10:12:10Z")

</div>

On 25.04.2009 00:04, Thomas H. wrote:

> functional programming language.  
> Keep in mind that Ruby constants are not really constant:

robert@fussel ~  
$ ruby19 -e ‘X=1;puts X;X=2;puts X’  
1  
-e:1: warning: already initialized constant X  
2

Generally, Ruby is less strict with these things (“private” is another  
example).

> But in Ruby there are no local constants analogical to local  
> variables, so when I simply define constants I unintentionally export  
> them, too. (Freeze is no option, because it freezes the object hold by  
> the variable, not the variable itself.)
> 
> Every alternative has its own tradeoff:
> 
> 1. If I define simple constants, I pollute the namespace of the  
> loading code.
> 2. If I define constants within class \<\< Object.new, the code is  
> somehow ugly.

This is also a kind of inappropriate solution because you create an  
instance just to get at its singleton class. This is not needed (see  
below).

> 1. If I define local variables, I don’t benefit from the fact that  
> they are actually constant.
> 
> So currently alternative #3 is best for me, but if somebody shows me a  
> way to make #2 less ugly (get away from class \<\< Object.new), that  
> would probably my favorite.

You can use an anonymous module for this:

robert@fussel ~  
$ ruby19 \<\<EOF

> Module.new do  
> TEST = 123  
> puts “Test is #{TEST}”  
> end  
> puts “Is there TEST?”  
> puts TEST  
> EOF  
> Test is 123  
> Is there TEST?  
> -:6:in `’: uninitialized constant TEST (NameError)

robert@fussel ~  
$

Kind regards

robert
