News for hackers. Stuff that matters.
Re:Sentimental Versioning by brabel on Monday October 12, 2020 @07:14AM (#24753263)
I've seen bugs caused by a tool not knowing that version `1.12` < `1.20` :/ so yeah, some professional developers don't know that.
Re:Sentimental Versioning by Joker_vD on Monday October 12, 2020 @08:14AM (#24753602)
Windows 95 reported it's version as 3.95 instead of 4.00 for this exact reason [0]. Apparently, writing lexicographical ordering on tuples is surprisingly unintuitive:

    bool operator<=(version lhs, version rhs) {
        return (lhs.Major <= rhs.Major) || (lhs.Minor <= rhs.Minor) || (lhs.Patch <= rhs.Patch);
    }
looks correct for anyone who have never wrote such comparison before, but of course it's wrong. The correct one is

    bool operator<=(version lhs, version rhs) {
        return (lhs.Major < rhs.Major)
               || ((lhs.Major == rhs.Major) && ((lhs.Minor < rhs.Minor)
                   || ((lhs.Minor == rhs.Minor) && (lhs.Patch <= rhs.Patch))));
    }
[0] https://devblogs.microsoft.com/oldnewthing/20040213-00/?p=40...
Re:Sentimental Versioning by Lvl999Noob on Monday October 12, 2020 @10:11AM (#24754483)
Your second code is wrong. For lhs = "4.3.7" and rhs = "3.3.7", your code will give true. It should be false.
Re:Sentimental Versioning by Joker_vD on Monday October 12, 2020 @10:30AM (#24754675)
Uh, no it won't?

    cat >test_ver.cpp << EOF
    #include <cstdio>
    
    struct version {
        int Major;
        int Minor;
        int Patch;
    
        version(int major, int minor, int patch)
            : Major(major)
            , Minor(minor)
            , Patch(patch)
        { }
    };
    
    bool operator<=(version lhs, version rhs) {
        return (lhs.Major < rhs.Major)
            || ((lhs.Major == rhs.Major) && ((lhs.Minor < rhs.Minor)
                    || ((lhs.Minor == rhs.Minor) && (lhs.Patch <= rhs.Patch))));
    }
    
    int main(int argc, char **argv) {
        version lhs(4, 3, 7);
        version rhs(3, 3, 7);
    
        printf("lhs <= rhs? %s\n", lhs <= rhs ? "true" : "false");
    }
    EOF

    g++ test_ver.cpp -o test_ver && ./test_ver
    
prints

    lhs <= rhs? false
Re:Sentimental Versioning by tsegers on Monday October 12, 2020 @11:17AM (#24755255)
No, it works. It's just non-obvious that it does due to the reliance on 4 levels of braces.

It is equivalent to the following:

    lhs.Major < rhs.Major
    or (lhs.Major == rhs.Major and lhs.Minor < rhs.Minor)
    or (lhs.Major == rhs.Major and lhs.Minor == rhs.Minor and lhs.Patch <= rhs.Patch)
Deduplicating (lhs.Major == rhs.Major) decreased readability enough to be confusing.
Re:Sentimental Versioning by Joker_vD on Monday October 12, 2020 @11:41AM (#24755562)
There is so many ways to write this comparison that after a couple of times you really wish there were something in the standard library to help you so that you could write e.g.

    bool operator<=(version lhs, version rhs) {
        return std::tie(lhs.Major, lhs.Minor, lhs.Patch) <= std::tie(rhs.Major, rhs.Minor, rhs.Patch);
    }
Wait, there is! And Python has something like this too, even more laconic: you don't need to write "std::tie", naked parentheses are enough.
Re:Sentimental Versioning by cpeterso on Monday October 12, 2020 @03:13PM (#24758266)
And Microsoft jumped from Windows 8.1 to 10 to avoid breaking applications they assume “first digit is 9 means Windows 9x”. And possibly to catch up with Mac OS X 10.x.