Forum: Ruby hygienic startup file

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2cb736dc6ab6b986406912b22dff9ea7?d=identicon&s=25 Thomas Hafner (Guest)
on 2009-04-23 00:43
(Received via mailing list)
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
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-04-23 00:51
(Received via mailing list)
Thomas Hafner 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
2cb736dc6ab6b986406912b22dff9ea7?d=identicon&s=25 Thomas Hafner (Guest)
on 2009-04-23 17:02
(Received via mailing list)
Joel VanderWerf <vjoel@path.berkeley.edu> wrote/schrieb
<49EF9F29.2060704@path.berkeley.edu>:

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

I can. That's it, thanks!

  Thomas
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-23 18:35
(Received via mailing list)
On 23.04.2009 16:50, Thomas Hafner wrote:
> Joel VanderWerf <vjoel@path.berkeley.edu> wrote/schrieb 
<49EF9F29.2060704@path.berkeley.edu>:
>
>> Can't you use local variables to do the same thing?
>
> I can. That's it, thanks!

Now you made me curious: why?

  robert
2cb736dc6ab6b986406912b22dff9ea7?d=identicon&s=25 Thomas Hafner (Guest)
on 2009-04-24 00:01
(Received via mailing list)
Robert Klemme <shortcutter@googlemail.com> wrote/schrieb
<75bjgbF17nqkvU1@mid.individual.net>:

> On 23.04.2009 16:50, Thomas Hafner wrote:
>> Joel VanderWerf <vjoel@path.berkeley.edu> wrote/schrieb 
<49EF9F29.2060704@path.berkeley.edu>:
>>
>>> 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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-24 09:16
(Received via mailing list)
2009/4/24 Thomas Hafner <thomas@faun.hafner.nl.eu.org>:
>
> 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
2cb736dc6ab6b986406912b22dff9ea7?d=identicon&s=25 Thomas Hafner (Guest)
on 2009-04-25 00:10
(Received via mailing list)
Robert Klemme <shortcutter@googlemail.com> wrote/schrieb
<9e3fd2c80904240015h11f3376l424a24457691b0c0@mail.gmail.com>:

> 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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-25 10:12
(Received via mailing list)
On 25.04.2009 00:04, Thomas Hafner 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).

> 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.

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 `<main>': uninitialized constant TEST (NameError)

robert@fussel ~
$

Kind regards

  robert
2cb736dc6ab6b986406912b22dff9ea7?d=identicon&s=25 Thomas Hafner (Guest)
on 2009-04-25 22:20
(Received via mailing list)
Robert Klemme <shortcutter@googlemail.com> wrote/schrieb
<75fun4F18b0q6U1@mid.individual.net>:

>> EOF
> Test is 123
> Is there TEST?
> -:6:in `<main>': 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
This topic is locked and can not be replied to.