How to duck type? - the psychology of static typing in Ruby

In article slrncajk30.4g8.childNOSPAM@child.ha.pwr.wroc.pl,

[…]

I alway have to look up definitions…
Type system - Wikipedia

Unfortunately I’m not familiar with Objective C so I can’t judge on that.

I cannot say I know Objective C well too, but I get some basic concepts.

From what I’ve seen so far I’d assume it’s similar to Java which is regarded
as statically typed although you have access to type information at runtime
(as seems to be the case with Objective C). But the crucial part is that
you declare types (of variables, of method arguments) in code and these
types are checked by the compiler.

Yes and no. Objective C started off with ANSI C and added a
Smalltalk-like object model on top of it. The C portions are strongly
typed, but the object framework made use (initially) of a generic object
type called “id”, which in practice mapped to “Object*” in the
underlying C implementation of the runtime. (Objective-C was initially
a pre-processor which generated pure C and linked to the runtime
libraries.) Since Objective C uses a single inheritance model,
“Object*” could point to objects of any class because all classes were
rooted in “Object”.

But the feature I described in my previous post has no equivalent in
Java - I’ll try to explain it (I may be very wrong, so anyone knowing
Obj-C better please correct me):

In Obj-C, when you create a variable to hold a pointer to an object of
class Object, you have 2 choices:

Object *obj;
id obj;

the second pointer is “typeless”, because it can point to an object of
any class. I wonder if similar mechanism could be useful in Ruby.

This isn’t quite correct, “id” was initially just a pre-processor
mapping for “Object*”. Later NeXT added “NSObject” as an alternate root
class for the object hierarchy, and “id” came to mean “pointer to an
instance of any class regardless of root class”. They also added typed
object declarations, so that “Object*” or “NSObject*” (or “MyObject*”)
were more restrictive than “id” and could only point to their respective
classes + lineal descendents. I always felt that the strong typing was
added to placate immigrants from the C++ world.

Ruby does not do this (as does Lisp, although it seems there are some
optimization type hints). So without these declarations it’s difficult to
do type verification at compile time without code execution. To introduce
this wuold be a major change in the language and break lots of code. If you
would allow for typeless and typed method arguments at the same time, you
would increase interpreter complexity by orders of magnitude and code would
be a real mess. I don’t think, it’s a good idea.

I’ll try to explain my idea in more detail. I suggest that one could put
optional type information when declaring the variable, eg:

def some_method ( String str, second_param )

do |Array ar, smth, Fixnum int|

etc.

So basically, current typeless declaration would become something
similar to Obj-C’s id, and new typed one would be similar to Obj-C’s
Object*.

Note I don’t mean to change (dynamic) method dispatching here - I just
wish Ruby had some mechanism for type checking on variable assignment,
so I don’t get enigmatic error messages deep inside a library I use (but
I didn’t write). Of course such mechanism would not prevent some runtime
errors (given you can remove method from an object), but it would surely
be very useful (at least for me).

In other words, this feature would be equivalent of ‘strongtyping’
library, just with better syntax and compile-time checking (to avoid
runtime overhead).

Objective C took a different approach by creating “protocols” (which
were adopted by Java as “interfaces”). Protocols are groups of method
signature declarations, with no implementation. If a class implements a
protocol, then invoking any of the methods declared in the protocol for
instances of that class is guaranteed to be legal. However, there are
no guarantees about what will actually happen. The focus and checking
is entirely on the existence of behaviors, while leaving the
responsibility for the actual behavior (implementation) to each
individual class. In Ruby everything is an object, so the type
declaration and checking for method arguments and return values doesn’t
gain you anything. About all you could check would be the existence of
methods as a set, rather than checking them one at a time.

I worry more about the hazard of undeclared variable names. There’s a
story, probably apocryphal, about a space probe being lost back in the
1960’s because somebody held down a keypunch key too long and turned the
variable X into XX on the left-hand of an assignment. Since FORTRAN4
didn’t require explicit declaration of variables, the calculation was
stuffed into XX (which appeared nowhere else in the program) and X
contained an incorrect value for subsequent calculations. Because of
this story, I worry sometimes that variables need not be delcared in
Ruby. I realize that since everything is an object there’s no need for
type declarations. However, I think variable set declarations would
make some sense - “Here’s the set of variable names I’ll be using, and
anything not in this set is a typo.”

