[squeak-dev] The Inbox: Kernel-fn.1151.mcz
Levente Uzonyi
leves at caesar.elte.hu
Wed Mar 21 21:48:47 UTC 2018
On Tue, 20 Mar 2018, Chris Cunningham wrote:
> 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 at gmx.de> wrote:
>
> > On 10.02.2018, at 20:36, Tony Garnock-Jones <tonyg at 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.
Here is a simpler and faster alternative:
True >> #xor: aBoolean
aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]
False >> #xor: aBoolean
aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]
Levente
>
> 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
>
>
More information about the Squeak-dev
mailing list
|