Ask a Question related to Ruby, Design and Development.
-
David Naseby #41
Re: "stereotyping"
> From: Rasputin [mailto:rasputin@idoru.mine.nu]
Below is a quick hack to do that. Needs work. Needs redirection of IO. But> It seemed like you were more interested in a way to know how an API
> will use your object. Why not send in a probe?
>
> Pass a custom object in that has a method_missing? method that does
> a ludicrous amount of debugging of how its called. That would tell you
> how an API is actually using your object, what methods it calls and how.
its kinda cute.. Has issues with side effects, of course, and printing
crapola all over the place.
# Usage:
# ins = ObjectProbe::Inspector.new( SomeObject.new )
# ins.probe
module ObjectProbe
class Inspector
def initialize( object )
@object = object
end
def target_class
@object.class
end
def target_methods
@object.methods - Object.new.methods
end
def probe
puts "Probing: #{target_class}"
target_methods.each do | method |
meta = MetaMethod.new( method.intern, @object )
print " Method: #{method}( "
meta.args.each do | arg |
print "[ #{arg.___requires.join(', ')} ], "
end
puts
end
end
end
class MetaMethod
def initialize( method, object )
@method = method
@object = object
end
def symbol
@method
end
def arity
m = @object.method( @method )
m.arity
end
def args
result = []
arity.times { result << DummyArgument.new }
begin
@object.send( @method, *result )
rescue
puts $!.to_s
end
result
end
end
class DummyArgument
attr_reader :___requires
def initialize
@___requires = []
end
def DummyArgument.clean_out_methods
methods_list = Object.new.methods
methods_list.each do | m |
meth = m.intern
# keep the important fns, and keep __send__ and __id__ to prevent
warnings.
next if( meth == :method_missing || meth == :__send__ || meth ==
:__id__ )
module_eval <<-"end_eval"
alias_method :__#{meth.to_i}__, #{meth.inspect}
def #{meth.id2name}(*args, &block)
method_missing( :#{meth}, *args )
__#{meth.to_i}__(*args, &block)
end
end_eval
end
end
def method_missing( symbol, *args )
@___requires << symbol
end
clean_out_methods
end
end
David Naseby Guest
-
"stereotyping" (was: Strong Typing (Managing metadata about attribute types) )
On Thu, 20 Nov 2003 14:52:17 +0900, Thien Vuong wrote: Again: why? Why do you need intrinsic interface validation? As Michael Campbell noted, if... -
"stereotyping" (was: Strong Typing (Managing metadata about attribute types)
On Thu, 20 Nov 2003 14:08:51 +0900, Simon Kitching wrote: You're right. Drb uses Marshal#dump and Marshal#load. YAPC uses YAML which has... -
"stereotyping" (was: Strong Typing (Managing metadataabout attribute types)
Simon, there is another way, the classes can be substantiated only on the remote end and all messages are routed to the remote object. the local... -
"stereotyping" (was: Strong Typing (Managing metadataabout attribute types)
Simon, yes, i understood that the first time. (sorry, i just spent a couple of hours reading through hugely verbose posts that tended toward... -
"stereotyping" (was: Strong Typing (Managing metadata about attribute types) )
On Thu, 20 Nov 2003 08:21:34 +0900, Sean O'Dell wrote: So does the existing one: foo.backend NoMethodError: undefined method `backend' for... -
Dan Doel #42
Re: "stereotyping"
Sean O'Dell wrote:
You always have to update documentation when you change something.>>>But again, its less hassle to document your API than to do rigourous
>>argument checking.
>>
>>
>No, it's more hassle. To update a document, you have to open a different
>file, and if you make a typo or just plain write it wrong, there is nothing
>to stop you from doing so. Interfaces can be described in the same source
>file as your class definition, so it's easy to find and update, plus, you
>can't update it wrong, or your code gives you errors.
>
>
Having an interface checking
system doesn't mean that you don't have to document your code. So in
effect, having interfaces means
you have to update two different places when you make an interface
change (three, actually, if you
count the code that uses the interface), and there's more things that
can get out of sync.
Besides, with systems like RDoc you can make all documentation
annotations in your source and
generate the documentation from there, so it's really no more or less
convenient than having an
interface definition in your source, at least for documentation purposes.
- Dan
Dan Doel Guest
-
Sean O'Dell #43
Re: "stereotyping"
On Friday 21 November 2003 01:50 pm, Dan Doel wrote:
Not always. If you provide code to others and are responsible enough to do> Sean O'Dell wrote:>> >> >>But again, its less hassle to document your API than to do rigourous
> >>argument checking.
> >No, it's more hassle. To update a document, you have to open a different
> >file, and if you make a typo or just plain write it wrong, there is
> > nothing to stop you from doing so. Interfaces can be described in the
> > same source file as your class definition, so it's easy to find and
> > update, plus, you can't update it wrong, or your code gives you errors.
> You always have to update documentation when you change something.
so, sure. On team projects, documentation happens very sporadically. RAA is
full of non or poorly documentation code. It is a good habit to have, but
humans often don't keep up with as well as they should.
Or, you could argue, the interface description could serve as the source for> Having an interface checking
> system doesn't mean that you don't have to document your code. So in
> effect, having interfaces means
> you have to update two different places when you make an interface
> change (three, actually, if you
> count the code that uses the interface), and there's more things that
> can get out of sync.
your API documentation. I'm going to add that to the wiki; the idea just
occurred to me. Automatic documentation generation would be extremely easy
if you had interface objects to query.
That much is a plus, but the biggest problem I have with that is the same as> Besides, with systems like RDoc you can make all documentation
> annotations in your source and
> generate the documentation from there, so it's really no more or less
> convenient than having an
> interface definition in your source, at least for documentation purposes.
the problem I had with defining interfaces through classes: methods are
spread out by the code inside them. Browsing a class is not all that
pleasant because of that. Smaller source files aren't so bad, but when a lot
of code sits in a source file, everything gets really spread out.
Sean O'Dell
Sean O'Dell Guest
-
Sean O'Dell #44
Re: "stereotyping"
On Friday 21 November 2003 02:42 pm, Dave Brown wrote:
I know. I agree, too. Doesn't happen as often as I wish.> In article <200311201143.59231.sean@celsoft.com>,
>
> Sean O'Dell <sean@celsoft.com> wrote:
> : Q: Okay. We have to look to code quite often in lieu of project
> : documentation, and normally we look to the description of
> : classes, and the declarations of function parameters to
> : determine how to make calls and to understand how classes are
> : designed that are unfamiliar to some of the programmers on the
> : team. Type checking would help us to know what parameters are
> : used by certain methods at-a-glance, which saves us from having
> : to spend time studying source code to figure things out.
>
> Of course, the simple answer to that is to use
> properly-descriptive parameter names.
I disagree here. It's a nomenclature issue, I suppose, but I am personally> It generally doesn't matter what something is made of--what
> matters is what it *is*.
only concerned about what an object does, not what it is. I can't use an
object passed to me that is a string, if it gives me no way to make use of
it. I need access, so to me the most important thing is what it does.
Also, objects do things in different ways. I could have an object that is a
Report object. If it uses text files, great, that's easy. If it uses MySQL,
okay, let me go set up a table it can use somewhere, or make the connection
to an existing one. It's what it does that determines there is an issue.
But, then again, you can say that with something like an interface, you're
making both statements. Interfaces are immutable, and you can't partially
implement one. When fulfilled, you can say "this object is this" as well as
"this object does this" pretty clearly.
Yeah, I know people feel that way. The problem I have with that point of view> In other words, if it's Java you're looking for, you know where to
> find it. Ruby "market share" isn't something I think is even
> worth considering. It's a wonderfully handy tool and it makes my
> life easier, and that's all I ask of it.
is that not caring about market share sounds a lot like not caring about
anyone outside the Ruby community. Getting programmers to use Ruby is not
about gaining market share, it's about being able to say "Ruby is here to be
the best programming language we can make it, no more and no less." If you
decide that features from Java aren't worth putting in simply because Java
has it, that's prejudice that I don't think is at the heart of Ruby. Ruby is
about adopting what works. Interfaces work in lots of places. Directing
people away from Ruby to get a feature like this doesn't seem to me what the
Ruby community historically has done. It's packed with lots of cool features
taken from here and there. If interfaces can be done with finesse and makes
Ruby stronger, it should be adopted. As things progress, it seems like we've
found a way to do it without a lot of back-breaking work which doesn't break
Ruby now, and which also doesn't look like a third eye growing out of its
elbow. It could be just another quietly tucked away feature that gets used
by some, ignored by others.
Being able to put something on a feature list is not a reason to discount it,> I don't care what management thinks of Ruby: I only care about
> getting the job done. When something needs to be done, I use
> whatever tools are at my disposal and are most effective. Ruby
> doesn't need to be "promoted"; it just needs to be used. Let it
> promote itself by demonstrating results. Leave the bulleted
> feature lists to the likes of Microsoft Word.
though, either. It has value in itself. If people have been asking for
something, and you've found a cool way to do it that fits right in with the
language, then you put it on the list. But that's not WHY you do it, to put
it on the list. You do it because there are real reasons for it, and the
reward is yet another really cool feature on the list.
Ask yourself: why does Ruby have iterators? You could do loops lots of other
ways. It's there because it was the coolest, smoothest way that could be
conceived of at the time and it endures today.
This is what I think we can achieve. Something cool and smooth and which will
endure and will make Ruby just that one little bit better.
Sean O'Dell
Sean O'Dell Guest
-
Yukihiro Matsumoto #45
Re: "stereotyping"
Hi,
In message "Re: "stereotyping""
on 03/11/22, gabriele renzi <surrender_it@rc1.vip.ukl.yahoo.com> writes:
|il Fri, 21 Nov 2003 08:11:17 -0700, "Ara.T.Howard"
|<ahoward@ngdc.noaa.gov> ha scritto::
|>tcl is the worlds greatest language, but ousterhout is a very bright guy.
|mh.. based on this we must hope that matz is really really stupid :)
Don't worry. I am.
By the way, where should I put "not" in the above statement, Ara?
matz.
Yukihiro Matsumoto Guest
-
Greg McIntyre #46
Re: "stereotyping"
"David Naseby" <david.naseby@eonesolutions.com.au> wrote:
Is this or something like it on the RAA? Perhaps a slightly more general> Below is a quick hack to do that. Needs work. Needs redirection of IO.
> But its kinda cute.. Has issues with side effects, of course, and
> printing crapola all over the place.
mechanism to proxy messages to the "real" object and call a
hook/callback?
--
Greg McIntyre ======[ [email]greg@puyo.cjb.net[/email] ]===[ [url]http://puyo.cjb.net[/url] ]===
Greg McIntyre Guest
-
Ara.T.Howard #47
Re: "stereotyping"
On Sat, 22 Nov 2003, Yukihiro Matsumoto wrote:
> Hi,
>
> In message "Re: "stereotyping""
> on 03/11/22, gabriele renzi <surrender_it@rc1.vip.ukl.yahoo.com> writes:
>
> |il Fri, 21 Nov 2003 08:11:17 -0700, "Ara.T.Howard"
> |<ahoward@ngdc.noaa.gov> ha scritto::
>
> |>tcl is the worlds greatest language, but ousterhout is a very bright guy.
>
> |mh.. based on this we must hope that matz is really really stupid :)
>
> Don't worry. I am.
>
> By the way, where should I put "not" in the above statement, Ara?
>
> matz.
loop { self.mouth << self.foot } if clr?
for the record:
tcl is not the worlds greatest language, but ousterhout is a very bright guy.
^^^
^^^
^^^
wouldn't want to offend ousterhout!
;-)
-a
--
ATTN: please update your address books with address below!
================================================== =============================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| STP :: [url]http://www.ngdc.noaa.gov/stp/[/url]
| NGDC :: [url]http://www.ngdc.noaa.gov/[/url]
| NESDIS :: [url]http://www.nesdis.noaa.gov/[/url]
| NOAA :: [url]http://www.noaa.gov/[/url]
| US DOC :: [url]http://www.commerce.gov/[/url]
|
| The difference between art and science is that science is what we
| understand well enough to explain to a computer.
| Art is everything else.
| -- Donald Knuth, "Discover"
|
| /bin/sh -c 'for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done'
================================================== =============================
Ara.T.Howard Guest
-
T. Onoma #48
Re: "stereotyping"
and i thought it was so radical when i wrote it yesterday
# notice if TypeErrors woud return offending respond_to? method
# in error message then it would continue to probe
class DuckHunter
def initialize
@a_r_g_s = {}
end
def a_r_g_s
@a_r_g_s
end
def d_u_c_k_c_a_l_l
begin
yield
rescue TypeError => e
self.send(e.message)
retry
end
end
def method_missing(aSym, *args)
# This will happen the first time
aSymStr = aSym.to_s
@a_r_g_s["#{aSymStr}"] = [ args.collect { |a| "#{a.class}" } ]
begin
d = %Q{
def self.#{aSymStr}(*args)
# This will happen the subsequent time
@a_r_g_s["#{aSymStr}"] } + %q{.concat [ args.collect { |a|
"#{a.class}" } ]
self
end
}
instance_eval d
rescue SyntaxError
puts "TypeError induced SyntaxError! TypeError must return respond_to
method!"
raise
end
self
end
end
# example
class TypeTest
def ameth(x)
big4 x
#---
puts x.to_i
puts x.jump(4)
puts x.do_what_ever("Duck can take it!", /\w+/)
puts x.do_what_ever("Duck can take it!", /\w+/, 42)
end
end
t = TypeTest.new
puts "\nDUCK QUACKS"
dh = DuckHunter.new
dh.d_u_c_k_c_a_l_l do
t.ameth(dh)
end
# show args
puts "\nameth:"
dh.a_r_g_s.each { |name, argpat| argpat.each { |args| puts "\t#{name}
(#{args.join(',')})" } }
# -----------
On Saturday 22 November 2003 12:52 am, Greg McIntyre wrote:late could be added> "David Naseby" <david.naseby@eonesolutions.com.au> wrote:>> > Below is a quick hack to do that. Needs work. Needs redirection of IO.
> > But its kinda cute.. Has issues with side effects, of course, and
> > printing crapola all over the place.
> Is this or something like it on the RAA? Perhaps a slightly more general
> mechanism to proxy messages to the "real" object and call a
> hook/callback?
T. Onoma Guest
-
T. Onoma #49
Re: "stereotyping"
Sorry I forgot to post results of DuckHunter examples. (DuckHunter itself is
also included below).
DuckHunter is a concise probe providing the functionality of #duck_signature,
and has a unique feature that suggests how Ruby might proceed to cleaning up
some of its code: If a type error returns the method that was not implemented
in the error message then DuckHunter will fix and continue to probe. Using
this on a number of libraries I have discoverd that ruby has a problem in
that it allows TypeError to be raised for any reason whatsoever. There needs
to be a tighter system for raising TypeErrors, including returning the
offened method. I believe that one of the first things that needs to happen
to improve Ruby's type mechanics is to ensure that a signature probe can run
without fail on any method.
Results:
DUCK QUACKS
big4:
succ()
to_i()DUCK QUACKS>()
>(Fixnum)
#<DuckHunter:0x402a8738>
#<DuckHunter:0x402a8738>
#<DuckHunter:0x402a8738>
#<DuckHunter:0x402a8738>
ameth:
succ()
jump(Fixnum)
to_i()
to_i()do_what_ever(String,Regexp)>()
>(Fixnum)
do_what_ever(String,Regexp,Fixnum)
-t0
On Saturday 22 November 2003 02:22 am, T. Onoma wrote:> and i thought it was so radical when i wrote it yesterday
>
> # notice if TypeErrors woud return offending respond_to? method
> # in error message then it would continue to probe
>
> class DuckHunter
>
> def initialize
> @a_r_g_s = {}
> end
>
> def a_r_g_s
> @a_r_g_s
> end
>
> def d_u_c_k_c_a_l_l
> begin
> yield
> rescue TypeError => e
> self.send(e.message)
> retry
> end
> end
>
> def method_missing(aSym, *args)
> # This will happen the first time
> aSymStr = aSym.to_s
> @a_r_g_s["#{aSymStr}"] = [ args.collect { |a| "#{a.class}" } ]
> begin
> d = %Q{
> def self.#{aSymStr}(*args)
> # This will happen the subsequent time
> @a_r_g_s["#{aSymStr}"] } + %q{.concat [ args.collect { |a|
> "#{a.class}" } ]
> self
> end
> }
> instance_eval d
> rescue SyntaxError
> puts "TypeError induced SyntaxError! TypeError must return respond_to
> method!"
> raise
> end
> self
> end
>
> end
>
> # example
>
> class TypeTest
> def ameth(x)
> big4 x
> #---
> puts x.to_i
> puts x.jump(4)
> puts x.do_what_ever("Duck can take it!", /\w+/)
> puts x.do_what_ever("Duck can take it!", /\w+/, 42)
> end
> end
>
> t = TypeTest.new
>
> puts "\nDUCK QUACKS"
>
> dh = DuckHunter.new
> dh.d_u_c_k_c_a_l_l do
> t.ameth(dh)
> end
>
> # show args
> puts "\nameth:"
> dh.a_r_g_s.each { |name, argpat| argpat.each { |args| puts "\t#{name}
> (#{args.join(',')})" } }
>
> # -----------
>
> On Saturday 22 November 2003 12:52 am, Greg McIntyre wrote:>> > "David Naseby" <david.naseby@eonesolutions.com.au> wrote:> >> > > Below is a quick hack to do that. Needs work. Needs redirection of IO.
> > > But its kinda cute.. Has issues with side effects, of course, and
> > > printing crapola all over the place.
> > Is this or something like it on the RAA? Perhaps a slightly more general
> > mechanism to proxy messages to the "real" object and call a
> > hook/callback?
> late could be added
T. Onoma Guest
-
Rasputin #50
Re: "stereotyping"
* Sean O'Dell <sean@celsoft.com> [1115 21:15]:
> On Friday 21 November 2003 12:48 pm, Rasputin wrote:> > * Sean O'Dell <sean@celsoft.com> [1144 19:44]:
> > This seems to be using interface implementation to flag a class
> > as suitable for use in a particular way. Thats just as much an agreed
> > protocol between the method and the argument as a respond_to? approach,
> > but respond_to? doesnt require such a fundamental change to the
> > language (and thats what it would have to be, if it was really to be
> > useful - I dont think an optional feature would please anyone).Right, but thats no different to enforcing a respond_to? and> The difference is: simply stating a class' purpose is easy. You do it once
> and that's pretty much it. As you develop, though, the interface changes.
> Keeping up with specific method documentation is much more labor-intensive.
> If you have an interface description that you had to adhere to, you wouldn't
> have the option of falling behind on updating it. Your code simply wouldn't
> work until you did.
arity check coupled with an assert. I'm not saying thats a better
way, just it gives you the same assurance (IMO) without
such a big change to the language.
> > But again, its less hassle to document your API than to do rigourous
> > argument checking.My main doubt about this is, unless I misunderstand it,> No, it's more hassle. To update a document, you have to open a different
> file, and if you make a typo or just plain write it wrong, there is nothing
> to stop you from doing so. Interfaces can be described in the same source
> file as your class definition, so it's easy to find and update, plus, you
> can't update it wrong, or your code gives you errors.
this only makes APIs easier to use if the author decides to
use interface declarations.
But the choice 'to doc or not to doc' is no different to
'to interface or not to' for a lazy sod (I speak as one myself).
Unless you enforce it across the language, which would get you
burnt at the stake, you've potentially forked the language and you may
not even see a benefit.
It seems to me that when working around lazy b*stards like
me, its easier to doc a third party library than to retrofit
interfaces onto it.
I agree, and I have found several promising APIs unusable because the>> > It seemed like you were more interested in a way to know how an API
> > will use your object. Why not send in a probe?
> Because probes can sometimes cause damage, and the errors reported deep inside
> may not be easily understood. It's a hit-or-miss proposition in there; some
> people have no trouble diving in and reading someone else's code. I do it as
> a last resort because I find it's a terribly inefficient way to debug.
documentation was non-existent. My point was there are ways and means in
Ruby that the typed languages dont have, that feel more Rubyish than
a bolt-on feature.
In this case (investigating an alien object) we can verify an
object passed as an argument( respond_to? and arity checks) has methods
we expect, and callers of our methods can also see how methods they pass in
are being used by us (by use of a probe object).
I dont think an interface check can do any more. Admittedly someone has
written 'this object is for Xing' on it, but 99% of the time knowing there
is a method doX(objectA,objectB) does that job. There are edge cases
(using RMI systems, etc) but personally I'd prefer to dissect the remote
object rather than trust a flag on it if I didnt trust the source - and if
I knew where it came from, I'd rather unit test it.
I've started talking personal prefs, so I'll stop posting after this -
thats my 2p, anyway.
But thats no different from probing the objects you are passed as arguments.> Well, since classes can implement interfaces, the test can also check that
> methods are being passed object that fulfill the interface contract. So, a
> sort of type checking can be performed.
Incihentally, my opposition to this isnt 'not invented here', its simply> > I think I share some of both sides viewpoint, but I dont want a
> > Java'ed Ruby, and it seems that this interface idea is coming from
> > that angle.
that interfaces in Java *increase* flexibility, whereas in Ruby they
seem to be a restriction.
--
Truth is the most valuable thing we have -- so let us economize it.
-- Mark Twain
Rasputin :: Jack of All Trades - Master of Nuns
Rasputin Guest



Reply With Quote

