Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

schapel
Posts: 244
Joined: Fri Jun 13, 2014 1:33 am UTC

Re: Coding: Fleeting Thoughts

Postby schapel » Tue Aug 26, 2014 6:20 pm UTC

This is why when I write range tests, I write something like this:

Code: Select all

if (0 <= a && a < n)
rather than

Code: Select all

if (a >= 0 && a < n)
I always need to mentally rearrange the latter expression to understand the range it is testing. It seems that this is not a popular idiom. I wonder why not.

Actually, I think the expressions involving ^ and != above are in general easier to understand, because they succinctly express the comparison being performed. I prefer the != notation to the ^ notation, because I mentally translate ^ into != when reading the code.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Tue Aug 26, 2014 6:35 pm UTC

Yakk wrote:
If you're writing an MPEG encoder or something extremely performance critical, then maybe some hard-to-read voodoo may be merited. But that was not this code.

Even then, doing more things on one line does not make your code faster.


Yeah. My point was heavily optimized code => (sometimes) hard to read. Not that somehow difficulty of readingefficiency of code or skill of programmer.

In fact, with regards to the latter, I'd argue it's quite the opposite. You could train a chimpanzee to produce unreadable spaghetti code. It's much harder to produce (and maintain) readable and well structured code. Code has a sort of entropy like that.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Wed Aug 27, 2014 5:06 am UTC

( @phlip: hey, your Life-in-Life video's on proggit. )

I don't know why everyone's talking about hard to read code and lots of shit on one line. jaap's code was just

Code: Select all

return !( hasSomeProperty(X) ^ isRunFooMode );
(and the other example was reducing 3 logical operations to one.) I think it would be hard to argue that splitting a single return value into conditional returns just to prevent an XOR operation is making code easier to read.

PM 2Ring wrote:I prefer

Code: Select all

if( (var1==1) != (var2==1) )
since (as you said) ^ is a bitwise operator, but I guess not everyone is comfortable with the idea that != is equivalent to XOR when used between booleans.
I remember using != in some language where I couldn't use XOR, but I prefer XOR. I think XOR captures the meaning of the operation more directly: "exactly one of these is true". != says "these have opposite truth values", which is the same thing, but an odd way to put it. I don't so much mind == for (although I would still prefer a dedicated operator).

One thing I'd like is an implication operator. It can be annoying having to say "B or not A".

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: Coding: Fleeting Thoughts

Postby korona » Wed Aug 27, 2014 6:01 pm UTC

In most programming languages != is more "correct" as ^ involves a cast to int and back in most programming languages.

speising
Posts: 2365
Joined: Mon Sep 03, 2012 4:54 pm UTC
Location: wien

Re: Coding: Fleeting Thoughts

Postby speising » Wed Aug 27, 2014 6:09 pm UTC

for booleans? i'm doubtful.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Wed Aug 27, 2014 6:15 pm UTC

speising wrote:for booleans? i'm doubtful.
a^b is an int in C++. Probably in almost all C-derived languages.(It's a bool in Java.) That means if a and b are bools, they'll undergo integer promotion. This is an ideological problem more than a practical one most of the time, but I do think it's a reasonable reason to discoruage it.

I also think that a==b is way clearer than !(a^b). Heck, I'd prefer a+b==1 to !(a^b).Doh, that's backwards, of course. This has not been one of my better posts. :-) I almost have to mentally construct the truth table to make sense of the xor one.
Last edited by EvanED on Wed Aug 27, 2014 7:44 pm UTC, edited 4 times in total.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Wed Aug 27, 2014 6:22 pm UTC

In C# &, ^, and | are all treated as logical operators when used on booleans anyway.
Last edited by Thesh on Wed Aug 27, 2014 6:24 pm UTC, edited 1 time in total.
Summum ius, summa iniuria.

speising
Posts: 2365
Joined: Mon Sep 03, 2012 4:54 pm UTC
Location: wien

Re: Coding: Fleeting Thoughts

Postby speising » Wed Aug 27, 2014 6:22 pm UTC

right, forget what i said. ^ is not a logical op.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Wed Aug 27, 2014 8:09 pm UTC

troyp wrote:I don't know why everyone's talking about hard to read code and lots of shit on one line. jaap's code was just

Code: Select all

return !( hasSomeProperty(X) ^ isRunFooMode );
(and the other example was reducing 3 logical operations to one.) I think it would be hard to argue that splitting a single return value into conditional returns just to prevent an XOR operation is making code easier to read.


I'll gladly argue

Spoiler:

Code: Select all

boolean includePredicate(X) {
  if (isRunFooMode) {
     return hasSomeProperty(X);
  }
  return !hasSomeProperty(X);
}


is easier to read than

Spoiler:

Code: Select all

boolean includePredicate(X) {
  return !(isRunFooMode ^ hasSomeProperty(X));
}


Programmers deal with simple if-statements all the time, and as such very strong intuition of how they work. There very obviously are no gotchas hidden in the first variant of the code. I can immediately tell what it does for any value of isRunFooMode and hasSomeProperty(X), because I've seen code like that thousands upon thousands of times, multiple times a day most days.

But the first, with a XNOR, to make sense of that I need to stop and think about what the code does, and even then it's far less intuitive, so every time I read the function, I'm like "Let's see, if isRunFooMode is true, and hasSomeProperty(X) is true, then the XOR is false, but it's negated, so we return true...", and then I sit trying to squeeze an entire XNOR truth table into my thought process, making it pretty crowded in terms of actually figuring out whether the code does what I think it does. This is because I have no intuitive model of XNOR, because I encounter explicit XNOR logic at the very most once or twice a year.

The == option is slightly less bad in that regard, as it's also deeply ingrained in the programmer's intuition. The ternary operator (pred?yes:no) is also a viable option for feeble-fingered programmers.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Thu Aug 28, 2014 12:21 am UTC

korona wrote:In most programming languages != is more "correct" as ^ involves a cast to int and back in most programming languages.
I think "most" is a great exaggeration. In C bools are ints, so I can't see any objection. In most other languages I can think of offhand, ^ is either overloaded for bools or outright illegal for bools. In a language like C++ where you're casting to ints... well, I agree it's ugly... although I still think it's more readable. Is there actually any real issue with this other than elegance? I do use != in C++, but I tend to think it's only a matter of pedantry on my part and I might be better off using ^.

EvanED wrote:I also think that a==b is way clearer than !(a^b). ... I almost have to mentally construct the truth table to make sense of the xor one.
I think that's somewhat of an exaggeration too, but I do agree that a==b is way better. That was the only thing jaap wrote that I took issue with (although he did say he'd probably use == for a simple case like this.)

