E11062: call has 4+ positional arguments - use named arguments for clarity

Category: E11xxx Code quality and IR analysis · Reported in phase: PRE_IR_CHECKS · Classification: MANY_ARGUMENTS_REQUIRE_NAMES · All error codes

What went wrong

A call has 4 or more positional arguments. Beyond 3 arguments, even humans must look up the function signature to understand which argument is which.

Named arguments are the MINIMUM fix for this error, not necessarily the best one. A long positional list is often a symptom of a deeper structural problem, and naming the arguments documents that problem without removing it. Work the resolution ladder in [ACTION] before settling for naming.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 817 (Why does EK9 require named arguments for 4+ parameters?)

Rationale

Fowler identifies "Long Parameter List" as a code smell starting at 3-4 parameters. Miller's cognitive limit research (7 +/- 2) bounds the number of items humans track simultaneously. 4 positional arguments is the point where ambiguity becomes systematic - the 3rd and 4th arguments are routinely confused.

For AI code analysis, every positional argument beyond 2 is a semantic gap requiring cross-file reasoning. Named arguments make call sites self-documenting - but self-documenting a list that should not exist is a weaker outcome than removing the list. Fowler's "Long Parameter List" entry points at Introduce Parameter Object, Preserve Whole Object, and Replace Parameter with Query as the structural fixes; naming is the fallback when none of those apply.

How to fix it

Named arguments clear this error and make the call self-documenting - but work DOWN this ladder first and stop at the FIRST rung that applies. Each rung is a question to answer, not a suggestion to skim.

Rungs 1-4 change the SHAPE of the call. Whatever shape you land on must still satisfy this error: if the rewritten call STILL passes 4+ arguments positionally - including into a record constructor you introduced at rung 1 - name them as rung 5 shows. Rung 5 is both the fallback when no deeper fix applies AND the finishing step for the deeper fixes.

  1. IS THIS GROUP A DATA CLUMP? If E11053 (data clump detected) ALSO fired for this parameter group in this same compilation, or the same group of parameters travels together into other callables, the long list is a symptom - extract a record and pass that. Extracting the record resolves E11053. It does NOT remove the arguments
  • they MOVE into the record's own construction, which is itself a 4+ argument call. Write that construction with named arguments or this error simply fires at its new home. The complete fix is this rung plus rung 5 applied to the construction site: 'formatAddress(street, city, state, zipCode)' becomes 'formatAddress(address)', taking an Address, and the Address is built as 'Address(street: "123 Main St", city: "Springfield", state: "IL", zipCode: "62704")'.
  1. DOES THE CALLER ALREADY HOLD THESE VALUES ON ONE OBJECT? If the arguments are fields unpacked from an object the caller already has in hand, pass the whole object instead (Preserve Whole Object): 'render(bounds)' rather than 'render(p.x, p.y, p.width, p.height)'.
  2. CAN AN ARGUMENT BE DERIVED RATHER THAN PASSED? If a parameter can be computed from the others, or reached by the callee itself, drop it from the signature (Replace Parameter with Query).
  3. IS THE CALLABLE DOING TOO MUCH? 5+ parameters often signals multiple responsibilities. If the parameters fall into groups used by different parts of the body, split the callable so each part takes only what it needs.
  4. NONE OF THE ABOVE - NAME THE ARGUMENTS. If the parameters are cohesive, all genuinely needed, and this group appears nowhere else, naming is the correct and COMPLETE fix. Do not invent a single-use record just to shorten the call - that is speculative generality, itself a smell. The [EXAMPLE] section below shows 'scheduleJob' called with four positional arguments, then with each one named.

EK9 requires all-or-nothing naming (E06240), so when you do name arguments every argument in the call must be named.

See also

  • E11053: data clump detected (if it co-fired, work rung 1 - extract a record - AND then name the arguments at the construction site)
  • E11061: 2+ Boolean literals require names
  • E06240: either all parameters named or none
  • E06250: named parameters must match arguments

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E11062: call has 4+ positional arguments - use named arguments for clarity

#!ek9
defines module error.e11062.bad

  defines function

    scheduleJob()
      ->
        jobName as String
        targetPath as String
        maxRetries as Integer
        intervalMinutes as Integer
      <- rtn as String: `${jobName} ${targetPath} ${maxRetries} ${intervalMinutes}`

    backup()
      <- rtn as String?
      rtn: scheduleJob("backup", "/data", 3, 60)

Fixed: Name the arguments

#!ek9
defines module error.e11062.good

  defines function

    scheduleJob()
      ->
        jobName as String
        targetPath as String
        maxRetries as Integer
        intervalMinutes as Integer
      <- rtn as String: `${jobName} ${targetPath} ${maxRetries} ${intervalMinutes}`

    backup()
      <- rtn as String?
      rtn: scheduleJob(jobName: "backup", targetPath: "/data", maxRetries: 3, intervalMinutes: 60)

Questions and answers

These Q&A entries show E11062 and its fix: