Not really.

Tons of well-written functions have many more potential code paths than that. And they're easy to reason about because the parameters don't interact much.

Just think of plotting libraries with a ton of optional parameters for showing/hiding axes, ticks, labels, gridlines, legend, etc.

Yes but this is about the difference between:

  engage_turbo_encabulator(True, False, True, False, True, False, True, False)
 
and:

  engage_turbo_encabulator(
    enable_hydrocoptic=True,
    allow_girdlespring=False,
    activate_marzelvanes=True,
    sync_trunnions=False,
    stabilize_panametric=True,
    lock_detractors=False,
    invert_logarithms=True,
    suppress_lunar_wane=False
  )
  
The latter is how you should use such a function if you can't change it (and if your language allows it).

If this was my function I would probably make the parameters atrributes of an TurboEncabulator class and add some setter methods that can be chained, e.g. Rust-style:

  encabulator = (
    TurboEncabulator.new()
    .enable_hydrocoptic(True)
    .allow_girdlespring(False)
    .enable_marzelvane_activation(True)
    .enable _trunnion_syncing(False)
    .enable_param_stabilization(True)
    .enable_detractor_locking(False)
    .enable_logarithm_inversion(True)
    .enable_lunar_wane_supression(False)
    .build()
  )

Did you mean to reply to a different comment?

I absolutely agree named arguments are the way to go. But my comment wasn't in the thread about that.

(follow-up) BTW thank you for introducing me to turbo encabulators -- I did not know about them and they seem exceptionally useful! TIL...

https://en.wikipedia.org/wiki/Turbo_encabulator