You, sir, name? wrote:Programmers deal with simple if-statements all the time, and as such very strong intuition of how they work. There very obviously are no gotchas hidden in the first variant of the code. I can immediately tell what it does for any value of isRunFooMode and hasSomeProperty(X), because I've seen code like that thousands upon thousands of times, multiple times a day most days.

But the first, with a XNOR, to make sense of that I need to stop and think about what the code does, and even then it's far less intuitive, so every time I read the function, I'm like "Let's see, if isRunFooMode is true, and hasSomeProperty(X) is true, then the XOR is false, but it's negated, so we return true...", and then I sit trying to squeeze an entire XNOR truth table into my thought process, making it pretty crowded in terms of actually figuring out whether the code does what I think it does. This is because I have no intuitive model of XNOR, because I encounter explicit XNOR logic at the very most once or twice a year.

The == option is slightly less bad in that regard, as it's also deeply ingrained in the programmer's intuition. The ternary operator (pred?yes:no) is also a viable option for feeble-fingered programmers.
As I mentioned above, I'm totally with you on the a==b vs !(a^b). (I didn't bring that up originally because it wasn't really relevant to the point I was making.) Still, I'd claim even with the !(a^b), the single return statement is probably better and certainly not worse.

I agree in the example in question, the two return statements aren't particularly problematic. I use multiple exit points regularly myself, so I'm not some kind of structured programming nazi. But I do think there's always a cost. It's always going to make it harder to reason about code and increase the chance of errors. Only a little in this case, admittedly.

But I think you're massively overstating the difficulties in reading a simple logical expression. I agree you have to think about !(a^b)* and that's always a bad thing. But we're only talking about a second here. It's a cost, but it's even less than the cognitive overhead on splitting up your return statement.

* Really, that's not even true. If you have the identity !(a^b) ≡ a==b ingrained, you'll be able to read it without pausing. Admittedly, I don't. I'm really lazy about this stuff. I just think it through each time. I do think it's worthwhile, though: it increases the fluency with which you read logic and keeps your mind free of distractions.

