<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 21, 2018 at 2:48 PM, Levente Uzonyi <span dir="ltr"><<a href="mailto:leves@caesar.elte.hu" target="_blank">leves@caesar.elte.hu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div class="gmail-HOEnZb"><div class="gmail-h5">On Tue, 20 Mar 2018, Chris Cunningham wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
Hi.  Reopening this thread - probably tomorrow will implement 'better' solution (with documentation).<br>
<br>
On Sat, Feb 10, 2018 at 12:03 PM, Tobias Pape <<a href="mailto:Das.Linux@gmx.de" target="_blank">Das.Linux@gmx.de</a>> wrote:<br>
<br>
      > On 10.02.2018, at 20:36, Tony Garnock-Jones <<a href="mailto:tonyg@leastfixedpoint.com" target="_blank">tonyg@leastfixedpoint.com</a>> wrote:<br>
      ><br>
      > On 02/10/2018 07:02 PM, Levente Uzonyi wrote:<br>
      >> So,<br>
      >>    a perform: {#or:. #xor:. #and:} atRandom with: b<br>
      >> would just work for that imaginary interpreter if b were a Boolean.<br>
      ><br>
      > Yes, that "interpreter" works just fine today, if b is a Boolean. It's<br>
      > the case where b is a Boolean-producing expression - such as in a "lazy"<br>
      > interpreter - that doesn't work without Fabio's proposed change.<br>
      ><br>
      > I went and looked at the ANSI standard (draft), btw [1].<br>
      ><br>
      > There, #xor: is specified as taking only a boolean.<br>
      ><br>
      > So this would be an extension, potentially affecting portability, for<br>
      > what that's worth these days.<br>
      ><br>
      > I think the performance objection has been well-refuted, and I see the<br>
      > consistency benefit as being real, but probably pretty limited, and I<br>
      > kind of don't like the potential portability implications.<br>
<br>
      I presume the main "feeling" here is parallelity:<br>
<br>
      #& takes an evaluated boolean   #and: takes an unevaluated block<br>
      #| takes an evaluated boolean   #or: takes an unevaluated block<br>
<br>
      #xor: takes an evaluated boolean but looks like #and: and #or:,<br>
      So it seems to belong to the right side, and then we think again about<br>
      the left side, come up with symbols, only to find that #~= and #~~ are already there.<br>
<br>
      So, just lets go all the way and document #xor: better, not making take it a block,<br>
      maybe pointing out that #~= ist typically better fitted…<br>
<br>
      Best regards<br>
              -Tobias<br>
<br>
<br>
So, I have written some tests for speed and 'ensuring the arguments are booleans', with another proposed solution.<br>
<br>
First, speed:<br>
<br>
#xor: base<br>
#~= is 124% slower (or 2-1/4 as much time as existing xor: method)<br>
#~~ is 75% faster<br>
#cbcXor: is 32% slower<br>
<br>
Note: for real speed, use ~~ , not ~= !<br>
<br>
Why cbcXor: ?  It is the only one that makes sure the arguments are boolean - fails otherwise.<br>
</blockquote>
<br></div></div>
Here is a simpler and faster alternative:<br>
<br>
True >> #xor: aBoolean<br>
<br>
        aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]<br>