Disclaimer - I’m not a computer scientist, I’ve just been programming in
a bunch of languages for a long time. If I’ve said anything outrageous,
please be gentle.

···

Marek Janukowicz childNOSPAM@t17.ds.pwr.wroc.pl wrote:

On Tue, 18 May 2004 08:48:04 +0200, Robert Klemme wrote:

That’s a good question. And the answer, I guess, is no.

Gavin

···

On Wednesday, May 19, 2004, 12:11:53 AM, Aredridel wrote:

If I’m writing some sort of CRM library that I want to share with the
world and have reused, then I should obviously document my interface well,
and not be overly strict about what I accept. Even so, it’s very unlikely
that someone else is going to have a class they’re using that’s
similar-to-but-not-quite my OpenCRM::Customer class. The benefits of a
duck typing attitude are not likely to take root in this system. But I’m
creating a library that is aimed at reuse, so I should allow for reuse.

How about a delegator to your Customer class, with some extensions for
distributed computing?

That’s a very common one that can be gotten wrong: Will your type checks
work with a dRb proxied object?

Marek Janukowicz wrote:

Such a separation is rather obvious. The business logic is rather easy
to test, but in my experience most bugs occur on the UI side (especially
in the connection layer between UI and business logic). How do you test
UI?

UI is often hard, especially GUI.

But I ran into an idea the other day that I was unfamiliar with.

‘Expect’ is sometimes used to wrap a GUI around a text interface –
spawn the process and interact with it.

Of course, that in itself is non-trivial perhaps.

But a text interface is easier to test, especially with Expect.

Hal

Hal Fulton wrote:

James Britt wrote:

Sean Russell wrote:

I keep thinking that if I push the idea too hard, I’ll be tarred and
feathered.

Then your goose would be cooked

But may be the idea will take flight, if people don’t think it too fowl.

If you typed that, you’d better duck.

We’ll put it on your bill.

I can’t resist pecking out just one more bird pun for this thread. After
all, one good tern deserves another.

I’m careful to separate the application and business object code from
the UI side, making it easier to test.

Such a separation is rather obvious.

Sorry

The business logic is rather easy
to test, but in my experience most bugs occur on the UI side
(especially
in the connection layer between UI and business logic). How do you test
UI?

I don’t unit test it. To be honest, I’ve never found it worth while. I
spend far more time maintaining the tests than the time I save because
they exist.

And in all this, tested or not, I very, very rarely see the wrong type
of object being used. Given that this is a thread object static typing,
that seems relevant… :slight_smile:

I also use a lot of meta-programming, which cuts down on the amount of
stuff where testing is needed.

Could you elaborate some (maybe trivial) example? I know what
meta-programming is, but I don’t know how can it be employed in eg. web
application testing.

For example, all my business objects use database wrapped objects to do
the database access. All these are generated on the fly, and so I only
have to test one generator, rather than 50 individual classes.

Cheers

Dave

···

On May 19, 2004, at 15:58, Marek Janukowicz wrote:

John Carter john.carter@tait.co.nz wrote in message news:Pine.LNX.4.58.0405211016130.28513@parore.tait.co.nz

I immediately see two problems with implementation though…

a) Ruby is too dynamic, the value it is called with may well gain the
method between compilation and execution of that line. A case in
point is the ‘cgi’ module which won’t just break under your ruling, it will
shatter.

I’ll have to take a look at the internals of CGI, but I agree that
inferrence typing won’t catch everything, and will generate some false
warnings. I argue, however, that these cases are more the exception
than the rule, and that this makes inferrence typing in Ruby useful.

b) Ruby has a remarkbly “narrow” (local) view of the world as it
compiles, to implement your suggest it would require a more global
view, if not multiple passes. This “local” view is important, it
keeps Ruby simple and fast.

