Java guilt

I just solved a problem by adding an instance method to String.

It makes for very elegant code elsewhere within the application.

Yet I can't shake the feeling I've done something dirty.

I think there needs to be a group like "Recovering Java Programmers
Anonymous" or somehting.

···

--
Giles Bowkett
http://www.gilesgoatboy.org


Hi --

I just solved a problem by adding an instance method to String.

It makes for very elegant code elsewhere within the application.

Yet I can't shake the feeling I've done something dirty.

I think there needs to be a group like "Recovering Java Programmers
Anonymous" or somehting.

Feeling squeamish about changing the core language isn't the sole
prerogative of recovering Java programmers :slight_smile: There's still no good
answer to the question of how to do it safely and in a way that does
not risk conflicts, though there are various "better practices". My
favorite is "extend", which lets you confine changes to particular
objects. That's not always very efficient, though.

David

···

On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
   (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Giles Bowkett wrote:

I just solved a problem by adding an instance method to String.

It makes for very elegant code elsewhere within the application.

Yet I can't shake the feeling I've done something dirty.

I think there needs to be a group like "Recovering Java Programmers
Anonymous" or somehting.

I've added instance methods to both String and Array. I didn't realize that I should feel dirty about it.

Raj

I worked in Java for 5+ years, and am coming up on my one year
anniversary on working in Ruby professionally. I *still* think adding
methods to core classes should be done very selectively, and only in
cases where that method is truly useful in a wide variety of contexts.
So if adding "foo" to String just makes my code cleaner in one spot
where its called, but I know I probably won't use "foo" anywhere else,
then I'll go with the less elegant solution of a helper method instead
of extending a builtin.

Note that I"m speaking of a larger Rails project with multiple
distributed developers - if its just you and a small side project then
hack up the core classes all you want. =)

- Rob

···

On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:

I just solved a problem by adding an instance method to String.

It makes for very elegant code elsewhere within the application.

Yet I can't shake the feeling I've done something dirty.

I think there needs to be a group like "Recovering Java Programmers
Anonymous" or somehting.

Actually that's my core concern with this kind of thing. Ruby isn't
the fastest language out there. Patching base classes could be pretty
bad for performance in some cases, although in practice it seems to
work out pretty well.

I just tried something:

Fixnum.class_eval do
  def +(number)
    self - number
  end
end

It blew up my irb.

···

On 3/14/07, David A. Black <dblack@wobblini.net> wrote:

Hi --

On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:
> I just solved a problem by adding an instance method to String.
>
> It makes for very elegant code elsewhere within the application.
>
> Yet I can't shake the feeling I've done something dirty.
>
> I think there needs to be a group like "Recovering Java Programmers
> Anonymous" or somehting.

Feeling squeamish about changing the core language isn't the sole
prerogative of recovering Java programmers :slight_smile: There's still no good
answer to the question of how to do it safely and in a way that does
not risk conflicts, though there are various "better practices". My
favorite is "extend", which lets you confine changes to particular
objects. That's not always very efficient, though.

--
Giles Bowkett
http://www.gilesgoatboy.org

http://giles.tumblr.com/

I guess you weren't raised Catholic^H^H^H^H^H^H^H^Hon Java.

···

On Thu, Mar 15, 2007 at 08:19:20AM +0900, Raj Sahae wrote:

Giles Bowkett wrote:
>I just solved a problem by adding an instance method to String.
>
>It makes for very elegant code elsewhere within the application.
>
>Yet I can't shake the feeling I've done something dirty.
>
>I think there needs to be a group like "Recovering Java Programmers
>Anonymous" or somehting.
>
I've added instance methods to both String and Array. I didn't realize
that I should feel dirty about it.

--
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
"The first rule of magic is simple. Don't waste your time waving your
hands and hopping when a rock or a club will do." - McCloctnick the Lucid

I just solved a problem by adding an instance method to String.

It makes for very elegant code elsewhere within the application.

Yet I can't shake the feeling I've done something dirty.

I think there needs to be a group like "Recovering Java Programmers
Anonymous" or somehting.

