Hi.  Reopening this thread - probably tomorrow will implement 'better' solution (with documentation).

On Sat, Feb 10, 2018 at 12:03 PM, Tobias Pape <Das.Linux@gmx.de> wrote:

> On 10.02.2018, at 20:36, Tony Garnock-Jones <tonyg@leastfixedpoint.com> wrote:
>
> On 02/10/2018 07:02 PM, Levente Uzonyi wrote:
>> So,
>>    a perform: {#or:. #xor:. #and:} atRandom with: b
>> would just work for that imaginary interpreter if b were a Boolean.
>
> Yes, that "interpreter" works just fine today, if b is a Boolean. It's
> the case where b is a Boolean-producing expression - such as in a "lazy"
> interpreter - that doesn't work without Fabio's proposed change.
>
> I went and looked at the ANSI standard (draft), btw [1].
>
> There, #xor: is specified as taking only a boolean.
>
> So this would be an extension, potentially affecting portability, for
> what that's worth these days.
>
> I think the performance objection has been well-refuted, and I see the
> consistency benefit as being real, but probably pretty limited, and I
> kind of don't like the potential portability implications.

I presume the main "feeling" here is parallelity:

#& takes an evaluated boolean   #and: takes an unevaluated block
#| takes an evaluated boolean   #or: takes an unevaluated block

#xor: takes an evaluated boolean but looks like #and: and #or:,
So it seems to belong to the right side, and then we think again about
the left side, come up with symbols, only to find that #~= and #~~ are already there.

So, just lets go all the way and document #xor: better, not making take it a block,
maybe pointing out that #~= ist typically better fitted…

Best regards
        -Tobias


So, I have written some tests for speed and 'ensuring the arguments are booleans', with another proposed solution.

First, speed:

#xor: base
#~= is 124% slower (or 2-1/4 as much time as existing xor: method)
#~~ is 75% faster
#cbcXor: is 32% slower

Note: for real speed, use ~~ , not ~= !

Why cbcXor: ?  It is the only one that makes sure the arguments are boolean - fails otherwise.

Tests to run:

First, install

True>>cbcXor: boolean
^boolean isFalse
True>>isTrue
^true
True>>isFalse
^false
False>>cbcXor: boolean
^boolean isTrue
False>>isFalse
^true
False>>isTrue
^false

"Setup"
pairs := #( true false true true false false false true ).
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. }.
methods := {
[:f :s| ]. 
[:f :s| f xor: s]. 
[:f :s| f cbcXor: s]. 
[:f :s| f ~= s]. 
[:f :s| f ~~ s].
}.
"Validity Test"
validCheck := methods collect: [:m|
m sourceString. 
#( true false false true ) = (pairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]])
ifTrue: ['Valid'] ifFalse: ['ERRORS'].
pairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]]. 
}].
"all methods are valid"
"Testing that non-booleans actually result in errors, and not false positive/negatives"
invalidCheck := methods collect: [:m|
m sourceString. 
((invalidPairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]]) select: [:r| r = #error]) size = 8
ifTrue: ['Valid'] ifFalse: ['ERRORS'].
invalidPairs pairsCollect: [:a :b| [m value: a value: b] on: Error do: [#error]]. 
}].
"Only #cbcXor: correctly fails all of these.  Some interesting results..."
"Timing test.  Need to run 10,000,000 to get reasonable distinctions on my machine."
timing := methods collect: [:m|
{ m sourceString.  [[10000000 timesRepeat: [pairs pairsDo: m]] timeToRun] on: Error do: [#invalid]. }
].
"And showing percentage slower"
base := timing first second.
bench := timing second second - base.
timing allButFirst collect: [:res| { res first. this := res second - base. ((this - bench) * 100 / bench) rounded. }].

Thanks,
cbc