Little Things

C

Chris Carter

I really think adding a new keyword, or way of calling methods is a
bad idea, and a big code smell. Having the pervasive show something
is different than the class might want you to think is good. How many
times have you been confused by some of Rails' proxy arrays, I know I
have been fooled many times, using the Pervasive in metaprogramming
allows us to see what the class ACTUALLY is.
 
D

Devin Mullins

i'm NOT advocating removing any existing methods whatsoever
Ahh... my bad. Now I capisce. Object#class will be the "Please, fool me
with your crazy proxies and your metahackery!" version, and
Pervasives::class will be the "I am smarter than you. Don't you dare try
to trick me," version.

--1 (retraction, that is)

Devin
 
A

ara.t.howard

Ahh... my bad. Now I capisce. Object#class will be the "Please, fool me with
your crazy proxies and your metahackery!" version, and Pervasives::class will
be the "I am smarter than you. Don't you dare try to trick me," version.

--1 (retraction, that is)

yeah. sorry if i was unclear about that.

cheers.

-a
 
T

Trans

Trans said:
Then go "p p" ;-)

Toliet humor --I can't beleive I said that! *blush* X-)

In anycase what about uppercase:

obj.SEND message
obj.CLASS
obj.ID

or maybe '::' can have some significance?

obj::send message
obj::class
obj::id

T.
 
C

Chris Carter

:: is the scoping operator, so unless we can make crazy lowercase
constants that can be run, I don't think that that's teh way to go
 
T

Trans

Chris said:
:: is the scoping operator, so unless we can make crazy lowercase
constants that can be run, I don't think that that's teh way to go

irb(main):001:0> obj = "string"
=> "string"
irb(main):002:0> obj::class
=> String

T.
 
C

Chris Carter

Yes, it calls methods, but just normal methods, you can't make methods
that cannot be called with ., but can with ::. But constants cannot
be called with . (or can they?)
 
J

Joel VanderWerf

Chris Carter wrote:
...
I have been following this whole dicussion, and I think it is time to
put my two cents in, and summarize it.

We started not liking how #send would call private methods. and we
need it to not call them, but wait we need soemthing so we can call
those private methds. The most commonly suggested method: #send! But
#send still causes namespace issues. The ultimate solution!...lots of
underscores. We hate those too, hrm. Lets add a new super
class/module/object/thing to the mix, called a Pervasive. When we
need something not unique to a class we call it with Pervasive.method
obj. Wait, then we do Pervasive.new(Foo, :args) every time, and we do
Pervasive.class obj a lot too. This is super ugly, probably breaks
encapsulation, etc... The solution, give the classes those methods,
and make them overriable, and also allow access to the object through
the Pervasive. Problem here though, when writing a library we won't
know that someone overrode a method somewhere else in the chain, so we
are stuck using the Pervasive a lot anyway. Why this isn't a problem
now you might ask? Because we don't have the Pervasive, so people are
less willing to override those methods. We still won't have a good
looking #send that calls private methds. Well, we will, but it needs
a name. I am willing to write up the RCR on this one.

Thanks for the summary, Chris.

Could this be solved by having a hash of method objects, accessed
through a method on Kernel?

pm = Kernel.pervasive_methods

m = pm["class"] # => #<UnboundMethod: Object#class>
"foo".bind(m).call #=> String

The values in the hash are always the original implementations.

No new syntax or modules, just one new method.
 
T

Trans

Joel said:
Thanks for the summary, Chris.

Could this be solved by having a hash of method objects, accessed
through a method on Kernel?

pm = Kernel.pervasive_methods

m = pm["class"] # => #<UnboundMethod: Object#class>
"foo".bind(m).call #=> String

The values in the hash are always the original implementations.

No new syntax or modules, just one new method.

Yes, that can be done. In fact:

require 'facets'
require 'kernel/as'

"foo".as(Kernel).class #=> String

The thing is though, do you really way to put ".as(Kernel)." or
whateverfor every pervasive call?

I know Ara says he doesn't want to get rid of the orginal methods. But
then it marginizes the whole point of it. Either we are free to use
methods such as #class and #send for our own purposes or we are not.
Trying to have it both ways won't be nearly as effective. We will still
be afraid to override those methods. I'm not saying we have to get rid
of those methods neccessarily, but I am saying the pervasive methods
would/should become the more common form. So the syntax should be
something very concise.

T.
 
J

Joel VanderWerf

Trans wrote:
...
require 'facets'
require 'kernel/as'

"foo".as(Kernel).class #=> String
Nice!

The thing is though, do you really way to put ".as(Kernel)." or
whateverfor every pervasive call?

I know Ara says he doesn't want to get rid of the orginal methods. But
then it marginizes the whole point of it. Either we are free to use
methods such as #class and #send for our own purposes or we are not.
Trying to have it both ways won't be nearly as effective. We will still
be afraid to override those methods. I'm not saying we have to get rid
of those methods neccessarily, but I am saying the pervasive methods
would/should become the more common form. So the syntax should be
something very concise.

My intuition is to make pervasive method calls a bit awkward and poorly
syntactically supported, to discourage use outside of metaprogramming
and hacking. You don't want ruby programmers to start using them by
default instead of #class, #send, etc.
 
T

Trans

Joel said:
My intuition is to make pervasive method calls a bit awkward and poorly
syntactically supported, to discourage use outside of metaprogramming
and hacking. You don't want ruby programmers to start using them by
default instead of #class, #send, etc.

I'm a meta-programmer. Why does everyone keep trying to make my life
harder? ;-)

T.
 
T

Trans

that's pretty good. i was leaning towards a module so we could just try to
write it as an extension now though...

it's backwards but... imitation of implementation:

module Kernel

def send! obj
@send_f ||= Functor.new{|op,*a| obj.send(op,*a)}
end

def class! obj
obj.class
end

def id! obj
obj.object_id
end

# ...
end

then:

obj = "hello"
obj!class #=> String

obj = 1
obj!send + 2 #=> 3

T.
 
T

Trans

Trans said:
obj = "hello"
obj!class #=> String

obj = 1
obj!send + 2 #=> 3

Oops... that's supposed to be:

obj = "hello"
class!obj #=> String

obj = 1
send!obj + 2 #=> 3

T.
 
I

Ilan Berci

Trans said:
I was a bit surprised about Matz mention of the little things in his
last <a
href="http://www.rubyist.net/~matz/slides/rc2006/mgp00017.html">ketynote</a>.
Little things can make all the difference! In fact, long time Rubyists
have been waiting a long for some important "little" things. Here's
some of the things on my little list....

First off great discussion and thank you kindly for posting the link!
Ironically, your first point about the discussion of the little things
vs Mat'z "the need for speed" has mostly gone untouched. I believe Matz
has brought up some excellent points in that slide show and that was the
first time I noticed his sense of urgency in getting the ball rolling on
1.9.

I should note before continuiing that I know nothing of the progress of
1.9 and haven't contributed in any way but like most am anxiously
looking forward to it!

My belief from reading that slide show is that the core team must be
getting hounded with suggestions, observations, complaints, etc... and
this is causing some considerable lag and frustration in it's life cycle
and this is a cry by the lead saying "Enough is enough!" I think he is
absolutely right, his team needs to push this thing out and then
formalize the process of change. IMO, they are pretty much forced to
accept a formalized process for change requests as there is now a lot of
momentum behind the language. I believe this is a key milestone for
Ruby hitting the big time.

I also really like his definition of Ruby as an "Agile" language! This
is a perfect definition and it seems so obvious after his statement.

As for the concerns over documentation, I believe it's need is too much
hyped about. Ruby is very intuitive by design and due to IRB and
metaprogramming, most of what one needs can be retreived quite easily
after reading a book or 2 and by coming here as I often do :)

He is not saying that we should stop talking about the little things,
but that we must concentrate on the big things in order that we keep up
and have a platform in which to add the little things later. A possible
analogy is a story I heard a few years back.

A professor placed a container on his desk and then proceeded to put
rocks into it, he continually placed smaller and smaller rocks into the
container as space would allow and then finally filled the remaining
space with sand. He then asked what the class learned from this
experiment.

