Discussion:
Environment changes in the beta
James M. Lawrence
2011-03-02 03:55:18 UTC
Permalink
% cat mystuff.rb
module MyStuff
CONST_B = 44
end

% cat Rakefile
require 'rake'
require './mystuff'

module MyStuff
CONST_A = 33
end

p MyStuff::CONST_A
p MyStuff::CONST_B
# => uninitialized constant Rake::Environment::MyStuff::CONST_B

task :default

% rake --version
rake, version 0.9.0.beta.1

% rake
33
rake aborted!
uninitialized constant Rake::Environment::MyStuff::CONST_B

Writing ::MyStuff::CONST_B instead works, and conversely
::MyStuff::CONST_A is an error.

It seems that Rake::DSL already provides the necessary partitioning.
If I wanted to keep the global scope clean, I would do

module MyStuff
extend Rake::DSL

task :default do
# ...
end
end

Could an example like that in the README replace the need for
environment.rb?
Jim Weirich
2011-03-02 21:03:08 UTC
Permalink
I've not had time to go over your email in detail, but I'm not getting the behavior I want out of the beta.1 in this area either. I'll review when I get a chance.
Post by James M. Lawrence
% cat mystuff.rb
module MyStuff
CONST_B = 44
end
% cat Rakefile
require 'rake'
require './mystuff'
module MyStuff
CONST_A = 33
end
p MyStuff::CONST_A
p MyStuff::CONST_B
# => uninitialized constant Rake::Environment::MyStuff::CONST_B
task :default
% rake --version
rake, version 0.9.0.beta.1
% rake
33
rake aborted!
uninitialized constant Rake::Environment::MyStuff::CONST_B
Writing ::MyStuff::CONST_B instead works, and conversely
::MyStuff::CONST_A is an error.
It seems that Rake::DSL already provides the necessary partitioning.
If I wanted to keep the global scope clean, I would do
module MyStuff
extend Rake::DSL
task :default do
# ...
end
end
Could an example like that in the README replace the need for
environment.rb?
_______________________________________________
Rake-devel mailing list
http://rubyforge.org/mailman/listinfo/rake-devel
--
-- Jim Weirich
-- ***@gmail.com
James M. Lawrence
2011-03-03 21:29:50 UTC
Permalink
Currently rake/dsl.rb says

include Rake::DSL

Of course the top-level include method is special (and probably
misnamed), having the effect of

class Object
include Rake::DSL
end

If the top-level object were extended instead, then the DSL would be
available at the global scope while not interfering with other classes
and modules. Running this with ruby alone (not through rake),

require 'rake'

extend Rake::DSL

task :default do # OK
# ...
end

module MyStuff
task :foo do # => NoMethodError for `task'
# ...
end
end

Users decide whether to have DSL in their classes/modules, and whether
at the singleton or instance level. That is,

module MyStuff
extend Rake::DSL

task :foo do
# ...
end
end

or

class MyStuff
include Rake::DSL

def initialize
task :foo do
# ...
end
end
end

Thus my proposal is that bin/rake simply extend Rake::DSL at the top
level rather than include it. The readme would cover how to use the
DSL in one's own classes with examples like the above.

I'm guessing that environment.rb was a noble effort to keep 'import'
alive, resolving the jruby conflict while maintaining backward
compatibility. Perhaps 'import' can be left out of Rake::DSL when
RUBY_ENGINE == "jruby", and/or deprecate import in favor of
Rake.import. Such a conflict may have no good solution. (Even though
it's not fair because you had it first :)
Jim Weirich
2011-03-05 20:36:34 UTC
Permalink
Post by James M. Lawrence
Thus my proposal is that bin/rake simply extend Rake::DSL at the top
level rather than include it. The readme would cover how to use the
DSL in one's own classes with examples like the above.
I've had time to look over your email and I must say ... it's brilliant! I would have never thought of just extending the actual top level "main" object. This puts the rake DSL at the top level for Rakefile without polluting the namespace of all objects. This solves all the problems I was trying to fix with the environment hack, except for ... (see below).
Post by James M. Lawrence
I'm guessing that environment.rb was a noble effort to keep 'import'
alive, resolving the jruby conflict while maintaining backward
compatibility. Perhaps 'import' can be left out of Rake::DSL when
RUBY_ENGINE == "jruby", and/or deprecate import in favor of
Rake.import. Such a conflict may have no good solution. (Even though
it's not fair because you had it first :)
Your guess is accurate. I don't like the explicit test for JRuby (that means some rakefile wouldn't run in JRuby, yuck). Instead I'm going to deprecate 'import' and promote the use of Rake.import. I think that's best.

Thanks so much.
--
-- Jim Weirich
-- ***@gmail.com
James M. Lawrence
2011-03-07 06:48:28 UTC
Permalink
 I would have never thought of just extending the actual top level "main" object.
Ha, you didn't have to divulge that. I assumed you thought of it but
that your focus was on 'import'.

My suggestion was a bit more drastic, though: it implicitly called for
the annihilation of environment.rb. There have been times when I, too,
have not realized that a change suddenly obsoletes a hunk of code :)
All of the following are now equivalent,