Which is why I keep saying, over, and over, and over, that I want
inferrence typing to be tied to the use of “-c”, not to the execution
of the code.

How is your postfix project coming along?

— SER

That was an interesting read!

“Paul Sanchez” pjs@alum.mit.edu schrieb im Newsbeitrag
news:pjs-CC200C.08190318052004@localhost…

In article slrncajk30.4g8.childNOSPAM@child.ha.pwr.wroc.pl,

[…]

I alway have to look up definitions…

Unfortunately I’m not familiar with Objective C so I can’t judge on
that.

I cannot say I know Objective C well too, but I get some basic concepts.

From what I’ve seen so far I’d assume it’s similar to Java which is
regarded
as statically typed although you have access to type information at
runtime
(as seems to be the case with Objective C). But the crucial part is
that
you declare types (of variables, of method arguments) in code and
these
types are checked by the compiler.

Yes and no. Objective C started off with ANSI C and added a
Smalltalk-like object model on top of it. The C portions are strongly
typed, but the object framework made use (initially) of a generic object
type called “id”, which in practice mapped to “Object*” in the
underlying C implementation of the runtime. (Objective-C was initially
a pre-processor which generated pure C and linked to the runtime
libraries.) Since Objective C uses a single inheritance model,
“Object*” could point to objects of any class because all classes were
rooted in “Object”.

So, if I understand this correctly, ObjC is quite similar to Java. Where
ObjC uses id Java uses a reference of type Object. The difference seems to
be that you can invoke arbitrary methods on an “id” reference whereas you
have to downcast in Java.

But the feature I described in my previous post has no equivalent in
Java - I’ll try to explain it (I may be very wrong, so anyone knowing
Obj-C better please correct me):

In Obj-C, when you create a variable to hold a pointer to an object of
class Object, you have 2 choices:

Object *obj;
id obj;

the second pointer is “typeless”, because it can point to an object of
any class. I wonder if similar mechanism could be useful in Ruby.

This isn’t quite correct, “id” was initially just a pre-processor
mapping for “Object*”. Later NeXT added “NSObject” as an alternate root
class for the object hierarchy, and “id” came to mean “pointer to an
instance of any class regardless of root class”. They also added typed
object declarations, so that “Object*” or “NSObject*” (or “MyObject*”)
were more restrictive than “id” and could only point to their respective
classes + lineal descendents.

Pretty much as it is in Java.

Objective C took a different approach by creating “protocols” (which
were adopted by Java as “interfaces”). Protocols are groups of method
signature declarations, with no implementation. If a class implements a
protocol, then invoking any of the methods declared in the protocol for
instances of that class is guaranteed to be legal.

This reminds me a bit of GNU C’s “signatures”. AFAIR you could declare a
signature as a collection of method signatures and assign any instance whose
class implements all methods contained in the signature. The class need not
be declared to implement this signature (as is the case with Java
interfaces). That could be used to retrofit signatures to existing library
code.

However, there are
no guarantees about what will actually happen. The focus and checking
is entirely on the existence of behaviors, while leaving the
responsibility for the actual behavior (implementation) to each
individual class.

Well, that’s always like this, isn’t it? Even Eiffel - which goes quite far
with regard to DBC - does not force any implementation. After all, there is
no way to do that actually.

In Ruby everything is an object, so the type
declaration and checking for method arguments and return values doesn’t
gain you anything. About all you could check would be the existence of
methods as a set, rather than checking them one at a time.

You couldn’t do that statically because the set of methods can change over
the lifetime of an instance. And if you mix typed and typeless code (excuse
the sloppy language) most checks will happen at runtime anyway. As said
earlier, I don’t see much use in adding “compile time” checks to Ruby. It
doesn’t fit.

I worry more about the hazard of undeclared variable names. There’s a
story, probably apocryphal, about a space probe being lost back in the
1960’s because somebody held down a keypunch key too long and turned the
variable X into XX on the left-hand of an assignment. Since FORTRAN4
didn’t require explicit declaration of variables, the calculation was
stuffed into XX (which appeared nowhere else in the program) and X
contained an incorrect value for subsequent calculations. Because of
this story, I worry sometimes that variables need not be delcared in
Ruby. I realize that since everything is an object there’s no need for
type declarations. However, I think variable set declarations would
make some sense - “Here’s the set of variable names I’ll be using, and
anything not in this set is a typo.”

