1. 14
  1.  

  2. 11

    LG makes a “Powerwall” style home battery. It has an annoying safety mechanism to turn itself off if it hasn’t received a keep alive message via a CAN BUS protocol.

    I thought this would be super simple: send a packet using an Arduino and a CAN BUS transceiver. I wrote up the code, took 10 minutes, got the connections in place and… NOTHING. No packets being received.

    I put a bunch of debug statements in via serial and tried changing the cables. Still nothing. Eventually I cut up my cables and plugged them into a logic analyser and learner how to use Sigrok. Yep the messages are there, why can’t the Arduino see it??

    Turns out the library assumed I was using an 16Mhz crystal in my circuit. Mine had an 8Mhz crystal…

    Code change:

    - MCP2515(10);
    + MCP2515(10, MCP_8MHZ);
    

    Urgh.

    1. 8

      To me this sounds more like an argument against unlabelled function arguments.

      The “boolean parameter tarpit” example that reads like this:

      doTask(task1, 200s, false, true, true);

      …would look perfectly readable if written like this:

      doTask(task: task1, timeout: 200s, detach: false, captureStdout: true, captureStderr: true);

      Leave any of the arguments out, and it is still perfectly readable since each argument is written out instead of based on arcane ordering.

      Likewise, the square example makes the case that default arguments are what makes print_square('*') print a 42-by-42 square of + characters when in fact the problem is that the arguments to print_square are based only on position, in combination with the fact that somehow a character is accepted where the function expected an integer.

      1. 3

        I think the article is poorly titled. The correct title should be ‘Default function arguments compose poorly with other C++ language features’. The relevant features are:

        • Function overloading
        • Anonymous parameters
        • Syntactically expensive value types
        • Implicit casting

        If you were adding default function arguments to C++ now (assuming the language didn’t have them already), you’d make them a shorthand way of writing overloads such that:

        void foo(int a, int b=12);
        

        Would be shorthand for:

        void foo(int a, int b);
        void foo(int a) { foo(a, 12); }
        

        That would eliminate the complexity with respect to overloads (which become horrendous when composed with templated functions). It would also make it possible to

        Repeated bool arguments are not great even without the overloading. LLVM is gradually moving to avoiding bool arguments entirely, but that requires defining an enum for each argument and that’s then annoying on the caller because they have to specify the enum name as well as the value.