One student exclaimed that the experiment simply showed that we can
always strive to fit more in.

The professor corrected the student and explained that if we don't do
the big things first, they will never be completed after perfoming all
the small things.


ilan
 
D

dblack

Hi --

My belief from reading that slide show is that the core team must be
getting hounded with suggestions, observations, complaints, etc... and
this is causing some considerable lag and frustration in it's life cycle
and this is a cry by the lead saying "Enough is enough!" I think he is
absolutely right, his team needs to push this thing out and then
formalize the process of change. IMO, they are pretty much forced to
accept a formalized process for change requests as there is now a lot of
momentum behind the language. I believe this is a key milestone for
Ruby hitting the big time.

Actually there's been a formalized process for several years:
http://www.rcrchive.net. It's recently been re-started, and there are
some differences in logistics (mailing lists instead of comments on
the site; more group participation in revision of RCR text). But the
basic components of the RCR, and the presence of a process, are not
new.


David

--
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)
 
T

Trans

Robert said:
I guess meta-programming shall be harder until to the point where you
insert

require 'metakit'

into your programming, what about that idea?

Could be a great one! My only concern is that having both the normal
#send, etc. and the meta-forms (whatever the syntax) could lead to some
sort of conflict that will defeat the purpose of even havnig a
"metakit". I may be totally wrong about that though --it's just a "gut"
worry.

T.
 
J

Joel VanderWerf

Trans said:
I'm a meta-programmer. Why does everyone keep trying to make my life
harder? ;-)

I'm sorry, T. You know I never meta-programmer I didn't like!
 
G

gwtmp01

that's pretty good. i was leaning towards a module so we could
just try to
write it as an extension now though...

This has been an interesting discussion but I think several related
issues have been bundled together, perhaps unnecessarily:

1) literal vs. dynamic method names

recv.method # method is explicitly named
recv.send x # method is dynamically named

2) public vs. private

recv.private_method # error
recv.send :private_method # 1.8 no error, 1.9 error
recv.funcall :private_method # 1.9 no error
recv.__send! :private_method # 1.9 no error

3) name clashes and meta programming

recv.send # is this Object#send or something else?
recv.__send__ # probably Object#send but no guarantee
recv.__send # same as __send__? or as send? or Object#send?
recv.__send! # ????
recv.class # is this Object#class? is this for recv
# or for an object proxied by recv?
recv.object_id # was this overridden? what about proxies?

I wonder if 1 & 2 might be better addressed via syntax. Something like:

recv.m # standard dispatch with literal method name
recv <- :m # standard dispatch with dynamic method name
recv <- :m2, a1 # dynamic method name with arguments
recv <-:)m2, a1) { #block} # parens needed with blocks

recv <<- :p # standard dispatch with access to private method :p

Currently a standard method (Object#send) is required to access a
dynamically
named method and that forces the dispatch semantics of the
Object#send mechanism
to become mingled with the dispatch of the message itself. That
isn't the case
with the standard 'dot' dispatch and I think it complicates the
situation
quite a bit. By using different syntax for dispatch to dynamically
named methods
there is no need to worry about Object#send itself being overridden.
The syntax
I suggested above (<- and <<-) is not special, just a way to
illustrate the idea.

That still leaves the problem of name clashes and unanticipated
redefinitions for
things like #class, #object_id, and so on. Could this be handled by
providing
a way to override the normal method lookup process?

(recv, BasicObject).class
(recv, BasicObject).object_id

Again, the syntax is just a suggestion, but the idea is to force
Ruby's method lookup
process to begin its search with a particular class, bypassing the
normal order of
lookups. The two ideas can be combined:

(recv, BasicObject) <- :class

BasicObject could be frozen so that its methods can't be redefined/
undefined.

Regardless of my particular suggestions I think it is helpful to view
the issues (1,2,3)
separately rather than as a larger indivisible problem.

Gary Wright
 
G

gwtmp01

I wonder if 1 & 2 might be better addressed via syntax. Something
like:

recv.m # standard dispatch with literal method name
recv <- :m # standard dispatch with dynamic method name

Another thought on the syntax:

recv.m a1
recv._ :m, a1 # dispatch to named method
recv.! :m, a1 # dispatch to named method (include private methods)

The mnemonic is that the underscore represents a blank method name
and the
blank is filled in by the first argument. Just think of the sequence
"._"
and ".!" as syntax and not as the standard dot with methods "_" and "!".

Of course this means that "_" and "!" would not be valid method names
(well,
"!" is already invalid

Gary Wright

P.S. Does anyone else think that language design is unnecessarily
constrained
by insisting on ASCII/Latin-1 characters? It sure would be nice to
assume that
source code was in Unicode and thus gain access to some more interesting
characters to use for language semantics.

P.P.S. Yes, I know about APL.

Gary Wright
 
T

Trans

This has been an interesting discussion but I think several related
issues have been bundled together, perhaps unnecessarily:

1) literal vs. dynamic method names

recv.method # method is explicitly named
recv.send x # method is dynamically named

2) public vs. private

recv.private_method # error
recv.send :private_method # 1.8 no error, 1.9 error
recv.funcall :private_method # 1.9 no error
recv.__send! :private_method # 1.9 no error

3) name clashes and meta programming