I worked in Java for 5+ years, and am coming up on my one year
anniversary on working in Ruby professionally. I *still* think adding
methods to core classes should be done very selectively, and only in
cases where that method is truly useful in a wide variety of contexts.

...and...

Note that I"m speaking of a larger Rails project with multiple
distributed developers - if its just you and a small side project then
hack up the core classes all you want. =)

There's quite a bit of irony here my friend. Rails ads a good size number of methods to the core Ruby classes. :wink:

James Edward Gray II

···

On Mar 14, 2007, at 9:06 PM, Rob Sanheim wrote:

On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:

Hi --

Giles Bowkett wrote:
> I just solved a problem by adding an instance method to String.
>
> It makes for very elegant code elsewhere within the application.
>
> Yet I can't shake the feeling I've done something dirty.
>
> I think there needs to be a group like "Recovering Java Programmers
> Anonymous" or somehting.
>
I've added instance methods to both String and Array. I didn't realize
that I should feel dirty about it.

You shouldn't -- you should just be aware of the potential problems.
Mainly it's the danger of naming conflicts, if we all start
distributing code that adds methods to the core. It's purely a
technical issue, though it's often characterized in quasi-moral terms
("great responsibilty") or stigmatized ("monkey-patching"). My
observation is that these characterizations are usually a prelude to
doing it anyway, even though they don't address the technical problems
directly.

As soon as someone figures out a way to make it work, all will be well
:slight_smile: Actually the libraries that allow block-scoped core changes have
never been widely used, as far as I can tell.

David

···

On 3/14/07, Raj Sahae <rajsahae@gmail.com> wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
   (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

True - and some of the things ActiveSupport adds are things I wouldn't
add myself, had I built Rails :). I think most of the extensions make
sense, given the type of applications Rails are targeting.

- Rob

···

On 3/14/07, James Edward Gray II <james@grayproductions.net> wrote:

On Mar 14, 2007, at 9:06 PM, Rob Sanheim wrote:

> On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:
>> I just solved a problem by adding an instance method to String.
>>
>> It makes for very elegant code elsewhere within the application.
>>
>> Yet I can't shake the feeling I've done something dirty.
>>
>> I think there needs to be a group like "Recovering Java Programmers
>> Anonymous" or somehting.
>
> I worked in Java for 5+ years, and am coming up on my one year
> anniversary on working in Ruby professionally. I *still* think adding
> methods to core classes should be done very selectively, and only in
> cases where that method is truly useful in a wide variety of contexts.

...and...

> Note that I"m speaking of a larger Rails project with multiple
> distributed developers - if its just you and a small side project then
> hack up the core classes all you want. =)

There's quite a bit of irony here my friend. Rails ads a good size
number of methods to the core Ruby classes. :wink:

James Edward Gray II

Hi David,

[snip]

As soon as someone figures out a way to make it work, all will be well
:slight_smile: Actually the libraries that allow block-scoped core changes have
never been widely used, as far as I can tell.

