Best name for "this method" ?

T

trans. (T. Onoma)

Hi --

  foo.methods[:new, :protected]   # if you need combination

This line's got me thinking... How does one define a class []
constructor? For example Hash can be use like this:

Hash[:a=>1,:b=>2 ]

class C
def C.[](...)
...
end
end

Duh! Thanks, I don't know why I thought there was something special about it.
You can define such methods; for example, there's Integer. A number
of people (including me :) aren't big fans of method names that begin
with uppercase letters, but it can be done.

Right. Well then, I must propose that all such class names be constructor
methods too. No sense in confusing things otherwise. By default:

def AClass(*args, &blk)
AClass.new(*args, &blk)
end

But for something like Hash, it would be defined like Hash[].

MHO,
T.

P.S. Okay, this is where you tell me why this is a bad idea ;)
 
A

Ara.T.Howard

  foo.methods[:new, :protected]   # if you need combination

This line's got me thinking... How does one define a class [] constructor? For
example Hash can be use like this:

Hash[:a=>1,:b=>2 ]

class << self; alias [] new; end
And then I start to wonder why we can't just use the class name like a method?

Hash:)a=>1, :b=>2)

probably possible:

irb(main):029:0> def method_missing(m,*a,&b);Class === (c = eval(m.to_s)) ?
c::new(*a,&b) : super;end
=> nil

irb(main):030:0> Range(1,2)
=> 1..2

??

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
D

David A. Black

Hi --

Right. Well then, I must propose that all such class names be constructor
methods too. No sense in confusing things otherwise. By default:

def AClass(*args, &blk)
AClass.new(*args, &blk)
end

I'm not getting the point of that. Why do you need a wrapper like
that around new? Also, the one somewhat common case of this --
Integer -- isn't a wrapper for new, since there is no Integer.new. So
you'd be introducing a constraint that currently doesn't exist.
But for something like Hash, it would be defined like Hash[].

What is "something like Hash" in this context? I'm not following
here.


David
 
T

trans. (T. Onoma)

probably possible:

     irb(main):029:0> def method_missing(m,*a,&b);Class === (c =
eval(m.to_s)) ? c::new(*a,&b) : super;end
     => nil

     irb(main):030:0> Range(1,2)
     => 1..2

??

Oooo... me likes.

Just added to my lib.

T.
 
T

trans. (T. Onoma)

I'm not getting the point of that. Why do you need a wrapper like
that around new? Also, the one somewhat common case of this --
Integer -- isn't a wrapper for new, since there is no Integer.new. So
you'd be introducing a constraint that currently doesn't exist.

Sorry, I should explain better. Let me put it this way: Why would I want to
write a constructor like Hash[], when it could just as well be written
Hash()? And in fact I don't --I cannot think of a single time that I have
used the later notation. Why? *Not* because it isn't useful, but rather b/c
it obfuscates my code b/c is looks like an Array or Hash lookup, and not like
calling a constructor method.
But for something like Hash, it would be defined like Hash[].

What is "something like Hash" in this context? I'm not following
here.

In other words, I am not saying it has to be X() == X.new(). Rather Hash() can
do what Hash[] does. And likewise for Integer(). They are specialized
constructor methods.

So my point, really, is simply, why not have this be default behavior for all
classes? Specialized forms can be specially defined, the others can be
equivalent to #new. Personally I like the look of it too.

T.
 
J

James Edward Gray II

Why would I want to write a constructor like Hash[], when it could
just as well be written Hash()? And in fact I don't --I cannot think
of a single time that I have
used the later notation. Why? *Not* because it isn't useful, but
rather b/c
it obfuscates my code b/c is looks like an Array or Hash lookup, and
not like
calling a constructor method.

I'm not a fan of Class(), but I have to agree with the above complaint.
Why Hash[] makes a new Hash is beyond me. I'm not a fan of that
interface.

James Edward Gray II
 
T

trans. (T. Onoma)

I'll preface this with saying I don't know Ruby yet as well as I know
Smalltalk, so please correct any fine points I get wrong.

In Smalltalk, the calling context is called "thisContext" because it
can be either a method or a block. And it returns an actual context
object, which are represented by a class in Smalltalk, but which are
not (as far as I can tell) reified in Ruby.