If there were proper tests in place they’d certainly catched that one.
Declarations could only prevent the accidental usage of an undeclared
variable. But they can’t ensure calculcations and algorithms are done
properly.

Disclaimer - I’m not a computer scientist, I’ve just been programming in
a bunch of languages for a long time. If I’ve said anything outrageous,
please be gentle.

:slight_smile: It’s ok for me. I couldn’t find anything offensive here.

Kind regards

robert
···

Marek Janukowicz childNOSPAM@t17.ds.pwr.wroc.pl wrote:

On Tue, 18 May 2004 08:48:04 +0200, Robert Klemme wrote:

In other words, this feature would be equivalent of ‘strongtyping’
library, just with better syntax and compile-time checking (to avoid
runtime overhead).

But there’s a whole lot of problems waiting:

  • You need return type declarations (at least optional)

You’re right.

  • What do you do if you invoke a method with a required parameter type bu
    t your value resides in some typeless var?

Good point - that’s the question I didn’t reconsider.

  • You’ll likely and up casting values all the time => errors here can
    only be detected at runtime

You may be right here too :slight_smile:

  • Internal handling of references must be completele changed.

I do not (yet) think about consequences for Ruby interpreter.

  • What do you gain by type info if any instance is free to override
    methods defined in the class at will?

How often do your instances override methods defined in class? You’re
right - type info would not help in this case, but most programs do not
do this.

Although I can see the benefit for some users, I’m still not convinced
that this is a good idea, that it fits Ruby well and / or that this will
show up in Ruby in the near future.

I’m not convinced too - that why I am presenting my idea here. Thanks
very much for your thoughts - they gave me much broader view of the
whole problem.

···

On Tue, 18 May 2004 11:20:30 +0200, Robert Klemme wrote:


Marek Janukowicz

matz@ruby-lang.org (Yukihiro Matsumoto) wrote in message news:1084872320.683534.4537.nullmailer@picachu.netlab.jp

I buy the flexibility from dynamic typing at the cost of compile-time
type check. I don’t think I am going to change my mind.

I want to make sure we’re all on the same page.

My proposed solution is to have Ruby do a duck-typing check as part of
the syntax checker (“-c”). This would be duck-type inferrence, so it
doesn’t require the programmer to declare variables or give them
types. It would simply raise a warning if someone tries to call
“5.collect”. That is, ruby will load the parse tree as it does with
-c, and then check to make sure that method calls are consistant with
expected duck types. It would issue warnings where it can, but
remember – this is a debugging/development tool, not a runtime tool.
I don’t want Ruby doing this sort of type checking all the time.

I’d like to clarify that I’m in total agreement with Ben’s comments,
especially in

http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&threadm=64FDC9A2-A9C4-11D8-A38F-000A95676A62%40pragprog.com&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DUTF-8%26group%3Dcomp.lang.ruby
http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&threadm=64FDC9A2-A9C4-11D8-A38F-000A95676A62%40pragprog.com&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DUTF-8%26group%3Dcomp.lang.ruby

regarding the ability to catch classes of errors outside of running
code. “-c” catches one class: syntax errors. Another class of error
is type errors that can be caught with type inferrence. Another class
is variable typo warnings like Ben’s example.

— SER

Hal Fulton wrote:

UI is often hard, especially GUI.

But I ran into an idea the other day that I was unfamiliar with.

‘Expect’ is sometimes used to wrap a GUI around a text interface –
spawn the process and interact with it.

Of course, that in itself is non-trivial perhaps.

But a text interface is easier to test, especially with Expect.

I’ve been using Ruby at my current job to test a web app via Internet
Explorer with the clIEController [0].

The downside is it only scripts IE, and (to the best of my knowledge),
you cannot get to the raw markup returned to the scripted browser, so it
doesn’t help you verify, for example, that each page is rendered as you
expect.