Are you referring to libraries like `scope-in-state'? AfaIac, these don't do
what I want them to do, which is the ability to restrict changes made to some
class while executing code in some other class. This is probably expensive as
hell and non-trivial to implement. But it sure would be great to have as it
would make Ruby a "safer" language.

Imagine if you could add String#foo to be visible within class Bar only
without having to subclass String and use it inside of Bar instead of String
(arguably the cleanest way to make this work otherwise).

Cheers,

···

On Thu, Mar 15, 2007 at 11:27:43AM +0900, David A. Black wrote:
--
Jos Backus
jos at catnook.com

I seem to remember behavio(u)rs and fluid-let...

Michael

···

On Thursday 15 March 2007, David A. Black wrote:

As soon as someone figures out a way to make it work, all will be
well

:slight_smile: Actually the libraries that allow block-scoped core changes have

never been widely used, as far as I can tell.

--
Michael Schuerig
mailto:michael@schuerig.de
Michael Schürig | Sentenced to making sense

With great power comes great responsibility!

It also might be the case in some future implementations that such a
patch might be ineffective, or intermittently effective.

For example, some Smalltalk implementations, would handle a + b under
the covers as an integer add of the two object pointers and a little
adjustment, followed by a quick check to see if the result were a
fixnum, and only send the :+ message if it wasn't. This check can be
done relatively inexpensively due to the way in which references to
FixNums (or SmallIntegers as Smalltalk called them) are encoded.

If a number x is in FixNum range then it's encoded as a 'pointer' with
the binary value x*2+1 This means that, if the low-order bit set it's
a Fixnum otherwise it isn't. So if we have two object pointers xp and
yp, referring to the objects x and y respectively we can implement x +
y as something like:

   result = xp + yp - 1;
   if (arithmetic overflow || !(result && 1) ) {
        result = send(xp,:+,yp)
   }

Note that, if xp and yp refer to Fixnums:

   xp + yp - 1
   = (x*2+1)+(y*2+1) - 1
   = x*2 + y*2 + 1
   = (x+y)*2 + 1

which is the correct representation for the FixNum x+y

I don't know whether YARV already does this or might in the future.
This is one of the things which VM implementers tend to look for, they
'cheat' and try not to get caught in the interest of performance.

Now Matz and his team might reject some of these tricks since the
dynamic nature of ruby might make it harder not to be caught, but in
some of these edge cases, I think that case can be made that it's
probably OK since it's unlikely that anyone will actually redefine
basic arithmetic operations on core classes such as FixNum and live to
tell about it without blowing up irb or worse.

···

On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:

I just tried something:

Fixnum.class_eval do
  def +(number)
    self - number
  end
end

It blew up my irb.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Exactly. So you are more in favor of the process than you thought. :wink:

James Edward Gray II

···

On Mar 14, 2007, at 10:35 PM, Rob Sanheim wrote:

On 3/14/07, James Edward Gray II <james@grayproductions.net> wrote:

On Mar 14, 2007, at 9:06 PM, Rob Sanheim wrote:

> On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:
>> I just solved a problem by adding an instance method to String.
>>
>> It makes for very elegant code elsewhere within the application.
>>
>> Yet I can't shake the feeling I've done something dirty.
>>
>> I think there needs to be a group like "Recovering Java Programmers
>> Anonymous" or somehting.
>
> I worked in Java for 5+ years, and am coming up on my one year
> anniversary on working in Ruby professionally. I *still* think adding
> methods to core classes should be done very selectively, and only in
> cases where that method is truly useful in a wide variety of contexts.

...and...

> Note that I"m speaking of a larger Rails project with multiple
> distributed developers - if its just you and a small side project then
> hack up the core classes all you want. =)

There's quite a bit of irony here my friend. Rails ads a good size
number of methods to the core Ruby classes. :wink:

James Edward Gray II

True - and some of the things ActiveSupport adds are things I wouldn't
add myself, had I built Rails :). I think most of the extensions make
sense, given the type of applications Rails are targeting.

> I just tried something:
>
> Fixnum.class_eval do
> def +(number)
> self - number
> end
> end
>
> It blew up my irb.

With great power comes great responsibility!

Two quick things about that: first, I tried it in another irb, and it
worked. This gave me great pleasure, although it was definitely a
guilty pleasure. For instance:

5 + 6

=> -1

What blew it up wasn't irb itself, but Wirble, which I use for syntax
coloring, tab completion, etc.

The other thing is, the great power/great responsibility thing, I
blogged about that a little while back, the "Ruby Is Spider-Man"
theory:

http://gilesbowkett.blogspot.com/2007/03/what-superhero-is-your-programming.html

Really though I'm growing more comfortable with the "patch everything"
philosophy. I see more problems coming from standard OO design issues
than I do from the "extra" power in Ruby.

···

On 3/15/07, Rick DeNatale <rick.denatale@gmail.com> wrote:

On 3/14/07, Giles Bowkett <gilesb@gmail.com> wrote:

--
Giles Bowkett
http://www.gilesgoatboy.org

http://giles.tumblr.com/

I wrote an experimental lib a while back that let you sub in your
class for another within the scope of another module/or class. I think
it's a pretty easy way to work with this concept. Far-sight better
than the clock based approaches, IMO. The central idea is:

  class InBlanket

    # This would have a even nicer DSL.

    String = Class.new(::String) do
      def to_s; "(" + super + ")"
    end

    def tryme
      puts "three pigs"
    end

  end

  InBlanket.new.tryme #=> "(three pigs)

This could actually be made to work fairly easily *if* literals used
the ::new methods. Unfortunately they don't. So one would have to do
back and use String.new instead of "". I consider this a design flaw
in Ruby current implementation, though I'm sure there are
justifications for it (probably execution speed related).

In any case, I think the above is about the most elegant approach
possible for selector namespaces. Every other notation I've seen
deters me due to the spaghetti it makes of the code.

T.

···

On Mar 15, 1:51 am, Jos Backus <j...@catnook.com> wrote:

    Hi David,

On Thu, Mar 15, 2007 at 11:27:43AM +0900, David A. Black wrote:

[snip]

> As soon as someone figures out a way to make it work, all will be well
> :slight_smile: Actually the libraries that allow block-scoped core changes have
> never been widely used, as far as I can tell.

Are you referring to libraries like `scope-in-state'? AfaIac, these don't do
what I want them to do, which is the ability to restrict changes made to some
class while executing code in some other class. This is probably expensive as
hell and non-trivial to implement. But it sure would be great to have as it
would make Ruby a "safer" language.