recv.send # is this Object#send or something else?
recv.__send__ # probably Object#send but no guarantee
recv.__send # same as __send__? or as send? or Object#send?
recv.__send! # ????
recv.class # is this Object#class? is this for recv
# or for an object proxied by recv?
recv.object_id # was this overridden? what about proxies?

I wonder if 1 & 2 might be better addressed via syntax. Something like:

recv.m # standard dispatch with literal method name
recv <- :m # standard dispatch with dynamic method name
recv <- :m2, a1 # dynamic method name with arguments
recv <-:)m2, a1) { #block} # parens needed with blocks

recv <<- :p # standard dispatch with access to private method :p

Currently a standard method (Object#send) is required to access a
dynamically
named method and that forces the dispatch semantics of the
Object#send mechanism
to become mingled with the dispatch of the message itself. That
isn't the case
with the standard 'dot' dispatch and I think it complicates the
situation
quite a bit. By using different syntax for dispatch to dynamically
named methods
there is no need to worry about Object#send itself being overridden.
The syntax
I suggested above (<- and <<-) is not special, just a way to
illustrate the idea.

That still leaves the problem of name clashes and unanticipated
redefinitions for
things like #class, #object_id, and so on. Could this be handled by
providing
a way to override the normal method lookup process?

(recv, BasicObject).class
(recv, BasicObject).object_id

Again, the syntax is just a suggestion, but the idea is to force
Ruby's method lookup
process to begin its search with a particular class, bypassing the
normal order of
lookups. The two ideas can be combined:

(recv, BasicObject) <- :class

BasicObject could be frozen so that its methods can't be redefined/
undefined.

Regardless of my particular suggestions I think it is helpful to view
the issues (1,2,3)
separately rather than as a larger indivisible problem.

Great observations and well summarized. Thank you!

I like you're '<-' idea. I think you make a very good point about this
being a dynamic dispatch operator. It did not dawn on me before but it
doesn't make a whole lot of sense to have overridable dyanimic dispatch
but not for literal dispatch. #send should just mean '.' And I would
suggest that unless #send is going to control all dispatching,
including literal calls, then another operator as you suggest is the
right idea.

The operator you suggest however would probably have to be flipped to
avoid ambiguity with Symbol#@-. Eg. recv < -:class (I know rare. but
possible).

As for the class search idea, that can be done easily enough with:

recv.as(BasicObject) -> :class

Though is would be better to code #as into core. But I would like to
see a short hand for the BasicObject case. Maybe

recv ~> :class

To outline, this would give ruby a complete set of dispatch operators:

. literal
<- dynamic
<<- functional (dynamic)
<~ pervasive (dynamic)

T.
 

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

Forum statistics

Threads
473,765
Messages
2,569,568
Members
45,042
Latest member
icassiem

Latest Threads

Top