edit: okay, I didn't really take on what you're saying. You're serious about having trouble reading the expression. Fair enough, but that's the problem, not the expression itself: you should get used to it. I think it's important to be able to use logical notation fluently. If you can't... well, you'll be forced to replace simple declarative expressions with chains of verbose imperative instructions. It's kind of like taking a simple math formula and replacing it with a paragraph of contorted English. It might be more readable to some people, but you'd never recommend it. The proper advice is "learn to read the notation".

The intuitive model for xor is just "exactly one of these is true" (a secondary intuition is "these two truth values are different"). Negating it you get xnor="both or neither are true" ("the two truth values are the same"). If you remember the intuitive meaning of xor, the negation will be very quick (you do it before you consider the actual values).

If you start actually using logical expressions more, you'll find it's virtually no effort at all. In fact, it'll reduce the load on your concentration (just like any good mathematical notation). Hell, you'll probably start to use it to write notes to yourself because it's easier to read.

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Thu Aug 28, 2014 12:52 am UTC

I once used:

Code: Select all

(bool_1a == bool_1b) == (bool_2a == bool_2b)
With about 10 lines of comment explaining what the hell was going on and why.
He/Him/His/Alex
God damn these electric sex pants!

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Thu Aug 28, 2014 1:05 am UTC

troyp wrote:
korona wrote:In most programming languages != is more "correct" as ^ involves a cast to int and back in most programming languages.
I think "most" is a great exaggeration. In C bools are ints, so I can't see any objection. In most other languages I can think of offhand, ^ is either overloaded for bools or outright illegal for bools. In a language like C++ where you're casting to ints... well, I agree it's ugly... although I still think it's more readable. Is there actually any real issue with this other than elegance? I do use != in C++, but I tend to think it's only a matter of pedantry on my part and I might be better off using ^.
Like I said, it's mostly ideological. There are at least two reasons I think it's more than that though. The first is if you decide you want to store the value of an expression in a bool variable or pass it as an argument to a function that takes a bool, a^b will produce a warning and a!=b will not. That means you "have to" use either a cast or != in such cases, which means using ^ in conditions is not just less elegant but inconsistent. Second, and I'll admit this is an edge case, if you have an overloaded function between int and bool the two expressions will resolve to different overloads. (Other problems are if you assign a^b to an auto it will take the wrong type, you'll get wrong types for templates, etc.)

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Thu Aug 28, 2014 1:42 am UTC

