-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
explore fixing #5187 via and/or/xor/not and associated updating ops #25180
Conversation
In this approach, I guess we could go with the versions from mathematical logic: Overall looking at the code It's a bit saddening to see the brevity and familiarity lost by doing this and the inconsistency of having operators like |
Yes, it's very much a tradeoffs game :). |
It would sadden me to see Julia become less ergonomic for bitwise operations and honestly I do not thing that
I suppose the tension come from the fact that If we decide to go for this I would very much like Unicode aliases http://www.fileformat.info/info/unicode/char/2228/index.htm and http://www.fileformat.info/info/unicode/char/2227/index.htm --edit: I should add that even though I am not a fan of this change, many thanks to |
I agree 100% with @vchuravy and @ararslan here. The problem with The two actions we should possibly take are:
|
While The other arguments against this approach strike me as much stronger :). Somewhat orthogonal to this discussion: Thanks all! :) |
(To be clear, I am quite sympathetic to the arguments against this approach. Nonetheless this approach seemed worth exploring given its combination of interesting tradeoffs and prior apparent support :).) |
Probably not. (See what I did there?) |
I did and I'm dying. Edit: Well, not dying it turns out 😛. |
This is nicely said. |
Stefan wrote:
Abstract logical? I think operationally there may be types which behave differently under bitwise operations and "logical" operations - see #25435 (comment) The other smoking gun is that the precedence desired for "logical" statements (lower?) seems to me to be a bit different to the precedence desired for "bitwise" operations (higher?). Personally, I see two distinct semantics here. We can afford two abstract interfaces (whatever they may be) that happen to overlap for (And yes, judging by the kind of people wanting to use Julia, I would guess you are just as likely to get an end user interested in non-standard logic as you are a seasoned programmer who needs to twiddle his bits. Even 3VL with |
(Another exploration in resolving #5187. This approach evolved out of #25156, but presents a better set of tradeoffs and much nicer looking code. Relevant parts of the #25156 writeup are repeated below.)
The crux of #5187:
&
and|
conflate logical and bitwise operations. The natural precedence of&
and|
for logical operations is low, whereas that for bitwise operations is high. This tension forces an unsatisfying precedence compromise.One approach to resolving this tension is to use regular functions instead of infix operators for (non-control-flow) logical and bitwise operations, for example
and
/or
/xor
/not
(as withxor
now) and corresponding updating operatorsand=
/or=
/xor=
/not=
. Having additional upsides (see below), this approach at one point or another received support from (e.g.) multiple(1) core(2) contributors(3) on github(4), slack, and triage.This branch explores what life looks like with the particular names/ops mentioned above. (#25156 explored a different realization of this concept, naming only bitwise operations and not providing corresponding updating operators). This branch is somewhat outdated and incomplete, and only the first half or so of the diff uses the updating operators, so assessing that half is best.
A few unexpected findings from preparing #25156 relevant here:
I was surprised by how infrequently I had to add parentheses to (compound) expressions when rewriting with
or
/and
/not
/xor
and associated updating ops: In such compound expressions, defensive parens seemed the rule rather than the exception.I was also surprised that, despite having the precedence table open (or by some point memorized) and knowing the associativity rules, I occasionally had to resort to checking the result of certain compound expressions at the repl to figure out precisely what they were doing.
These observations perhaps support the notion that something is amiss with precedence as it stands (#5187), or perhaps support the notion that relying upon precedence and associativity in compound bit twiddling and eager logical expressions is suboptimal in any case (too difficult to remember, too difficult to mentally parse, or what have you).
What are the tradeoffs of this approach?
Arguments in favor:
With
or
/and
/not
/xor
and associated updating ops, you never need the precedence table and/or associativity rules on hand (or memorized) to grok bit twiddling and/or eager logical expressions, nor need you interrogate particularly complex expressions at the repl.Functions
or
/and
/not
/xor
and the associated updating ops are relatively semantically clear independent of which language(s) you came from, whereas expectations regarding the semantics, precedence, and associativity of infix ops&
/|
/~
vary depending on which language(s) you came from.or
/and
/not
/xor
and associated updating ops yield substantially nicer looking code than the approach in #25156, providing a much better approximation to the cuteness and compactness of the present infix operators. Particularly, this approach's updating ops are quite pleasant.This approach immediately frees all of
&
,|
, and~
(rather than only #25156's~
). Uses for free ASCII appear in every discussion of feature introduction or extension (think views, partial evaluation and currying, dataflow pipelining, traits/protocols, missingness, getfield overloading, things namespacing related, et cetera). Dare I say there are better uses for these operators in a language like Julia than bit twiddling.FemtoCleaner can perform this approach's rewrites (in contrast to those in #25156).
Arguments against:
To those of us who came from C(/-influenced languages),
&
/|
/~
(/^
) feel natural for bitwise and eager logical operations. (On the other hand, names like those in this approach are common to a number of languages, e.g. lisps, ada, algol, some pascals, et cetera.)Expressions in
or
/and
/not
/xor
and associated updating operators are slightly more verbose than in&
/|
/~
(but unlike #25156's names, the names here retain most of the infix operators' compactness and cuteness).The advantages of
or
/and
/not
/xor
hold primarily in compound / complex expressions. In short such expressions, the downsides of&
/|
/~
are weaker and the upsides stronger, and one could argue that expressions where the downsides of&
/|
/~
become significant should be refactored.Other considerations worth bearing in mind:
Though a good fraction of those of us active on github came from C and do / have done a nontrivial amount of bit twiddling, chances are we represent a minority in the broader Julia userbase (and likely will be a shrinking minority with future uptake). Naturalness/intuitiveness for us may not be a good predictor of naturalness/intuitiveness for the broader userbase, perhaps to the contrary.
Typing speed is rarely if ever a productivity rate limiter when bit twiddling, whereas existing-code-grokking speed frequently is.
Thoughts? Thanks all! :)