Rake::Environment.run do
task :a do
p 'task a'
end
end

Rake::DSL.environment do
task :b do
p 'task b'
end
end

module Rake::Environment
task :c do
p 'task c'
end
end

Rake::Environment.module_eval do
task :d do
p 'task d'
end
end

task :default => [:a, :b, :c, :d]

Option c is clearly the winner, with d being needed for access to
top-level locals (probably uncommon). Aren't a and b vestigial
structures from the old 'import' workaround device?

But what is Rake::Environment doing now?

module MyStuff
extend Rake::DSL

task :default do
# ...
end
end

In my first email, I asked if an example like that in the readme could
replace the need for environment.rb. Meaning, rather than give users
an empty bucket (Rake::Environment), teach them how to make their own
bucket (MyStuff). At least _I_ would prefer a fresh module over
Rake::Environment.

load_string also looks like a vestigial artifact. It's the same as
module_eval now.

Rake::Environment.load_string %{
task :x do
p 'task x'
end
}

Rake::Environment.module_eval %{
task :y do
p 'task y'
end
}

task :default => [:x, :y]

(They are not quite the same; load_string uses eval() which treats
constants differently.)

Lastly there is load_rakefile, which is effectively

Rake::Environment.module_eval(File.read("extra.rake"))

But this has the same problem shown in my first email on beta.1
(http://rubyforge.org/pipermail/rake-devel/2011-March/000832.html).
Indeed running the examples from that email,

% rake --version
rake, version 0.9.0.beta.2

% rake
33
rake aborted!
uninitialized constant #<Class:0x489f7c>::MyStuff::CONST_B

Ah, but what is that anonymous class? It's the load_string/module_eval
difference mentioned above. Rake::Environment is simultaneously a
named module and an anonymous module because eval() doesn't understand
that the module is really Rake::Environment. (In C terms,
rb_mod_module_eval calls eval_under while rb_f_eval does not.) But
this is moot because replacing load_string with module_eval gives the
equally undesirable

uninitialized constant Rake::Environment::MyStuff::CONST_B

The constants in a Rakefile are placed inside Rake::Environment, but
since the Rakefile may require files, and since require starts a new
scope, it all goes to pot. The lesson from beta.1 is that Rakefiles
can't be sandboxed into Rake::Environment.
I don't like the explicit test for JRuby (that means some Rakefile
wouldn't run in JRuby, yuck). Instead I'm going to deprecate
'import' and promote the use of Rake.import.
'import' is not a built-in jruby method; it's only defined with
'require "jruby"', and that is only needed for jruby-specific things
like enabling/disabling ObjectSpace.

Additionally, jruby + Rake seems an unlikely choice for a build tool.
The launch time for jruby is excruciating in this context. JRuby is
aimed at the opposite use case where startup time is not important.
Does *anyone* regularly use jruby with Rake?

I would be interested to see a real-life example where jruby + Rake +
'require "jruby"' is needed. There are viable workarounds even if that
did happen. It's not immediately obvious to me that Rake should change
its API to accommodate that case. If Rake weren't the most popular gem
of all time with 15K downloads per day, the issue might be different.
Jim Weirich
2011-03-14 01:22:35 UTC
Permalink
Post by James M. Lawrence
My suggestion was a bit more drastic, though: it implicitly called for
the annihilation of environment.rb.
Yes, environment is on the chopping block, but I wanted some beta time with the functionality changed before cleaning up the cruft leftover from the namespace rework. I've included (at least some) of that cleanup in beta 5.

Thanks so much for your input.
--
-- Jim Weirich
-- ***@gmail.com
James M. Lawrence
2011-03-14 07:34:35 UTC
Permalink
Post by James M. Lawrence
My suggestion was a bit more drastic, though: it implicitly called for
the annihilation of environment.rb.
Yes, environment is on the chopping block [...]
OK, as in my email about the magic comment I should have just asked
before writing so much.

Are you sure you wish to deprecate 'import'? It seems a gray area due
to the reasons I gave. I assume googlers will find this thread after
being flooded with 'import' warnings :)

Incidentally I didn't mention the nailgun option for jruby. Even
conceding the statup time issue, the case for deprecating 'import' is
still unclear to me.
Jim Weirich
2011-03-14 10:55:24 UTC
Permalink
Post by James M. Lawrence
Are you sure you wish to deprecate 'import'? It seems a gray area due
to the reasons I gave. I assume googlers will find this thread after
being flooded with 'import' warnings :)
Ok, fair question. I'll put it to the mailing list: Deprecate import or not.

I see several options:

(A) Leave import as is and let JRuby worry about the conflict.
(B) Deprecate import (favoring Rake.import), eventually ceding the import statement to JRuby (this is in the current beta direction)
(C) Make A vs B a command line option (but which way to default?)