I’ve hacked some code for the controller that walks the IE HTML node
tree and emits proper XML (not actual XHTML, though) so that one can run
xpath calls, via REXML, against the markup to see that certain data is
on the page, or check that a page fetch didn’t return an error page.

If nothing else, it saves much time clicking through pages, filling in
forms, clicking submit, etc. My test script will spawn a score of
threads; browsers pop up all over the place, and I test a dozen
pages/site paths at a time.

James

[0] http://www.clabs.org/wtr/index.cgi?page=/ClIEController

Robert Klemme wrote:

I worry more about the hazard of undeclared variable names. There’s a
story, probably apocryphal, about a space probe being lost back in the
1960’s because somebody held down a keypunch key too long and turned the
variable X into XX on the left-hand of an assignment. Since FORTRAN4
didn’t require explicit declaration of variables, the calculation was
stuffed into XX (which appeared nowhere else in the program) and X
contained an incorrect value for subsequent calculations. Because of
this story, I worry sometimes that variables need not be delcared in
Ruby. I realize that since everything is an object there’s no need for
type declarations. However, I think variable set declarations would
make some sense - “Here’s the set of variable names I’ll be using, and
anything not in this set is a typo.”

If there were proper tests in place they’d certainly catched that one.
Declarations could only prevent the accidental usage of an undeclared
variable. But they can’t ensure calculcations and algorithms are done
properly.

I have a beef with this attitude. Of course you’ll catch this error if
you have a test in place to test for it. Of course proper testing will
ensure a working product. Of course testing for undeclared variables
won’t prove you have a working program. That doesn’t mean it’s useless.
In fact, this is one of the most useful features of compilers in a
compiled language.

Matz has often said that one of his major goals with Ruby is to make
things easy for the programmer, unlike most languages that make things
easy for the computer.

Checking to see if you’re assigning to an undeclared variable is one of
those really helpful things that a computer can do for you. It can’t
easily prove the correctness of your algorithms, it can’t easily decide
if your code needs to be refactored. But catching this kind of typo is
something that it should be pretty good at. So, why is this a bad thing?

Sometimes, you don’t want the extra keystrokes of having to declare your
variables. That’s fine. But, sometimes you really want typo detection.

$num = 2
$num += 3

if ($numb != 5)
puts “foo”
end

If I run the above by default, it just prints “foo”. If I run it with
‘-v’ it tells me:

