From: Nokan Emiro Date: 2013-01-27T02:12:31+09:00 Subject: Re: limitations --e89a8fb1ffc412a81804d43426ae Content-Type: text/plain; charset=UTF-8 Hi Robert, Why do you think you need to redefine behavior of these operators? > Because I'm working on a type that behaves like any other Ruby class (in terms that it accepts all operations and messages that a Numeric, an Array, a Hash or anything else), but it collects all it's history into a huge Ruby expression for further evaluation. It works charmingly with the normal ops like :+, :-, :*, :/, :[], :<< etc., but, of course, it fails with those outside of an object's own world. irb(main):001:0> x = Accumulator.new :x => <<< x >>> irb(main):002:0> y = x + 123 => <<< x + 123 >>> irb(main):003:0> z = 2 * y => <<< 2 * (x + 123) >>> irb(main):004:0> q = 1 - z ** 2 => <<< 1 - (2 * (x + 123)) ** 2 >>> irb(main):005:0> q+z+y => <<< 1 - (2 * (x + 123)) ** 2 + 2 * (x + 123) + x + 123 >>> irb(main):006:0> It may be useful to drop in "spy objects" (like the x above) into black box functions, like crypto functions, hash calculations, numerical approximations, or even well-known calculations, just to wrap them up in a huge expression instead of looking at them as the code of a long method, or just look for algebric simplifications on the result. It can help improving the original calculation or finding out more about the method's internals. There are two huge limitations of this. One is that if the function makes decision based on the value of the input, this will fail. For instance, the expression x > 0 does not have a boolean value, but the expression <<< x > 0 >>> itself, which is an Accumulator object, and has a logical value of true in conditional expressions, since it's not nil nor false. The second limitation is that methods can contain lines like x = y && z, or with other words I have no control over them and they can use &&, ||, and, or, and not in calculations that I can incorporate into the object's internal expression describing it's calculation history. The solution for the first one could be to break the calculation and ask the user what to answer for a relation like x > 0, or the Accumulator could do a parallel calculation with normal values (Numerics, Arrays, etc) just to return acceptable values for the tested function. That's the easier part. But it seems that it's impossible to grab "operations" like &&... :( irb(main):001:0> x = Accumulator.new :x => <<< x >>> irb(main):002:0> y = x && 123 => 123 irb(main):003:0> y => 123 <<<--------- this should be <<< x && 123 >>> somehow... irb(main):004:0> x => <<< x >>> irb(main):005:0> def fib(n) irb(main):006:1> n < 2 ? 1 : fib(n - 2) + fib(n - 1) irb(main):007:1> end => nil irb(main):008:0> (0..6).each { |i| p fib i } 1 1 2 3 5 8 13 => 0..6 irb(main):009:0> fib x => 1 <<<<--------------- Well, this is because x < 2 is <<< x < 2 >>>, which is true (at least not false or nil), so the ?: in fib() returns 1 :( irb(main):010:0> x < 2 => <<< x < 2 >>> irb(main):011:0> --e89a8fb1ffc412a81804d43426ae Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Hi Robert,

Why do you think you need to redefine behavior of=C2=A0these operato= rs?

Because I'm working on a type that behaves like any= other Ruby class (in
terms that it accepts all operations and me= ssages that a Numeric, an Array,
a Hash or anything else), but it= collects all it's history into a huge=C2=A0Ruby
expression for further evaluation. =C2=A0It works charmingly with the = normal
ops like :+, :-, :*, :/, :[], :<< etc., but, of cour= se, it fails with those outside
of=C2=A0an object's own world= .

irb(main):001:0> x =3D Accumulator.new :x
=
=3D> <<< =C2=A0x =C2=A0>>>
irb(main):00= 2:0> y =3D x + 123
=3D> <<< =C2=A0x + 123 =C2=A0&g= t;>>
irb(main):003:0> z =3D 2 * y
=3D> <<< =C2=A02 * (x + 123) =C2=A0>>>
= irb(main):004:0> q =3D 1 - z ** 2
=3D> <<< =C2=A01= - (2 * (x + 123)) ** 2 =C2=A0>>>
irb(main):005:0> q+= z+y
=3D> <<< =C2=A01 - (2 * (x + 123)) ** 2 + 2 * (x = + 123) + x + 123 =C2=A0>>>
irb(main):006:0>

It may be useful to= drop in "spy objects" (like the x above) into black box function= s,
like=C2=A0crypto functions, hash calculations, numerical appro= ximations, or even well-known
calculations, just to wrap them up in a huge expression instead of loo= king at them as
the code of a=C2=A0long method, or just look for = algebric simplifications on the result. =C2=A0It can
help=C2=A0im= proving the original calculation or finding out more about the method's= internals.

There are two huge limitations of this. One is that if = the function makes decision
based on the value of the input, this= will fail. =C2=A0For instance, the expression x > 0
does not = have a boolean value, but the expression <<< =C2=A0x > 0 =C2=A0= >>> itself, which
is an Accumulator object, and has a logical value of true in condition= al expressions,
since it's not nil nor false. =C2=A0The secon= d limitation is that methods can contain
lines like x =3D y &= & z, or with other words I have no control over them and they
can use &&, ||, and, or, and not in calculations that I can in= corporate into the
object's internal expression describing it= 's calculation history. =C2=A0The solution for
the first one = could be to break the calculation and ask the user what to answer
for a relation like x > 0, or the Accumulator could do a parallel c= alculation with
normal values (Numerics, Arrays, etc) just to ret= urn acceptable values for the
tested function. That's the eas= ier part. =C2=A0But it seems that it's impossible to grab
"operations" like &&... :(

=
irb(main):001:0> x =3D Accumulator.new :x
=3D> <<= ;< =C2=A0x =C2=A0>>>
irb(main):002:0> y =3D x &= ;& 123
=3D> 123
irb(main):003:0> y
=3D> 123 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <<<--------- =C2=A0this should be = =C2=A0<<< =C2=A0x && 123 =C2=A0>>> somehow...
irb(main):004:0> x
=3D> <<< =C2=A0x =C2=A0&= gt;>>
irb(main):005:0> def fib(n)
irb(main):006:1> =C2=A0 n = < 2 ? 1 : fib(n - 2) + fib(n - 1)
irb(main):007:1> end
=3D> nil
irb(main):008:0> (0..6).each { |i| p fib i }=
1
1
2
3
5
8
13
=3D> 0..6
irb(main):009:0> fib x
= =3D> 1 =C2=A0 =C2=A0<<<<--------------- =C2=A0Well, this is = because x < 2 is <<< =C2=A0x < 2 =C2=A0>>>, which i= s true (at least not false or nil), so the ?: in fib() returns 1 =C2=A0:(
irb(main):010:0>=C2=A0x < 2
=3D> <<< =C2= =A0x < 2 =C2=A0>>>
irb(main):011:0>=C2=A0


--e89a8fb1ffc412a81804d43426ae--