Weight in people.
--
-- Jim Weirich
-- ***@gmail.com
Luis Lavena
2011-03-14 11:51:45 UTC
Permalink
Post by James M. Lawrence
Are you sure you wish to deprecate 'import'? It seems a gray area due
to the reasons I gave. I assume googlers will find this thread after
being flooded with 'import' warnings :)
Ok, fair question.  I'll put it to the mailing list:  Deprecate import or not.
(A) Leave import as is and let JRuby worry about the conflict.
(B) Deprecate import (favoring Rake.import), eventually ceding the import statement to JRuby (this is in the current beta direction)
(C) Make A vs B a command line option (but which way to default?)
I haven't used import in *long* time, and none of my projects uses it nowdays.

I barely remember one or 2 projects that did use it, I think Rubinius
was one where I saw it.

If voting counts, I would say (B) and set a date for removal.
--
Luis Lavena
AREA 17
-
Perfection in design is achieved not when there is nothing more to add,
but rather when there is nothing more to take away.
Antoine de Saint-Exupéry
Vassilis Rizopoulos
2011-03-14 12:28:30 UTC
Permalink
Post by Luis Lavena
Post by Jim Weirich
Post by James M. Lawrence
Are you sure you wish to deprecate 'import'? It seems a gray area due
to the reasons I gave. I assume googlers will find this thread after
being flooded with 'import' warnings :)
Ok, fair question. I'll put it to the mailing list: Deprecate import or not.
(A) Leave import as is and let JRuby worry about the conflict.
(B) Deprecate import (favoring Rake.import), eventually ceding the import statement to JRuby (this is in the current beta direction)
(C) Make A vs B a command line option (but which way to default?)
I haven't used import in *long* time, and none of my projects uses it nowdays.
I barely remember one or 2 projects that did use it, I think Rubinius
was one where I saw it.
If voting counts, I would say (B) and set a date for removal.
Ditto.
I don't think I've ever used import and I 've got several projects (6 to
be exact) here that are not mine and don't use import either.
B would be my prefered option as well.
Cheers,
V.-
--
http://www.ampelofilosofies.gr
James M. Lawrence
2011-03-14 13:55:39 UTC
Permalink
Post by James M. Lawrence
Are you sure you wish to deprecate 'import'? It seems a gray area due
to the reasons I gave. I assume googlers will find this thread after
being flooded with 'import' warnings :)
Ok, fair question.  I'll put it to the mailing list:  Deprecate import or not.
(A) Leave import as is and let JRuby worry about the conflict.
(B) Deprecate import (favoring Rake.import), eventually ceding the import statement to JRuby (this is in the current beta direction)
(C) Make A vs B a command line option (but which way to default?)
Rake is the most downloaded gem of all time. I assume that some
programmers use 'import' even if those on this list do not.

As I mentioned earlier, 'import' is only defined in jruby with
"require 'jruby'". It's not an automatic conflict.

My answer is that more data is needed. I've not heard of anyone using
jruby with rake. Given the set of programmers who do, the subset of
those who additionally need "require 'jruby'" is even smaller. It
could be the empty set. It would be most unfortunate if thousands of
programmers are annoyed in order to benefit the empty set of
programmers. And gradations thereof.
Wayne E. Seguin
2011-03-14 13:37:15 UTC
Permalink
I have never used import myself directly, I vote for B. IMHO namespacing a
loading mechanism
specifc to the library (Rake.import) is always a better option in order to
avoid general conflicts even
with other libraries.

~Wayne
Post by Jim Weirich
Post by James M. Lawrence
Are you sure you wish to deprecate 'import'? It seems a gray area due
to the reasons I gave. I assume googlers will find this thread after
being flooded with 'import' warnings :)
Ok, fair question. I'll put it to the mailing list: Deprecate import or not.
(A) Leave import as is and let JRuby worry about the conflict.
(B) Deprecate import (favoring Rake.import), eventually ceding the import
statement to JRuby (this is in the current beta direction)
(C) Make A vs B a command line option (but which way to default?)
Weight in people.
--
-- Jim Weirich
_______________________________________________
Rake-devel mailing list
http://rubyforge.org/mailman/listinfo/rake-devel
--
~Wayne

Wayne E. Seguin
***@gmail.com
wayneeseguin on irc.freenode.net
http://twitter.com/wayneeseguin/
https://github.com/wayneeseguin/
Jim Weirich
2011-03-14 18:05:02 UTC
Permalink
I have never used import myself directly, I vote for B. IMHO namespacing a loading mechanism
specifc to the library (Rake.import) is always a better option in order to avoid general conflicts even
with other libraries.
Ola tweeted that the JRuby 'import' is not recommend anymore and jruby_import is the recommended method now. Given that, I think the question is moot at this point.

I'm leaning to either A (or C with a default to A).
--
-- Jim Weirich
-- ***@gmail.com
Loading...