So if you implemented it in Ruby, you'd have to decide whether it
referred to the block context or the enclosing method context,
and you'd have to invent a reification of the dynamic execution
context, as the method name by itself isn't very useful.

I'd certainly think twice about adding it to the language. What you
explicitly leave out of a language is as important as what you put in.

In 20+ years of reading and writing Smalltalk, I've hardly ever used
it or seen it used except for writing debuggers and similar tools that
deal with dynamic execution state.

I wanted to include some statistics on its use in Smalltalk, but
unfortunately, it's not a true message send in VisualWorks; it's
inlined by the compiler. So you'd have to write some bytecode scanning
code to find where it's called (which might be fun!)

Did anyone ever respond to you? If no, we's very sorry.

Actually Ruby has something quite like thisContext called a Binding. At least
I think they would be the same according to your description. (Yes, the
Smalltalk name is probably better.)

Bindings are a bit heavy weight (I think) for just getting the current method
name. Although, it would be cool if Bindings had little to no cost, then we
could use the heck out of em.

Anyone know what the costs associated with Bindings are more exactly?

T.
 
T

trans. (T. Onoma)

Why not method_name? called() is a bit ambiguous IMHO...

Two downsides of method_name. The lesser is that it is not brief. The grater
is that it indicates nothing about the fact that it is _this_, the current,
method's name.

T.
 
A

Ara.T.Howard

Oooo... me likes.

Just added to my lib.

T.

it might be dangerous - although i can see why it would be. just pointing out
it can be done easily. generally at this point guy chimes in with something
subversive that could be done by using eval - perhaps something like

class Evil
def to_s
'system "rm -rf ."'
end
end

Evil()

it does look nice though.

cheers.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
G

gabriele renzi

trans. (T. Onoma) ha scritto:
Two downsides of method_name. The lesser is that it is not brief. The grater
is that it indicates nothing about the fact that it is _this_, the current,
method's name.

I think the groovy guys name it 'callee' or something similar.
I remember seeing it as a way to write recursive procs, but I may be wring.
 
R

Robert Klemme

trans. (T. Onoma) said:
I'm not getting the point of that. Why do you need a wrapper like
that around new? Also, the one somewhat common case of this --
Integer -- isn't a wrapper for new, since there is no Integer.new. So
you'd be introducing a constraint that currently doesn't exist.

Sorry, I should explain better. Let me put it this way: Why would I want to
write a constructor like Hash[], when it could just as well be written
Hash()? And in fact I don't --I cannot think of a single time that I have
used the later notation. Why? *Not* because it isn't useful, but rather b/c
it obfuscates my code b/c is looks like an Array or Hash lookup, and not like
calling a constructor method.
But for something like Hash, it would be defined like Hash[].

What is "something like Hash" in this context? I'm not following
here.

In other words, I am not saying it has to be X() == X.new(). Rather Hash() can
do what Hash[] does. And likewise for Integer(). They are specialized
constructor methods.

So my point, really, is simply, why not have this be default behavior for all
classes? Specialized forms can be specially defined, the others can be
equivalent to #new. Personally I like the look of it too.

I prefer #new because it emphasizes the factoryness of a Class instance.
Class() doesn't help you in cases like these:

class SomeFactory
def initialize(cl)
@cl = cl
end

def create() @cl.new end
def discard(obj) end
end

Also, methods Integer() and such are defined in Kernel. Having such a
method as a wrapper for C.new in Kernel for every class would clutter
Kernel unnecessarily and introduce unnecessary dependencies. I try to
stick to the rule of thumb to change base classes as minimal as possible.
That way code stays maintainable and the likeliness of imcompatibilities
between different classes that change Kernel and the like decreases.

Kind regards

robert
 
R

Robert Klemme

trans. (T. Onoma) said:
Oooo... me likes.

Just added to my lib.
But:
NoMethodError: undefined method `B' for A:Module
from (irb):7NoMethodError: undefined method `B' for main:Object
from (irb):9

Kind regards

robert
 
T

trans. (T. Onoma)

I prefer #new because it emphasizes the factoryness of a Class instance.
Class() doesn't help you in cases like these:

class SomeFactory
def initialize(cl)
@cl = cl
end

def create() @cl.new end
def discard(obj) end
end