Imagine if you could add String#foo to be visible within class Bar only
without having to subclass String and use it inside of Bar instead of String
(arguably the cleanest way to make this work otherwise).

Jos Backus schrieb:

As soon as someone figures out a way to make it work, all will be well
:slight_smile: Actually the libraries that allow block-scoped core changes have
never been widely used, as far as I can tell.

Are you referring to libraries like `scope-in-state'? AfaIac, these don't do
what I want them to do, which is the ability to restrict changes made to some
class while executing code in some other class. This is probably expensive as
hell and non-trivial to implement. But it sure would be great to have as it
would make Ruby a "safer" language.

Jos, we've talked about this two months ago on ruby-core. Maybe it's only the syntax of libraries like "import-module" which you don't like, but I think they can do what you want. See below.

Imagine if you could add String#foo to be visible within class Bar only
without having to subclass String and use it inside of Bar instead of String
(arguably the cleanest way to make this work otherwise).

Changing the interface of import-module to something like Tom's example, here's your use case:

   require "import-module-extended"

   class Bar

     extending(String) do
       def foo
         "the foo version of #{self.inspect}"
       end
     end

     def initialize(name)
       @name = name
     end

     def hello(name = nil)
       name ||= @name
       puts(name.foo)
     end

   end

   b = Bar.new("Jos")
   b.hello # => the foo version of "Jos"
   b.hello("Pit") # => the foo version of "Pit"

   b.hello(1) rescue puts "no Fixnum#foo" # => no Fixnum#foo
   "Pit".foo rescue puts "no String#foo" # => no String#foo

You can see that #foo is added to String but is only visible within class Bar. (The implementation is a quick and dirty hack, though.)

Regards,
Pit

···

On Thu, Mar 15, 2007 at 11:27:43AM +0900, David A. Black wrote:

Really though I'm growing more comfortable with the "patch everything"
philosophy.

I'll borrow a quote from Alan Runyan (one of the creators of Plone),
which applies to Python and but even more so to Ruby:

"Ruby is a language for consenting adults."

s
Luciano

Trans schrieb:

I wrote an experimental lib a while back that let you sub in your
class for another within the scope of another module/or class. I think
it's a pretty easy way to work with this concept. Far-sight better
than the clock based approaches, IMO. The central idea is:

  class InBlanket

    # This would have a even nicer DSL.

    String = Class.new(::String) do
      def to_s; "(" + super + ")"
    end

    def tryme
      puts "three pigs"
    end

  end

  InBlanket.new.tryme #=> "(three pigs)

This could actually be made to work fairly easily *if* literals used
the ::new methods. Unfortunately they don't. So one would have to do
back and use String.new instead of "". I consider this a design flaw
in Ruby current implementation, though I'm sure there are
justifications for it (probably execution speed related).

Tom, what would happen in your implementation if I pass a string from the outside to tryme? And what would happen if I use a string created in InBlanket outside of the class?

Regards,
Pit

I stand corrected. This is a fine interface.

T.

···

On Mar 16, 12:45 pm, Pit Capitain <p...@capitain.de> wrote:

Jos Backus schrieb:

> On Thu, Mar 15, 2007 at 11:27:43AM +0900, David A. Black wrote:
>> As soon as someone figures out a way to make it work, all will be well
>> :slight_smile: Actually the libraries that allow block-scoped core changes have
>> never been widely used, as far as I can tell.

> Are you referring to libraries like `scope-in-state'? AfaIac, these don't do
> what I want them to do, which is the ability to restrict changes made to some
> class while executing code in some other class. This is probably expensive as
> hell and non-trivial to implement. But it sure would be great to have as it
> would make Ruby a "safer" language.

