From: "Sean E. Russell" Date: 2005-11-26T00:19:29+09:00 Subject: Ruby pipes --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--