ritf.rb:7: warning: global variable `$numb’ not initialized

That’s some really useful information! It’s a shame that I get that
information too late. At this point my program is already running and
already doing the wrong thing.

I think it would be great if there were some analysis software for ruby
code that would look over it, and without actually running it, find
potential problems like this one. This would be the equivalent of
compiling a C program, in that it would weed out all the obvious typos
and similar mistakes. This could even be the behaviour of ‘ruby -c’ if
the ‘-v’ flag is supplied.

Among people who don’t program Ruby, one of the biggest complaints I’ve
heard is that they’d be scared to create a really big program in Ruby
because it wouldn’t find a simple typo until it is actually executing
the code at that point. If it’s a rarely-hit spot, then it could be a
long time before it is discovered. This concerns me too – but I’m a
big enough fan that I overlook this flaw and use Ruby anyhow.

One of the few things that Perl still has that Ruby doesn’t is this:

use strict;

$num = 3;
$num += 2;
if ($numb != 5) {
print “Foo!!\n”;
}
% perl perl.pl
Global symbol “$num” requires explicit package name at perl.pl line 3.
Global symbol “$num” requires explicit package name at perl.pl line 4.
Global symbol “$numb” requires explicit package name at perl.pl line 5.
Execution of perl.pl aborted due to compilation errors.

It’s an option. You don’t have to use it, but for critical packages,
most people do. Sure, it’s nothing more than partial typo detection,
but is any of us really prefekt?

And besides, if you think proper unit tests will catch all your errors,
so you don’t need this type of check – what if the typo is in your
unit test?

Ben

Sean Russell wrote:

My proposed solution is to have Ruby do a duck-typing check as part of
the syntax checker (“-c”). This would be duck-type inferrence, so it
doesn’t require the programmer to declare variables or give them
types. It would simply raise a warning if someone tries to call
“5.collect”.

Well, here’s one comment.

if foo()
def 5.collect
puts “I exist!”
end
end

Of course, Fixnums can’t have singleton methods now. Later, I think they
may.

The point is, methods may be added/deleted/redefined at runtime. This
makes static checking very difficult in the general case.

Hal

Hi –

matz@ruby-lang.org (Yukihiro Matsumoto) wrote in message news:1084872320.683534.4537.nullmailer@picachu.netlab.jp

I buy the flexibility from dynamic typing at the cost of compile-time
type check. I don’t think I am going to change my mind.

I want to make sure we’re all on the same page.

My proposed solution is to have Ruby do a duck-typing check as part of
the syntax checker (“-c”). This would be duck-type inferrence, so it
doesn’t require the programmer to declare variables or give them
types. It would simply raise a warning if someone tries to call
“5.collect”. That is, ruby will load the parse tree as it does with
-c, and then check to make sure that method calls are consistant with
expected duck types.

I think “expected duck types” may be a contradiction in terms :slight_smile:
Actually there’s no reason not just to say: consistent with expected
types, since “duck type” is essentially a description of how Ruby
objects’ types work. In other words, the question of whether or not a
given object responds to a given message is (already, without ‘duck’)
a question about its type.

David

···

On Thu, 20 May 2004, Sean Russell wrote:


David A. Black
dblack@wobblini.net

James - can you make this additional code available?

Also, when you spawn multiple browsers, did you investigate which
process they are in. When I have tried this they all live in the same
process, and therefore share cookies, so cant be used for testing site
that use cookies.

Thanks

Paul

···

I’ve hacked some code for the controller that walks the IE HTML node
tree and emits proper XML (not actual XHTML, though) so that one can run
xpath calls, via REXML, against the markup to see that certain data is
on the page, or check that a page fetch didn’t return an error page.

If nothing else, it saves much time clicking through pages, filling in
forms, clicking submit, etc. My test script will spawn a score of
threads; browsers pop up all over the place, and I test a dozen
pages/site paths at a time.

James

[0] http://www.clabs.org/wtr/index.cgi?page=/ClIEController

Rails[1] provide access to the rendered template without going
through a browser, which can then be queried through XPath (if the
template uses XHTML). It can also provide access to the attributes
assigned to make the template. And even to check which template was
used.

This is done by using mock requests and responses and works extremely
well. It’s considerably faster than going through HTTP for every
request (which is often what slows down functional/acceptance testing
and make them run for hours). It also gives you the opportunity to set
and check conditions through code that might have been incovenient to
generate through regular interfacing. Basically mocking.

So you have the opportunity to either XPath query the final XHTML or
examine the variables that the template is supposed to be generated
from. The latter is often a lot easier and catches most errors (by
basically just testing controller and model) that computers are good at
(comparing objects) and leaves the stuff that computers are less good
at it human testing (does this look right?).

[1] Rails is that web-application framework that I’ve been talking
about for far too long without sharing much code yet :wink:

···


David Heinemeier Hansson,
http://www.instiki.org/ – A No-Step-Three Wiki in Ruby
http://www.basecamphq.com/ – Web-based Project Management
http://www.loudthinking.com/ – Broadcasting Brain
http://www.nextangle.com/ – Development & Consulting Services

James Britt jamesUNDERBARb@neurogami.com wrote in message news:40AC08AD.5020801@neurogami.com

Hal Fulton wrote:

UI is often hard, especially GUI.

But I ran into an idea the other day that I was unfamiliar with.

‘Expect’ is sometimes used to wrap a GUI around a text interface –
spawn the process and interact with it.

Of course, that in itself is non-trivial perhaps.

But a text interface is easier to test, especially with Expect.

I’ve been using Ruby at my current job to test a web app via Internet
Explorer with the clIEController [0].

The downside is it only scripts IE, and (to the best of my knowledge),
you cannot get to the raw markup returned to the scripted browser, so it
doesn’t help you verify, for example, that each page is rendered as you
expect.

I’ve hacked some code for the controller that walks the IE HTML node
tree and emits proper XML (not actual XHTML, though) so that one can run
xpath calls, via REXML, against the markup to see that certain data is
on the page, or check that a page fetch didn’t return an error page.

If nothing else, it saves much time clicking through pages, filling in
forms, clicking submit, etc. My test script will spawn a score of
threads; browsers pop up all over the place, and I test a dozen
pages/site paths at a time.

James

[0] http://www.clabs.org/wtr/index.cgi?page=/ClIEController

Dunno if it’s relavent, but perhaps a port of Perl’s WWW::Mechanize
module is in order.

Regards,

Dan

I’ve been using Ruby at my current job to test a web app via Internet
Explorer with the clIEController [0].

The downside is it only scripts IE, and (to the best of my knowledge),
you cannot get to the raw markup returned to the scripted browser, so it
doesn’t help you verify, for example, that each page is rendered as you
expect.

You should be able to fetch it with something like:

document.root.outerHTML

···

James Britt (jamesUNDERBARb@neurogami.com) wrote:

I’ve hacked some code for the controller that walks the IE HTML node
tree and emits proper XML (not actual XHTML, though) so that one can run
xpath calls, via REXML, against the markup to see that certain data is
on the page, or check that a page fetch didn’t return an error page.

If nothing else, it saves much time clicking through pages, filling in
forms, clicking submit, etc. My test script will spawn a score of
threads; browsers pop up all over the place, and I test a dozen
pages/site paths at a time.


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

A better example is that perl does exactly what you were asking for
otherwise (behavior when -c and -v are both supplied to the ruby
interpreter):

jenova ~ % cat -n what.pl
1 $num = 3;
2 $num += 2;
3 if ($numb != 5) {
4 print “Foo!!\n”;
5 }
jenova ~ % perl -cw what.pl
Name “main::numb” used only once: possible typo at what.pl line 3.
what.pl syntax OK
jenova ~ %

-c catches compile issues, and -w adds in warning text.

···

On Thu, 20 May 2004 00:59:22 +0900 Ben Giddings bg-rubytalk@infofiend.com wrote:

One of the few things that Perl still has that Ruby doesn’t is this:

use strict;

$num = 3;
$num += 2;
if ($numb != 5) {
print “Foo!!\n”;
}
% perl perl.pl
Global symbol “$num” requires explicit package name at perl.pl line 3.
Global symbol “$num” requires explicit package name at perl.pl line 4.
Global symbol “$numb” requires explicit package name at perl.pl line
5. Execution of perl.pl aborted due to compilation errors.

Ben Giddings wrote:

Among people who don’t program Ruby, one of the biggest complaints I’ve
heard is that they’d be scared to create a really big program in Ruby
because it wouldn’t find a simple typo until it is actually executing
the code at that point. If it’s a rarely-hit spot, then it could be a
long time before it is discovered. This concerns me too – but I’m a
big enough fan that I overlook this flaw and use Ruby anyhow.

A code coverage tool (combined with unit tests) can help this. There’s
one in RAA.

Hal

I’d say, from an ‘optimistic’ perspective that this falls in what sean
sees as ‘catch something is better than nothing’.

Note that this is a bug:

def foo(x)
if x
def 5.collect

end
end
bar(5)
end

def bar(x)
x.collect
end

what happens if we do foo(false)?
NoSuchMethodError in bar.

FWIW, I would be happy to see something like rubylint/checker module,
not necessarily in the interpreter itself. I’d like:
ruby -rubylint program.rb

At least it should be possible to reach the same results similar tools
can reach.

···

il Thu, 20 May 2004 07:33:31 +0900, Hal Fulton hal9000@hypermetrics.com ha scritto::

Well, here’s one comment.

if foo()
def 5.collect
puts “I exist!”
end
end

Of course, Fixnums can’t have singleton methods now. Later, I think they
may.

The point is, methods may be added/deleted/redefined at runtime. This
makes static checking very difficult in the general case.