@ahammel: I think that's a horrible expression (or as horrible as a 3-operation expression can be), but not because of the compact syntax. It's actually really easy to read (it takes me 1-2 seconds, and I'm not a fast thinker). The issue is the meaning itself is complicated and unintuitive. The nicest way I can think to express it is: "Either the bool1's match and the bool2's match or neither pair matches." That's just an odd proposition: it doesn't really resolve to something simple. Probably the only way to make it intuitive would be to build up abstractions that have a meaning in the problem domain and express it in terms of those.

@EvanED: makes sense to me. I'll keep using it, then.
Do you know why bool^bool gives an int in the first place? Is it for compatibility with some version of C with a bool keyword? Or to make it easy to combine bools with bitwise expressions?

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Thu Aug 28, 2014 3:24 am UTC

troyp wrote:@ahammel: I think that's a horrible expression (or as horrible as a 3-operation expression can be), but not because of the compact syntax. It's actually really easy to read (it takes me 1-2 seconds, and I'm not a fast thinker). The issue is the meaning itself is complicated and unintuitive. The nicest way I can think to express it is: "Either the bool1's match and the bool2's match or neither pair matches." That's just an odd proposition: it doesn't really resolve to something simple. Probably the only way to make it intuitive would be to build up abstractions that have a meaning in the problem domain and express it in terms of those.
It's a little better with reasonable variable names, but not much. The context is manipulating DNA sequences, which is full of difficult-to-intuit conditions and off-by-ones and fence-posts and generally just sucks.
He/Him/His/Alex
God damn these electric sex pants!

jareds
Posts: 436
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: Coding: Fleeting Thoughts

Postby jareds » Thu Aug 28, 2014 3:32 am UTC

There are two major differences between bitwise AND (&) and logical AND (&&) in both C and C++. The first difference is that logical AND short circuits: this is moot for XOR. The second difference is whether they operate on a bitwise basis: logical AND computes 1 if both operands are non-zero, 0 otherwise. (There are further differences in C++.) By the principal of least surprise, I would expect logical XOR (^^) to compute: (A ^^ B) => (A != 0) ^ (B != 0).

I see the following difficulties with providing logical XOR and bitwise XOR with the same operator symbol. If (int XOR bool) is permitted, it's not obvious whether it should be bitwise or logical. If (int XOR bool) is forbidden, that is different than all the other bitwise and logical operators. Also, there is a problem specific to C: it has had a boolean type since C99, but the results of the equality, relational, and logical operators still have type 'int', so it would not be very useful to have an overloaded bitwise/logical XOR operator.

In general, this distinction is a reason to be wary of using bitwise operators instead of logical operators. Whatever one may think of it, the practice of using integral 'exp' instead of 'exp != 0' in a boolean context is prevalent, so if you see a bitwise operator used as a logical operator, you have to stop and think about whether the operands are guaranteed to be 0 or 1 (unless perhaps the operands are the results of equality, relational, or logical operators).

ahammel wrote:I once used:

Code: Select all

(bool_1a == bool_1b) == (bool_2a == bool_2b)
With about 10 lines of comment explaining what the hell was going on and why.

I can't help but notice that you could have written:

Code: Select all

!(bool_1a ^ bool_1b ^ bool_2a ^ bool_2b)

Without context, it's not actually possible to tell if this is a point for or against XNOR (especially since neither variant is particularly clear). (The XNOR variant would actually be much more clear if you were interested in the sum mod 2, but probably less clear otherwise.)

User avatar
Diadem
Posts: 5654
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Thu Aug 28, 2014 10:06 am UTC

jareds wrote:
ahammel wrote:I once used:

Code: Select all

(bool_1a == bool_1b) == (bool_2a == bool_2b)
With about 10 lines of comment explaining what the hell was going on and why.

I can't help but notice that you could have written:

Code: Select all

!(bool_1a ^ bool_1b ^ bool_2a ^ bool_2b)

Without context, it's not actually possible to tell if this is a point for or against XNOR (especially since neither variant is particularly clear). (The XNOR variant would actually be much more clear if you were interested in the sum mod 2, but probably less clear otherwise.)

It really depends on the context which is clearest here. If the context is "I want an even number of these to be true" then your version is best. So basically if it is one group of 4 booleans, instead of 2 pairs of 2 booleans. You could also use

Code: Select all

bool_1a != bool_1b ^ bool_2a == bool_2b

which in some contexts may make sense, but in others is very confusing.
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Thu Aug 28, 2014 11:26 am UTC

troyp wrote:( @phlip: hey, your Life-in-Life video's on proggit. )

Yeah, I noticed it was getting a lot of traffic recently. Motivated me to poke around in YT's video settings and find out there is actually a way to replace the audio track of a vid without reuploading... so it keeps the same URL, keeps all its stats, and whatnot. So... I've done that.

I'm not 100% sure what I was thinking when I thought that the earpiercing Shepard tone would be a good backing for that video, but I've definitely changed my mind now...

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Thu Aug 28, 2014 3:08 pm UTC

Diadem wrote:
jareds wrote:
ahammel wrote:I once used:

Code: Select all

(bool_1a == bool_1b) == (bool_2a == bool_2b)
With about 10 lines of comment explaining what the hell was going on and why.

I can't help but notice that you could have written:

Code: Select all

!(bool_1a ^ bool_1b ^ bool_2a ^ bool_2b)

Without context, it's not actually possible to tell if this is a point for or against XNOR (especially since neither variant is particularly clear). (The XNOR variant would actually be much more clear if you were interested in the sum mod 2, but probably less clear otherwise.)

It really depends on the context which is clearest here. If the context is "I want an even number of these to be true" then your version is best. So basically if it is one group of 4 booleans, instead of 2 pairs of 2 booleans. You could also use

Code: Select all

bool_1a != bool_1b ^ bool_2a == bool_2b

which in some contexts may make sense, but in others is very confusing.
In context it's more like "either both of these sets of booleans match or neither does". I'm not positive that's the clearest way of expressing that in code, but it was the best I could come up with at the time.
He/Him/His/Alex
God damn these electric sex pants!

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Sat Aug 30, 2014 4:30 am UTC

jareds wrote:I can't help but notice that you could have written:

Code: Select all

!(bool_1a ^ bool_1b ^ bool_2a ^ bool_2b)

Without context, it's not actually possible to tell if this is a point for or against XNOR (especially since neither variant is particularly clear). (The XNOR variant would actually be much more clear if you were interested in the sum mod 2, but probably less clear otherwise.)
Or

Code: Select all

bool_1a == bool_1b == bool_1c == bool1d
if you were interested in the number of Falses mod 2 (which is the same thing since there's an even number of values, but not in general). However in this case the variable names are a good indication that the pair-matching version was what was intended.

Actually, I suspect ahammel's code was Python, so the expression above wouldn't actually work due to python's handling of chained relational operators (chained relationals are interpreted as the conjunction of the pairwise relations). It's a little odd to have associativity fail for ==, but I actually think Python does this right. For an arithmetic operator, breaking the associativity would be disastrous, but for relational operators you rarely want to parenthesize them anyway. This allows relational operators to be used the natural, mathematical way in the common case and parentheses serve an "evaluation" function ("use the truth value of this relational expression as a value") Still, this underlines my (minor) misgivings about using == as a logical operator. Equality and equivalence are not the same thing conceptually, and in some languages may not be the same thing practically.

phlip wrote:
troyp wrote:( @phlip: hey, your Life-in-Life video's on proggit. )

Yeah, I noticed it was getting a lot of traffic recently. Motivated me to poke around in YT's video settings and find out there is actually a way to replace the audio track of a vid without reuploading... so it keeps the same URL, keeps all its stats, and whatnot. So... I've done that.

I'm not 100% sure what I was thinking when I thought that the earpiercing Shepard tone would be a good backing for that video, but I've definitely changed my mind now...

Yeah, it was pretty awful. OTOH, it's kind of interesting to listen to. I'd try to spot when the pitch dropped, but it's actually quite hard. I could tell roughly when it happened ("oh, it just dropped a moment ago"), but I could never identify an exact note. It almost sounded as if there was a cross-fade during the transition.

Mind you, now I think about it, I realize it was probably cycling the notes in the chord (or maybe I should say "scale"): they'd all rise continuously, and as top one disappears it would reappear at the bottom. Because the whole set of notes maintains the same spacing, the disappearing notes at the top aren't really noticed, but the constant upwards movement is. So when I periodically noticed the drop, it was probably just my perspective shifting and jumping back down. I've heard Shephard tones described as an auditory barber pole illusion, but I'd sort of forgotten about it until now. It really is an accurate description.

User avatar
The Great Hippo
Swans ARE SHARP
Posts: 7368
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

Re: Coding: Fleeting Thoughts

Postby The Great Hippo » Sun Aug 31, 2014 12:46 am UTC

Python 3.x supports function annotations, which are ostensibly for implementing your own type-checking and doc strings. There's a couple of limitations to this, though -- and I was wondering if a reasonable way to overcome some of them might be a bizarre implementation of something like algebraic data types.

For example, say a function accepts x, which must be hashable, but cannot be None. I want to type-check it. Rather than doing an error check in the function -- and rather than creating some sort of predicate annotation system (presumedly with an Annotation class) -- would it be reasonable to implement expressions like 'hashable - None' -- which would produce a new type that returns True when compared to hashables, except in cases where they are None?

Extending that, could you then do expressions like 'int + str' -- which would produce a new type that returns True when compared to ints or strings?

And even if so, would this be insane to do? I'm not planning on trying to implement it; it's just a fleeting thought I had today at work.

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Sun Aug 31, 2014 3:43 am UTC

The Great Hippo wrote:Python 3.x supports function annotations, which are ostensibly for implementing your own type-checking and doc strings. There's a couple of limitations to this, though -- and I was wondering if a reasonable way to overcome some of them might be a bizarre implementation of something like algebraic data types.

For example, say a function accepts x, which must be hashable, but cannot be None. I want to type-check it. Rather than doing an error check in the function -- and rather than creating some sort of predicate annotation system (presumedly with an Annotation class) -- would it be reasonable to implement expressions like 'hashable - None' -- which would produce a new type that returns True when compared to hashables, except in cases where they are None?

Extending that, could you then do expressions like 'int + str' -- which would produce a new type that returns True when compared to ints or strings?

And even if so, would this be insane to do? I'm not planning on trying to implement it; it's just a fleeting thought I had today at work.
Sounds like union types, which are indeed a thing that type checkers can work with.

You may want to have a look at mypy, which is a Python variant with static type checking using annotations. I believe it supports union types. Guido recently proposed blessing it's syntax for use by type checking linters.

http://www.mypy-lang.org
He/Him/His/Alex
God damn these electric sex pants!

User avatar
The Great Hippo
Swans ARE SHARP
Posts: 7368
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

Re: Coding: Fleeting Thoughts

Postby The Great Hippo » Sun Aug 31, 2014 8:17 am UTC

Ah, thanks! Yeah, I see that they support a Union object to unify types in an annotations. I also like their 'Undefined' object, which lets you type 'x = Undefined(str)', then raises an error if you 1) Use x in any expression before defining x explicitly, and 2) define x as anything besides a string. No way to apparently exclude a type from another type, though (IE, hashable - int), but I can't imagine that would be hard to implement.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Mon Sep 01, 2014 1:25 pm UTC

Yesterweek I was introduced to Python's doctest standard module. I love it.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
Xanthir
My HERO!!!
Posts: 5426
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: Coding: Fleeting Thoughts

Postby Xanthir » Tue Sep 02, 2014 6:04 am UTC

The Great Hippo wrote:Ah, thanks! Yeah, I see that they support a Union object to unify types in an annotations. I also like their 'Undefined' object, which lets you type 'x = Undefined(str)', then raises an error if you 1) Use x in any expression before defining x explicitly, and 2) define x as anything besides a string. No way to apparently exclude a type from another type, though (IE, hashable - int), but I can't imagine that would be hard to implement.

Subtractive types are indeed harder to implement than additive unions, but there are some clever ways around some of the problems. One the more recent issues of The Monad Reader had a nice essay and implementation of a system for doing subtractive types.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

User avatar
Diadem
Posts: 5654
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Fri Sep 05, 2014 4:01 pm UTC

So our code had a bug. Some of our tests were failing, but only sometimes, and only in the release build, not the debug one. The frequency of failure also seemed dependent on the setup of the pc used. In cases like that an accidentally uninitialized variable is a prime suspect. Finding it however is a different story. Both compiling and running our code takes a while, and the issue was buried somewhere deep inside the code spaghetti. I couldn't run the code in the debugger, and if I made too many changes, such as turning on logging, the bug disappeared altogether. So this was a rather frustrating week.

I found the problem though. So here's a fun question:

Code: Select all

double old, new;
old = new = some_unknown_function();
while (new >= old) {
  (...)
  new = some_unknown_function();
}

How often is the while-loop executed at least

Answer:
Spoiler:
Zero times, which happens if some_unknown_function() returns a NaN
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

User avatar
Moo
Oh man! I'm going to be so rebellious! I'm gonna...
Posts: 6441
Joined: Thu Aug 16, 2007 3:15 pm UTC
Location: Beyond the goblin city
Contact:

Re: Coding: Fleeting Thoughts

Postby Moo » Fri Sep 05, 2014 4:18 pm UTC

Silly weakly typed languages :P



Anyhoo. Now that I'm playing with Bootstrap, I am recognizing just how many sites are built using it. But simultaniously I'm developing this aversion to it already because I always hate fads and doing what all the "cool kids" are doing. My brain is weird.
Proverbs 9:7-8 wrote:Anyone who rebukes a mocker will get an insult in return. Anyone who corrects the wicked will get hurt. So don't bother correcting mockers; they will only hate you.
Hawknc wrote:FFT: I didn't realise Proverbs 9:7-8 was the first recorded instance of "haters gonna hate"

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Fri Sep 05, 2014 4:51 pm UTC

Moo wrote:Silly weakly typed languages :P

would consider ML one of the two most strongly-typed "languages" I "know". And yet:

Code: Select all

# let x= 5.0 /. 0.0 -. 5.0 /. 0.0;;
val x : float = nan
# x <= x;;
- : bool = false

(I can't test SML or Haskell handily.)

Aside: you can just use "nan" instead of computing it. But I didn't realize that until I already had written that.)

User avatar
Moo
Oh man! I'm going to be so rebellious! I'm gonna...
Posts: 6441
Joined: Thu Aug 16, 2007 3:15 pm UTC
Location: Beyond the goblin city
Contact:

Re: Coding: Fleeting Thoughts

Postby Moo » Fri Sep 05, 2014 4:58 pm UTC

Ah, apologies. It looked a lot like javascript at a quick glance and I am currently having a spat with javascript.

C# would throw an exception if anything evaluated to NaN and you tried to assign it to a double, I'm pretty sure, so you wouldn't have had so much debugging to do to find this problem (unless you were hiding exceptions, I guess). And I have had my fair share of NaN issues with javascript (due in part to my limited knowledge of it). I shouldn't have made assumptions.
Proverbs 9:7-8 wrote:Anyone who rebukes a mocker will get an insult in return. Anyone who corrects the wicked will get hurt. So don't bother correcting mockers; they will only hate you.
Hawknc wrote:FFT: I didn't realise Proverbs 9:7-8 was the first recorded instance of "haters gonna hate"

jareds
Posts: 436
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: Coding: Fleeting Thoughts

Postby jareds » Fri Sep 05, 2014 5:45 pm UTC

EvanED wrote:(I can't test SML or Haskell handily.)

SML:

Code: Select all

Standard ML of New Jersey v110.74 [built: Sat Oct  6 00:59:36 2012]
- val x = 1.0/0.0-1.0/0.0;
val x = nan : real
- x<=x;
val it = false : bool
SML does have the interesting feature that "real" is not an "equality type", so you can't use the normal = operator on them (the normal equality operator for SML). (This of course means that the equality operator is an actual equivalence relation.) The Real structure does have an == operator with IEEE equality. I.e.:

Code: Select all

- x=x;
stdIn:4.1-4.4 Error: operator and operand don't agree [equality type required]
  operator domain: ''Z * ''Z
  operand:         real * real
  in expression:
    x = x
- Real.==(x,x);
val it = false : bool

Haskell:

Code: Select all

GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
Prelude> let x = 1.0/0.0-1.0/0.0
Prelude> x<=x
False

Moo wrote:Ah, apologies. It looked a lot like javascript at a quick glance and I am currently having a spat with javascript.

C# would throw an exception if anything evaluated to NaN and you tried to assign it to a double, I'm pretty sure, so you wouldn't have had so much debugging to do to find this problem (unless you were hiding exceptions, I guess). And I have had my fair share of NaN issues with javascript (due in part to my limited knowledge of it). I shouldn't have made assumptions.

I don't know C#, but you are claiming that its double does not fully implement IEEE floating point (in that it allows, at most, signaling NaNs and not quiet NaNs (which are actually more normally used than signaling NaNs in practice)), which is very unlikely. NaN is not a JavaScript thing, but rather a thing from IEEE floating point that therefore now corresponds directly to the behavior of modern hardware floating-point implementations.

I do believe that JavaScript's particular dynamic typing rules compound the confusion by allowing you to get NaN when you are not even expecting a floating-point value, which is bad.

Nyktos
Posts: 138
Joined: Mon Mar 02, 2009 4:02 pm UTC

Re: Coding: Fleeting Thoughts

Postby Nyktos » Fri Sep 05, 2014 10:05 pm UTC

jareds wrote:I don't know C#, but you are claiming that its double does not fully implement IEEE floating point (in that it allows, at most, signaling NaNs and not quiet NaNs (which are actually more normally used than signaling NaNs in practice)), which is very unlikely. NaN is not a JavaScript thing, but rather a thing from IEEE floating point that therefore now corresponds directly to the behavior of modern hardware floating-point implementations.
A quick test suggests that C# indeed implements NaN as you'd expect.

Python, however, does raise an exception in this case.

Code: Select all

>>> 0.0 / 0.0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero

User avatar
Diadem
Posts: 5654
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Fri Sep 05, 2014 10:19 pm UTC

The above code was C++ actually. I'm a bit insulted that people would think I would abase myself enough to write javascript :)

The language behavior is not the problem anyway. NaN being unequal to itself is the correct IEEE behavior. It is just annoying (not that the alternatives are better. NaNs are just a necessary evil in general). And you can raise an exception, if you want, you can turn floating point exceptions on or off on modern processors. It's off in our code. That wasn't my decision, but I agree with it. Exceptions are nasty and annoying, and should never have been invented.
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Coding: Fleeting Thoughts

Postby jestingrabbit » Fri Sep 05, 2014 10:26 pm UTC

Diadem wrote:The above code was C++ actually. I'm a bit insulted that people would think I would abase myself enough to write javascript :)

The language behavior is not the problem anyway. NaN being unequal to itself is the correct IEEE behavior. It is just annoying (not that the alternatives are better. NaNs are just a necessary evil in general). And you can raise an exception, if you want, you can turn floating point exceptions on or off on modern processors. It's off in our code. That wasn't my decision, but I agree with it. Exceptions are nasty and annoying, and should never have been invented.


Still though, if you want to be sure that something executes once, you can use a do-while instead of a while. It more directly communicates that the block is intended to be executed at least once, and it accomplishes that no matter how the flag is evaluating.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Diadem
Posts: 5654
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Fri Sep 05, 2014 10:32 pm UTC

jestingrabbit wrote:
Diadem wrote:The above code was C++ actually. I'm a bit insulted that people would think I would abase myself enough to write javascript :)

The language behavior is not the problem anyway. NaN being unequal to itself is the correct IEEE behavior. It is just annoying (not that the alternatives are better. NaNs are just a necessary evil in general). And you can raise an exception, if you want, you can turn floating point exceptions on or off on modern processors. It's off in our code. That wasn't my decision, but I agree with it. Exceptions are nasty and annoying, and should never have been invented.


Still though, if you want to be sure that something executes once, you can use a do-while instead of a while. It more directly communicates that the block is intended to be executed at least once, and it accomplishes that no matter how the flag is evaluating.

It was a "for (x = 0;new >= old;)" actually. Which is absolutely horrible, but I didn't want to focus the discussion on that, so I sanitized the code somewhat.

The original author loves weird for loops. He uses many like "for (int i = n; i--;). Very annoying.
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Fri Sep 05, 2014 10:34 pm UTC

Diadem wrote:Exceptions are nasty and annoying...
Exceptions are nasty and annoying... but unfortunately not nearly as nasty and annoying as not having exceptions.

There's nothing I enjoy more than not being able to say foo(bar()) and not being able to actually initialize variables. Oh wait... "less." That's the word I meant. :-)

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Fri Sep 05, 2014 11:37 pm UTC

I hate calling a function, not knowing if it can fail or in what cases. Nothing like using a library where a useless exception is thrown 5 levels deep on the call stack.
Summum ius, summa iniuria.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Coding: Fleeting Thoughts

Postby jestingrabbit » Sat Sep 06, 2014 9:51 am UTC

Diadem wrote:It was a "for (x = 0;new >= old;)" actually.


*Backs slowly away from the codebase*.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
The Great Hippo
Swans ARE SHARP
Posts: 7368
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

Re: Coding: Fleeting Thoughts

Postby The Great Hippo » Sat Sep 06, 2014 5:08 pm UTC

A particular problem I'm trying to solve in Python 3.x: I'd like to make a special class that can be instantiated inside of another class (which wraps it), but no where else. Said special class has subclasses that can be instantiated anywhere, but the special class should never be instantiated outside of very specific circumstances.

Because it can be instantiated in a very limited circumstance, I can't use an abstract base class. One simple method might be to make a keyword argument required to instantiate these classes, but that seems inelegant (plus, I'd have to make sure all the classes that inherit from these classes override that).

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Sat Sep 06, 2014 5:23 pm UTC

Can't you just, you know, not instantiate the class where it doesn't belong?
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
The Great Hippo
Swans ARE SHARP
Posts: 7368
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

Re: Coding: Fleeting Thoughts

Postby The Great Hippo » Sat Sep 06, 2014 5:59 pm UTC

You, sir, name? wrote:Can't you just, you know, not instantiate the class where it doesn't belong?
Yeah, but I'd like it to raise an exception if someone forgets to not do that.

It's a messaging system, and I'm using classes to create a hierarchy (A 'MouseMove' message inherits from the MouseInput class, which inherits from the Input class, which inherits from the Message class -- so we can fire events on any Message, Input, MouseInput, or MouseMove message -- but you should never actually send an instance of any of these classes except for MouseMove, because the others are far too generic to be of any real use).

I suppose I could figure out some way to have the dispatcher raise an error if you try to send a message earmarked as 'not-for-actual-use'.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Sat Sep 06, 2014 6:15 pm UTC

You could always have a parameter to the constructor that needs to be set to some specific token value that indicates you shouldn't be instantiating this class, like "NeverInstantiateOutsideOfClassFoobar". :P
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 12 guests