Jos, we've talked about this two months ago on ruby-core. Maybe it's
only the syntax of libraries like "import-module" which you don't like,
but I think they can do what you want. See below.

> Imagine if you could add String#foo to be visible within class Bar only
> without having to subclass String and use it inside of Bar instead of String
> (arguably the cleanest way to make this work otherwise).

Changing the interface of import-module to something like Tom's example,
here's your use case:

   require "import-module-extended"

   class Bar

     extending(String) do
       def foo
         "the foo version of #{self.inspect}"
       end
     end

     def initialize(name)
       @name = name
     end

     def hello(name = nil)
       name ||= @name
       puts(name.foo)
     end

   end

   b = Bar.new("Jos")
   b.hello # => the foo version of "Jos"
   b.hello("Pit") # => the foo version of "Pit"

   b.hello(1) rescue puts "no Fixnum#foo" # => no Fixnum#foo
   "Pit".foo rescue puts "no String#foo" # => no String#foo

Jos Backus schrieb:
>>As soon as someone figures out a way to make it work, all will be well
>>:-) Actually the libraries that allow block-scoped core changes have
>>never been widely used, as far as I can tell.
>
>Are you referring to libraries like `scope-in-state'? AfaIac, these don't
>do
>what I want them to do, which is the ability to restrict changes made to
>some
>class while executing code in some other class. This is probably expensive
>as
>hell and non-trivial to implement. But it sure would be great to have as it
>would make Ruby a "safer" language.

Jos, we've talked about this two months ago on ruby-core. Maybe it's
only the syntax of libraries like "import-module" which you don't like,
but I think they can do what you want. See below.

Indeed we did.

>Imagine if you could add String#foo to be visible within class Bar only
>without having to subclass String and use it inside of Bar instead of
>String
>(arguably the cleanest way to make this work otherwise).

Changing the interface of import-module to something like Tom's example,
here's your use case:

  require "import-module-extended"

  class Bar

    extending(String) do
      def foo
        "the foo version of #{self.inspect}"
      end
    end

    def initialize(name)
      @name = name
    end

    def hello(name = nil)
      name ||= @name
      puts(name.foo)
    end

  end

  b = Bar.new("Jos")
  b.hello # => the foo version of "Jos"
  b.hello("Pit") # => the foo version of "Pit"

  b.hello(1) rescue puts "no Fixnum#foo" # => no Fixnum#foo
  "Pit".foo rescue puts "no String#foo" # => no String#foo

You can see that #foo is added to String but is only visible within
class Bar. (The implementation is a quick and dirty hack, though.)

That's sweet! This does indeed seem to do what I'm looking for. Thanks Pit!
And Tom, too. :slight_smile:

If I wanted this to be used inside class Baz, too, would I stick `foo' in a
module and use `extending' with that module somehow? I need to go check out
`import-module-extended'...

If it's a hacky implementation, how could it be cleaned up? This would be
great to have as part of stdlib.

Cheers,

···

On Sat, Mar 17, 2007 at 01:45:03AM +0900, Pit Capitain wrote:

>On Thu, Mar 15, 2007 at 11:27:43AM +0900, David A. Black wrote:

--
Jos Backus
jos at catnook.com