I don't follow. Help you do what? It would still instantiate the factory.
(IMHO) factories are better as module functions, anyway. So you could do
something like:

class SomeFactory
def self.set(cl)
@@cl = cl
end
def self.new
@@cl.new
end
end

SomeFactory.set(String)
str = SomeFactory()

If one so desired.

Besides, all methods that return a new value are "factories". That;s actually
the main point --why () is better then [].
Also, methods Integer() and such are defined in Kernel. Having such a
method as a wrapper for C.new in Kernel for every class would clutter
Kernel unnecessarily and introduce unnecessary dependencies. I try to
stick to the rule of thumb to change base classes as minimal as possible.
That way code stays maintainable and the likeliness of imcompatibilities
between different classes that change Kernel and the like decreases.

Sure. I'd rather not clutter up Kernel either. I think its already got too
many methods (why all those string related methods, for instance?) But in
this case it doesn't really bother me, especially if a missing_method takes
care of it.

It might be interesting if () were a "method dispatcher" method itself, then
it could be defined/redefined like [] is. But don't quote me on that, for the
moment it's just a passing thought ;)

T.
 
F

Florian Gross

James said:
I'm not a fan of Class(), but I have to agree with the above complaint.
Why Hash[] makes a new Hash is beyond me.

Array[] can be used to construct a new Array from values and Hash[] can
be used to construct a new Hash from values.

Regards,
Florian Gross
 
J

James Edward Gray II

James said:
I'm not a fan of Class(), but I have to agree with the above
complaint. Why Hash[] makes a new Hash is beyond me.

Array[] can be used to construct a new Array from values and Hash[]
can be used to construct a new Hash from values.

For some reason, when you put it that way, it made a little more sense.
A parallel to the instance method I guess. Hmm...

James Edward Gray II
 
T

trans. (T. Onoma)

NoMethodError: undefined method `B' for A:Module
from (irb):7


=> Object


NoMethodError: undefined method `B' for main:Object
from (irb):9

I was waiting for this ;) See if you can break this one.

class Object
def const_get(c)
self.class.const_get(c)
end
def const_set(c,v)
self.class.const_set(c,v)
end
end

module Kernel
alias method_missing_orig method_missing
def method_missing(m,*a,&b)
Class === (c = const_get(m)) ? c::new(*a,&b) :
method_missing_orig(m,*a,&b)
end
end
 
D

David A. Black

Hi --

I was waiting for this ;) See if you can break this one.

class Object
def const_get(c)
self.class.const_get(c)
end
def const_set(c,v)
self.class.const_set(c,v)
end
end

I've lost track of where this is going a bit, but here you seem to be
making it look like non-module/class objects have constants:

a = ""
a.const_set("X",1)
p a.const_get("X") # 1

not to mention:

p String::X # 1

(i.e., indirect setting of a Class object's constant).


David
 
A

Ara.T.Howard

I was waiting for this ;) See if you can break this one.

harp:~ > cat c.rb
class Object
def const_get(c)
self.class.const_get(c)
end
def const_set(c,v)
self.class.const_set(c,v)
end
end
module Kernel
alias method_missing_orig method_missing
def method_missing(m,*a,&b)
Class === (c = const_get(m)) ? c::new(*a,&b) : method_missing_orig(m,*a,&b)
end
end
require 'singleton'
class C; include Singleton; end
C()

harp:~ > ruby c.rb
c.rb:12:in `const_get': wrong constant name new (NameError)
from c.rb:12:in `method_missing'
from c.rb:12:in `method_missing'
from c.rb:17


tho that may not be fair.

cheers.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
T

trans. (T. Onoma)

Two downsides of method_name. The lesser is that it is not brief. The
grater is that it indicates nothing about the fact that it is _this_, the
current, method's name.

It occurs to me that technically the method name should be called the
'message', shouldn't it?

T.
 
D

David A. Black

Hi --

It occurs to me that technically the method name should be called the
'message', shouldn't it?

Not necessarily. Messages being sent to objects can result in methods
being invoked, but there is not an identity or one-to-one
correspondence between the two things. They just happen to (often)
coincide.

Consider this:

a = Object.new
def a.meth; puts "hi"; end
a.method("meth").call # hi

At no point has the message "meth" been sent to the object a -- but
"meth" is still the method's name.


David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top