--nextPart6158620.BxYiCQ7NuP
Content-Type: text/plain;
  charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi,

I'm having a bit of a trouble with Ruby pipes and am looking for an efficie=
nt=20
solution to the problem.

Consider:

	a,b =3D IO.pipe

Both a and b are IO objects, and there is nothing (that I can tell) to=20
differentiate them from any other sort of IO object.  That is, there is no=
=20
way to tell that they are pipes.  This is a failure in the typing system.

Unfortunately, not all functions on IO objects are valid for all IO objects=
=2E =20
=46or instance:

	a.tell

which should return the current position in the stream, instead throws an=20
exception for pipes.  This is behavior that Ruby inherits from C's stdio, b=
ut=20
it is also a failure of the duck typing system: there exist methods that ar=
e=20
defined as failing for objects of a given type, yet those methods exist for=
=20
those objects.

So, if I have a method that accepts an IO object, it is insufficient to tes=
t=20
that the object is an IO instance to ensure that the methods are valid.  Th=
e=20
only way to ensure that the code works is to rescue potential errors:

	def foo( ob )
		begin
			ob.tell
		rescue Errno::ESPIPE
		end
	end

However, this is an order of magnitude slower, whether the method succeeds =
or=20
fails.  This is unacceptable, especially because we *know* which functions=
=20
will fail for which objects, and a kind_of? test is much, much faster.

In my current project, I *could* do the following, because of how I'm using=
=20
the mystery object:

	class Foo
		def initialize( ob )
			@ob =3D ob
			begin
				ob.tell
				@pipe =3D false
			rescue Errno::ESPIPE
				@pipe =3D true
			end
		end
		def foo
			@pipe ? 0 : @ob.tell
		end
	end

I don't know about the rest of you, but this is hackery to the extreme.  I =
get=20
a creepy, slimy feeling just looking at it.  And this only works because of=
=20
how I'm using the code; if I'm providing a function where the object is bei=
ng=20
passed in every time, I can't use this trick.

As I said before, Ruby inherits this problem from C, so it isn't something=
=20
that could be easily fixed in Ruby (I think).  Two ideal solutions would be:

	1) Pipes are a subclass of IO, and can be tested as such
	2) Pipes don't expose IO methods that are known to fail,
	    so respond_to? could be used to duck-type them.

(2) would break all sorts of class inheritance rules, and this situation is=
 a=20
good example of a fundamental flaw in mixing duck typing and OO -- but that=
's=20
a different thread.  In any case, neither solution is likely to happen, so =
my=20
question boils down to:

Is there no other way to solve this without either (a) incurring the huge=20
performance hit of relying on exception handling for branching, or (b)=20
resorting to an ugly hack?

=2D-=20
=2D-- SER

"As democracy is perfected, the office of president represents,=20
more and more closely, the inner soul of the people.  On some=20
great and glorious day the plain folks of the land will reach=20
their heart's desire at last and the White House will be adorned=20
by a downright moron."        -  H.L. Mencken (1880 - 1956)

--nextPart6158620.BxYiCQ7NuP
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2-ecc0.1.6 (GNU/Linux)

iD8DBQBDhynRP0KxygnleI8RAjIiAJoC6hE6NNW+SEkrDysl8D3szuS2sACgz1qZ
8OZu2FV3ZGhuk97rGNzeMf8=
=6Z1+
-----END PGP SIGNATURE-----

--nextPart6158620.BxYiCQ7NuP--