A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') ----- + xor: alternativeBlock - xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
+ ^alternativeBlock value! - ^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') ----- + xor: alternativeBlock - xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009" + ^alternativeBlock value not! - ^aBoolean not!
commits-2 wrote
A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
- ^alternativeBlock value!
- ^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
- ^alternativeBlock value not!
- ^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet, would it do any harm if we would allow "a xor: [b]"?
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote
A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
- ^alternativeBlock value!
- ^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
- ^alternativeBlock value not!
- ^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet, would it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will always be evaluated right after its creation. If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
#xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects (sometimes).
I'm just curious - is there an equivalent symbol for xor similar to | and & that we could use?
Also, before making this change to using blocks (if we do), we'd need to fix all users - probably also in the VMMaker packages.
-cbc
On Fri, Feb 9, 2018 at 9:18 AM, Levente Uzonyi leves@caesar.elte.hu wrote:
On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote
A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value!
^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value not!
^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet, would it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will always be evaluated right after its creation. If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
I understand that it can be but troubling to use a block with or: and: but not xor: Still I'm not fond of this change...
And indeed, we have the same laxist behavior for & and |. See https://stackoverflow.com/questions/47424242/understanding-weird-logical-ope...
Didn't Eliot suggest something like:
Boolean>>xor: aBoolean ^self == aBoolean not
This way we don't accept aBlock but fail instantly at runtime because messageNotUnderstood: #not... Performance-wise, we still send a message (hopefully inlined soon with sista).
Or maybe
True>>xor: aBoolean ^aBoolean ifTrue: [false] ifFalse: [self]
But before changing anything, consider that the right way to handle such case might better be to integrate QualityAssistant in the browser like in Pharo See https://github.com/Uko/QualityAssistant
2018-02-09 18:31 GMT+01:00 Chris Cunningham cunningham.cb@gmail.com:
#xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects (sometimes).
I'm just curious - is there an equivalent symbol for xor similar to | and & that we could use?
Also, before making this change to using blocks (if we do), we'd need to fix all users - probably also in the VMMaker packages.
-cbc
On Fri, Feb 9, 2018 at 9:18 AM, Levente Uzonyi leves@caesar.elte.hu wrote:
On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote
A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value!
^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value not!
^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet, would it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will always be evaluated right after its creation. If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On Fri, Feb 9, 2018 at 6:31 PM Chris Cunningham cunningham.cb@gmail.com wrote:
#xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects (sometimes).
I'm just curious - is there an equivalent symbol for xor similar to | and & that we could use?
In some languages, they use ^ but for obvious reason that's not useful. I wonder if we could use ~ for #xor:?
Also, before making this change to using blocks (if we do), we'd need to fix all users - probably also in the VMMaker packages.
Right...fortunately, there aren't that many senders...
Fabio
-cbc
On Fri, Feb 9, 2018 at 9:18 AM, Levente Uzonyi leves@caesar.elte.hu wrote:
On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote
A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value!
^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value not!
^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet, would it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will always be evaluated right after its creation. If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On 09.02.2018, at 19:06, Fabio Niephaus lists@fniephaus.com wrote:
On Fri, Feb 9, 2018 at 6:31 PM Chris Cunningham cunningham.cb@gmail.com wrote: #xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects (sometimes).
I'm just curious - is there an equivalent symbol for xor similar to | and & that we could use?
In some languages, they use ^ but for obvious reason that's not useful. I wonder if we could use ~ for #xor:?
Wikipedia says:
"It is symbolized by the prefix operator J[2] and by the infix operators XOR (/ˌɛks ˈɔːr/), EOR, EXOR, ⊻, ⩒, ⩛, ⊕, ↮, and ≢. "
Theoretically, we could use any of these symbols, (⊕ is often used in maths) but our fonts don't display them yet, so that has to wait.
Further there:
"+, a plus sign", well, would work (on booleans) but could be confusing "J, as in Jpq", not working for us
", sometimes written as • >< • >-<" THAT could work.
I like
a >< b
it looks like an X a bit.
Best regards -Tobias
PS: GMail/Inbox apparently destroys the citation level :(
Also, before making this change to using blocks (if we do), we'd need to fix all users - probably also in the VMMaker packages.
Right...fortunately, there aren't that many senders...
Fabio
-cbc
On Fri, Feb 9, 2018 at 9:18 AM, Levente Uzonyi leves@caesar.elte.hu wrote: On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value!
^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value not!
^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet, would it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will always be evaluated right after its creation. If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
2018-02-09 19:35 GMT+01:00 Tobias Pape Das.Linux@gmx.de:
On 09.02.2018, at 19:06, Fabio Niephaus lists@fniephaus.com wrote:
On Fri, Feb 9, 2018 at 6:31 PM Chris Cunningham cunningham.cb@gmail.com
wrote:
#xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument
block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects
(sometimes).
I'm just curious - is there an equivalent symbol for xor similar to |
and & that we could use?
In some languages, they use ^ but for obvious reason that's not useful.
I wonder if we could use ~ for #xor:?
Wikipedia says:
"It is symbolized by the prefix operator J[2] and by the infix operators XOR (/ˌɛks ˈɔːr/), EOR, EXOR, ⊻, ⩒, ⩛, ⊕, ↮, and ≢. "
Theoretically, we could use any of these symbols, (⊕ is often used in maths) but our fonts don't display them yet, so that has to wait.
Further there:
"+, a plus sign", well, would work (on booleans) but could be
confusing "J, as in Jpq", not working for us
", sometimes written as • >< • >-<" THAT could work.
I like
a >< b
it looks like an X a bit.
Best regards -Tobias
Nice.
We could also note or as union a/b, and as intersection a/\b but it's too late to change this. Anyway, given the number of senders of xor:, I'm not convinced that we need a binary message. We also have a pair of binary messages that already works: ~= or even ~~
PS: GMail/Inbox apparently destroys the citation level :(
Also, before making this change to using blocks (if we do), we'd need to
fix all users - probably also in the VMMaker packages.
Right...fortunately, there aren't that many senders...
Fabio
-cbc
On Fri, Feb 9, 2018 at 9:18 AM, Levente Uzonyi leves@caesar.elte.hu
wrote:
On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value!
^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value not!
^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet,
would
it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will
always be evaluated right after its creation.
If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On 09.02.2018, at 19:47, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
2018-02-09 19:35 GMT+01:00 Tobias Pape Das.Linux@gmx.de:
On 09.02.2018, at 19:06, Fabio Niephaus lists@fniephaus.com wrote:
On Fri, Feb 9, 2018 at 6:31 PM Chris Cunningham cunningham.cb@gmail.com wrote: #xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects (sometimes).
I'm just curious - is there an equivalent symbol for xor similar to | and & that we could use?
In some languages, they use ^ but for obvious reason that's not useful. I wonder if we could use ~ for #xor:?
Wikipedia says:
"It is symbolized by the prefix operator J[2] and by the infix operators XOR (/ˌɛks ˈɔːr/), EOR, EXOR, ⊻, ⩒, ⩛, ⊕, ↮, and ≢. "
Theoretically, we could use any of these symbols, (⊕ is often used in maths) but our fonts don't display them yet, so that has to wait.
Further there:
"+, a plus sign", well, would work (on booleans) but could be confusing "J, as in Jpq", not working for us ", sometimes written as • >< • >-<" THAT could work.
I like
a >< b
it looks like an X a bit.
Best regards -Tobias
Nice. We could also note or as union a/b, and as intersection a/\b but it's too late to change this. Anyway, given the number of senders of xor:, I'm not convinced that we need a binary message. We also have a pair of binary messages that already works: ~= or even ~~
True. We often forget this simplicity…
PS: GMail/Inbox apparently destroys the citation level :(
Also, before making this change to using blocks (if we do), we'd need to fix all users - probably also in the VMMaker packages.
Right...fortunately, there aren't that many senders...
Fabio
-cbc
On Fri, Feb 9, 2018 at 9:18 AM, Levente Uzonyi leves@caesar.elte.hu wrote: On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value!
^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value not!
^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet, would it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will always be evaluated right after its creation. If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On 02/09/2018 06:47 PM, Nicolas Cellier wrote:
We also have a pair of binary messages that already works: ~= or even ~~
This is actually an excellent point.
Perhaps the extra inefficiencies from the proposed new xor: definition that Levente identified are acceptable, given that performance-critical code can just use ~= or ~~?
Being able to accept "a xor: b" as well as "a xor: [b]" seems like a win for consistency with the other spelled-out operators to me.
(We wouldn't need to change any existing usage, either, right? Since true and false both understand #value?)
None of the senders in the trunk image are remotely performance-sensitive, it seems to me, with the possible exception of a use in detecting a word boundary in the regex engine.
Tony
On Fri, Feb 9, 2018 at 11:05 AM, Tony Garnock-Jones < tonyg@leastfixedpoint.com> wrote:
On 02/09/2018 06:47 PM, Nicolas Cellier wrote:
We also have a pair of binary messages that already works: ~= or even ~~
This is actually an excellent point.
Perhaps the extra inefficiencies from the proposed new xor: definition that Levente identified are acceptable, given that performance-critical code can just use ~= or ~~?
Being able to accept "a xor: b" as well as "a xor: [b]" seems like a win for consistency with the other spelled-out operators to me.
This was my original concern, too, but looking at Boolean, we have from
ancient times the method #eqv: which expects a boolean as an argument. It also is just another way to spell out == . Just like xor: is another, more familiar way to say ~~ (which while truely the same, I would not have thought of. Oh well.)
As an aside, we should move Boolean>>#xor: out of category "*Etoys-Squeakland-logical operations" and into just normal "logical operations" like #& and #eqv: and #xor: in the other booleans.
Interesting that #and: and #or: are not there, either - why are they in "controlling"?
-cbc
On Fri, Feb 9, 2018 at 8:30 PM Chris Cunningham cunningham.cb@gmail.com wrote:
On Fri, Feb 9, 2018 at 11:05 AM, Tony Garnock-Jones < tonyg@leastfixedpoint.com> wrote:
On 02/09/2018 06:47 PM, Nicolas Cellier wrote:
We also have a pair of binary messages that already works: ~= or even ~~
This is actually an excellent point.
Perhaps the extra inefficiencies from the proposed new xor: definition that Levente identified are acceptable, given that performance-critical code can just use ~= or ~~?
Being able to accept "a xor: b" as well as "a xor: [b]" seems like a win for consistency with the other spelled-out operators to me.
This was my original concern, too, but looking at Boolean, we have from
ancient times the method #eqv: which expects a boolean as an argument. It also is just another way to spell out == . Just like xor: is another, more familiar way to say ~~ (which while truely the same, I would not have thought of. Oh well.)
As an aside, we should move Boolean>>#xor: out of category "*Etoys-Squeakland-logical operations" and into just normal "logical operations" like #& and #eqv: and #xor: in the other booleans.
Interesting that #and: and #or: are not there, either - why are they in "controlling"?
-cbc
Okay, so we have identified alternatives for performance-critical code (~= or ~~) and it does not seem necessary to update senders. Apart from Chris' side note, is there anything else that needs to be addressed before this can be merged?
Fabio
I am still wondering why one would want to use xor with a block in the first place. The only purpose I can think of is that one does not accidentally write broken code. But then again, you can always misspell anything, get the types wrong, and you still need to test your stuff, right? As Nicolas wrote, it could even be caught by an automatic quality check in the future to shorten the time until feedback.
Since short-circuiting evaluation seems to be the primary feature of and: and or:, and I believe this is why they are in "controlling", just like ifTrue: and ifFalse: are, why should xor: conform with them? If it were not for Smalltalk's simple and uniform evaluation semantics, we would not need the blocks for conjunction and disjunction at all (you need to teach Smalltalk newcomers to use them correctly, after all). So one has to understand that the blocks are needed for conditional evaluation. Then the only reason why one would want to apply that to xor: is that one mistakenly believes that it might not always evaluate the right side, isn't it? If one believes that xor: had to conform with and: and or: in their technically-justified syntax usage ("oh I always have to use blocks to the right of boolean operators"), then one might not have understood the evaluation semantics yet and this patch would prevent one from noticing it at this moment.
So the "prevent accidental breakage" argument might be valid enough to merge this, but a linter should definitely point out the "misuse" as soon as possible, IMHO.
2018-02-10 17:33 GMT+01:00 Fabio Niephaus lists@fniephaus.com:
On Fri, Feb 9, 2018 at 8:30 PM Chris Cunningham cunningham.cb@gmail.com wrote:
On Fri, Feb 9, 2018 at 11:05 AM, Tony Garnock-Jones tonyg@leastfixedpoint.com wrote:
On 02/09/2018 06:47 PM, Nicolas Cellier wrote:
We also have a pair of binary messages that already works: ~= or even ~~
This is actually an excellent point.
Perhaps the extra inefficiencies from the proposed new xor: definition that Levente identified are acceptable, given that performance-critical code can just use ~= or ~~?
Being able to accept "a xor: b" as well as "a xor: [b]" seems like a win for consistency with the other spelled-out operators to me.
This was my original concern, too, but looking at Boolean, we have from ancient times the method #eqv: which expects a boolean as an argument. It also is just another way to spell out == . Just like xor: is another, more familiar way to say ~~ (which while truely the same, I would not have thought of. Oh well.)
As an aside, we should move Boolean>>#xor: out of category "*Etoys-Squeakland-logical operations" and into just normal "logical operations" like #& and #eqv: and #xor: in the other booleans.
Interesting that #and: and #or: are not there, either - why are they in "controlling"?
-cbc
Okay, so we have identified alternatives for performance-critical code (~= or ~~) and it does not seem necessary to update senders. Apart from Chris' side note, is there anything else that needs to be addressed before this can be merged?
Fabio
On Sat, 10 Feb 2018, Tony Garnock-Jones wrote:
On 02/10/2018 06:05 PM, Jakob Reschke wrote:
I am still wondering why one would want to use xor with a block in the first place.
An interpreter, perhaps:
a perform: {#or:. #xor:. #and:} atRandom with: [b]
Seems like a pretty artificial example, of course :-)
Neither #or: nor #and: check the type of the argument, so adding that to #xor: would be a new "feature". But both #or: and #and: accept booleans as argument. So,
a perform: {#or:. #xor:. #and:} atRandom with: b
would just work for that imaginary interpreter if b were a Boolean.
Levente
Tony
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.
All told, I'm neutral.
Cheers, Tony
[1] http://wiki.squeak.org/squeak/uploads/172/standard_v1_9-indexed.pdf
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
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
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@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.
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
On Wed, Mar 21, 2018 at 2:48 PM, Levente Uzonyi leves@caesar.elte.hu wrote:
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@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.
Here is a simpler and faster alternative:
True >> #xor: aBoolean
aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]
False >> #xor: aBoolean
aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]
and is this noticeably slower?
True >> #xor: aBoolean
^aBoolean ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBoolean
^aBoolean ifTrue: [ true ] ifFalse: [ false ]
but I would much prefer to see either
Boolean>>xor: aBooleanOrBlock
^ aBooleanOrBlock value not
or
True >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ true ] ifFalse: [ false ]
The lack of symmetry with and: and or: is, IMO, bad.
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
On Wed, Mar 21, 2018 at 4:09 PM, Eliot Miranda eliot.miranda@gmail.com wrote:
On Wed, Mar 21, 2018 at 2:48 PM, Levente Uzonyi leves@caesar.elte.hu wrote:
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@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.
Here is a simpler and faster alternative:
True >> #xor: aBoolean
aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]
False >> #xor: aBoolean
aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]
and is this noticeably slower?
True >> #xor: aBoolean
^aBoolean ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBoolean
^aBoolean ifTrue: [ true ] ifFalse: [ false ]
but I would much prefer to see either
Boolean>>xor: aBooleanOrBlock
^ aBooleanOrBlock value not
or
True >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ true ] ifFalse: [ false ]
The lack of symmetry with and: and or: is, IMO, bad.
I started out with this mind-set, but Tobias' arguments crystallized the discussion for me: 1. Adhere to standards (booleans only) 2. Or, maybe #xor: behave like and: and or:. I also found another discussion - unlike and: and or:, for xor: you will ALWAYS have to evaluate the block - and that doubles (or significantly more) the amount of time needed to run the method. It is still small, of course.
With this last slight variation, our rule would be "as long as the receiver is a boolean and the arguments' value is a boolean, then we apply the rule". I could live with that.
-cbc
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
-- _,,,^..^,,,_ best, Eliot
On Wed, 21 Mar 2018, Eliot Miranda wrote:
On Wed, Mar 21, 2018 at 2:48 PM, Levente Uzonyi leves@caesar.elte.hu wrote: 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@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.
Here is a simpler and faster alternative:
True >> #xor: aBoolean
aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]
False >> #xor: aBoolean
aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]
and is this noticeably slower?
True >> #xor: aBoolean
^aBoolean ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBoolean
^aBoolean ifTrue: [ true ] ifFalse: [ false ]
Yes, it is. Here are the bytecodes for your suggestion:
33 <10> pushTemp: 0 34 <99> jumpFalse: 37 35 <71> pushConstant: true 36 <90> jumpTo: 38 37 <72> pushConstant: false 38 <7C> returnTop
And for my variant:
33 <10> pushTemp: 0 34 <98> jumpFalse: 36 35 <79> return: true 36 <7A> return: false
I measured the latter to be 14% faster.
Levente
but I would much prefer to see either
Boolean>>xor: aBooleanOrBlock
^ aBooleanOrBlock value not
or
True >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ true ] ifFalse: [ false ]
The lack of symmetry with and: and or: is, IMO, bad.
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
-- _,,,^..^,,,_ best, Eliot
On Wed, Mar 21, 2018 at 5:15 PM, Levente Uzonyi leves@caesar.elte.hu wrote:
On Wed, 21 Mar 2018, Eliot Miranda wrote:
On Wed, Mar 21, 2018 at 2:48 PM, Levente Uzonyi leves@caesar.elte.hu wrote: 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@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.
Here is a simpler and faster alternative:
True >> #xor: aBoolean
aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]
False >> #xor: aBoolean
aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]
and is this noticeably slower?
True >> #xor: aBoolean
^aBoolean ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBoolean
^aBoolean ifTrue: [ true ] ifFalse: [ false ]
Yes, it is. Here are the bytecodes for your suggestion:
33 <10> pushTemp: 0 34 <99> jumpFalse: 37 35 <71> pushConstant: true 36 <90> jumpTo: 38 37 <72> pushConstant: false 38 <7C> returnTop
And for my variant:
33 <10> pushTemp: 0 34 <98> jumpFalse: 36 35 <79> return: true 36 <7A> return: false
I measured the latter to be 14% faster.
For xor: it's hardly worth it. Nicer if the compiler and decompiler did the transformation...
Levente
but I would much prefer to see either
Boolean>>xor: aBooleanOrBlock
^ aBooleanOrBlock value not
or
True >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ true ] ifFalse: [ false ]
The lack of symmetry with and: and or: is, IMO, bad.
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
-- _,,,^..^,,,_ best, Eliot
So, speed:
current (^aBoolean or ^aBoolean not) - standard ~~ 71% faster ul's xor: (aBoolean ifTrue: [^] ifFalse: [^]) 7% slower em's xor: ( ^aBoolean ifTrue: [] ifFalse: []) 22% slower ul's block xor: (aBoolean value ifTrue: [^] ifFalse: [^]) 42% slower em's block xor: (^aBoolean value ifTrue: [] ifFalse: []) 65% slower fn's xor: (^ alternativeBlock value or ^alternativeBlock value not) 84% slower
I find it weird that the extra ifTrue:ifFalse: call after the value actually makes the method faster. Weird. But it does make it more consistent/right - it only works when the receiver and value of the argument are both booleans - with the right results.
Note that even though the percentages are fairly large, the actual time to run 10,000,000 of these checks took right about 3 second for the slowest of these - once I've removed the 6 seconds of the loop overhead. Still fast.
Will be moving to trunk shortly, using this style: ^aBoolean value ifTrue: [] ifFalse: [] It just feels more natural. Feel free to adjust if desired.
-cbc
On Wed, Mar 21, 2018 at 7:20 PM, Eliot Miranda eliot.miranda@gmail.com wrote:
On Wed, Mar 21, 2018 at 5:15 PM, Levente Uzonyi leves@caesar.elte.hu wrote:
On Wed, 21 Mar 2018, Eliot Miranda wrote:
On Wed, Mar 21, 2018 at 2:48 PM, Levente Uzonyi leves@caesar.elte.hu wrote: 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@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.
Here is a simpler and faster alternative:
True >> #xor: aBoolean
aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]
False >> #xor: aBoolean
aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]
and is this noticeably slower?
True >> #xor: aBoolean
^aBoolean ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBoolean
^aBoolean ifTrue: [ true ] ifFalse: [ false ]
Yes, it is. Here are the bytecodes for your suggestion:
33 <10> pushTemp: 0 34 <99> jumpFalse: 37 35 <71> pushConstant: true 36 <90> jumpTo: 38 37 <72> pushConstant: false 38 <7C> returnTop
And for my variant:
33 <10> pushTemp: 0 34 <98> jumpFalse: 36 35 <79> return: true 36 <7A> return: false
I measured the latter to be 14% faster.
For xor: it's hardly worth it. Nicer if the compiler and decompiler did the transformation...
Levente
but I would much prefer to see either
Boolean>>xor: aBooleanOrBlock
^ aBooleanOrBlock value not
or
True >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ false ] ifFalse: [ true ]
False >> #xor: aBooleanOrBlock
^aBooleanOrBlock value ifTrue: [ true ] ifFalse: [ false ]
The lack of symmetry with and: and or: is, IMO, bad.
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
-- _,,,^..^,,,_ best, Eliot
-- _,,,^..^,,,_ best, Eliot
Currency sign looks like a X on top of a O : ¤
Best, Karl
On Fri, Feb 9, 2018 at 7:35 PM, Tobias Pape Das.Linux@gmx.de wrote:
On 09.02.2018, at 19:06, Fabio Niephaus lists@fniephaus.com wrote:
On Fri, Feb 9, 2018 at 6:31 PM Chris Cunningham cunningham.cb@gmail.com
wrote:
#xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument
block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects
(sometimes).
I'm just curious - is there an equivalent symbol for xor similar to |
and & that we could use?
In some languages, they use ^ but for obvious reason that's not useful.
I wonder if we could use ~ for #xor:?
Wikipedia says:
"It is symbolized by the prefix operator J[2] and by the infix operators XOR (/ˌɛks ˈɔːr/), EOR, EXOR, ⊻, ⩒, ⩛, ⊕, ↮, and ≢. "
Theoretically, we could use any of these symbols, (⊕ is often used in maths) but our fonts don't display them yet, so that has to wait.
Further there:
"+, a plus sign", well, would work (on booleans) but could be
confusing "J, as in Jpq", not working for us
", sometimes written as • >< • >-<" THAT could work.
I like
a >< b
it looks like an X a bit.
Best regards -Tobias
PS: GMail/Inbox apparently destroys the citation level :(
Also, before making this change to using blocks (if we do), we'd need to
fix all users - probably also in the VMMaker packages.
Right...fortunately, there aren't that many senders...
Fabio
-cbc
On Fri, Feb 9, 2018 at 9:18 AM, Levente Uzonyi leves@caesar.elte.hu
wrote:
On Fri, 9 Feb 2018, marcel.taeumel wrote:
commits-2 wrote A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-fn.1151.mcz
==================== Summary ====================
Name: Kernel-fn.1151 Author: fn Time: 9 February 2018, 12:32:25.516883 pm UUID: 9fb7df4b-6bf4-4af8-9c75-7496c2f0b517 Ancestors: Kernel-tonyg.1150
For consistency: allow blocks to be passed into #xor: (see #or: and #and:).
=============== Diff against Kernel-tonyg.1150 ===============
Item was changed: ----- Method: False>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value!
^aBoolean!
Item was changed: ----- Method: True>>xor: (in category 'logical operations') -----
- xor: alternativeBlock
- xor: aBoolean "Posted by Eliot Miranda to squeak-dev on 3/24/2009"
^alternativeBlock value not!
^aBoolean not!
Hey Nicolas,
it seems that you had the intention to not allow "a xor: [b]" because, obviously, one does always have to check both operands for XOR. Yet,
would
it do any harm if we would allow "a xor: [b]"?
Performance. Two fold: you create a block for no reason, because it will
always be evaluated right after its creation.
If there is no block, #value still has to be sent.
Levente
Best, Marcel
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
On 09.02.2018, at 19:35, Tobias Pape Das.Linux@gmx.de wrote:
On 09.02.2018, at 19:06, Fabio Niephaus lists@fniephaus.com wrote:
On Fri, Feb 9, 2018 at 6:31 PM Chris Cunningham cunningham.cb@gmail.com wrote: #xor: is on the same plane as #| and #& - evaluate both sides and apply
We also have #and: and #or: - evaluate receiver, and evaluate argument block if and only if necessary.
I use #and: and #or: for speed purposes - and to avoid side effects (sometimes).
I'm just curious - is there an equivalent symbol for xor similar to | and & that we could use?
In some languages, they use ^ but for obvious reason that's not useful. I wonder if we could use ~ for #xor:?
Wikipedia says:
"It is symbolized by the prefix operator J[2] and by the infix operators XOR (/ˌɛks ˈɔːr/), EOR, EXOR, ⊻, ⩒, ⩛, ⊕, ↮, and ≢. "
Theoretically, we could use any of these symbols, (⊕ is often used in maths) but our fonts don't display them yet, so that has to wait.
Further there:
"+, a plus sign", well, would work (on booleans) but could be confusing "J, as in Jpq", not working for us
", sometimes written as • >< • >-<"
THAT could work.
I like
a >< b
it looks like an X a bit.
Since I am having stupid ideas:
Smalltalk at: #'_' put: nil
;P
Best regards -Tobias
squeak-dev@lists.squeakfoundation.org