<br>
False >> #xor: aBoolean<br>
<br>
        aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]</blockquote><div><br></div><div>and is this noticeably slower?</div><div><br></div><div> <span style="color:rgb(0,0,0);font-size:12.800000190734863px">True >> #xor: aBoolean</span></div><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><span style="color:rgb(0,0,0);font-size:12.800000190734863px">        ^aBoolean ifTrue: [ false ] ifFalse: [ true ]</span><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><span style="color:rgb(0,0,0);font-size:12.800000190734863px">False >> #xor: aBoolean</span><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><span style="color:rgb(0,0,0);font-size:12.800000190734863px">        ^aBoolean ifTrue: [ true ] ifFalse: [ false ]</span></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px"><br></span></font></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px">but I would much prefer to see either</span></font></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px"><br></span></font></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px">Boolean>>xor: aBooleanOrBlock</span></font></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px"><br></span></font></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px">    ^</span></font><span style="color:rgb(0,0,0);font-size:12.800000190734863px"> aBooleanOrBlock value not</span></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px"><br></span></font></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px">or</span></font></div><div class="gmail_quote"><font color="#000000"><span style="font-size:12.800000190734863px"><br></span></font></div><div class="gmail_quote"><div class="gmail_quote"><div><span style="color:rgb(0,0,0);font-size:12.800000190734863px">True >> #xor: </span><span style="color:rgb(0,0,0);font-size:12.800000190734863px">aBooleanOrBlock</span></div><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><span style="color:rgb(0,0,0);font-size:12.800000190734863px">        ^</span><span style="color:rgb(0,0,0);font-size:12.800000190734863px">aBooleanOrBlock value</span><span style="color:rgb(0,0,0);font-size:12.800000190734863px"> ifTrue: [ false ] ifFalse: [ true ]</span><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><span style="color:rgb(0,0,0);font-size:12.800000190734863px">False >> #xor: </span><span style="color:rgb(0,0,0);font-size:12.800000190734863px">aBooleanOrBlock</span><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><br style="color:rgb(0,0,0);font-size:12.800000190734863px"><span style="color:rgb(0,0,0);font-size:12.800000190734863px">        ^</span><span style="color:rgb(0,0,0);font-size:12.800000190734863px">aBooleanOrBlock value</span><span style="color:rgb(0,0,0);font-size:12.800000190734863px"> ifTrue: [ true ] ifFalse: [ false ]</span></div><div class="gmail_quote"><span style="color:rgb(0,0,0);font-size:12.800000190734863px"><br></span></div><div class="gmail_quote">The lack of symmetry with and: and or: is, IMO, bad.</div><div><span style="color:rgb(0,0,0);font-size:12.800000190734863px"><br></span></div><div><span style="color:rgb(0,0,0);font-size:12.800000190734863px"><br></span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span class="gmail-HOEnZb"><font color="#888888">Levente</font></span><div class="gmail-HOEnZb"><div class="gmail-h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
Tests to run:<br>
<br>
First, install<br>
<br>
True>>cbcXor: boolean<br>
^boolean isFalse<br>
True>>isTrue<br>
^true<br>
True>>isFalse<br>
^false<br>
False>>cbcXor: boolean<br>
^boolean isTrue<br>
False>>isFalse<br>
^true<br>
False>>isTrue<br>
^false<br>
<br>
"Setup"<br>
pairs := #( true false true true false false false true ).<br>
invalidPairs := { true. 1. true. #[ 1 3 0 9 ]. true. 'abc'. false. 1. false. #[ 1 3 0 9 ]. false. 'abc'. 'abc'. true. #[ 1 3 0 9 ]. false. }.<br>
methods := {<br>
[:f :s| ]. <br>
[:f :s| f xor: s]. <br>
[:f :s| f cbcXor: s]. <br>
[:f :s| f ~= s]. <br>
[:f :s| f ~~ s].<br>
}.<br>
"Validity Test"<br>
validCheck := methods collect: [:m|<br>
{ <br>
m sourceString. <br>
#( true false false true ) = (pairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]])<br>
ifTrue: ['Valid'] ifFalse: ['ERRORS'].<br>
pairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]]. <br>
}].<br>
"all methods are valid"<br>
"Testing that non-booleans actually result in errors, and not false positive/negatives"<br>
invalidCheck := methods collect: [:m|<br>
{ <br>
m sourceString. <br>
((invalidPairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]]) select: [:r| r = #error]) size = 8<br>
ifTrue: ['Valid'] ifFalse: ['ERRORS'].<br>
invalidPairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]]. <br>
}].<br>
"Only #cbcXor: correctly fails all of these.  Some interesting results..."<br>
"Timing test.  Need to run 10,000,000 to get reasonable distinctions on my machine."<br>
timing := methods collect: [:m|<br>
{ m sourceString.  [[10000000 timesRepeat: [pairs pairsDo: m]] timeToRun] on: Error do: [#invalid]. }<br>
].<br>
"And showing percentage slower"<br>
base := timing first second.<br>
bench := timing second second - base.<br>
timing allButFirst collect: [:res| { res first. this := res second - base. ((this - bench) * 100 / bench) rounded. }].<br>
<br>
Thanks,<br>
cbc<br>
<br>
</blockquote>
</div></div><br><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>