InnerAlien

InnerAlien

Hardware|Software

25 Jan 2026

Find the Number of Elements of a List

№4 · 99 Picat Problems
myLength(L) = myLength(L, 0).
myLength([], Len) = Len.
myLength([_|Xs], Len) = myLength(Xs, Len+1).

Explanation

This function counts the number of elements in a list. Unlike the previous problems that peeled off elements until reaching a stopping condition, this one introduces a new pattern: the accumulator.

Wrapper function (line 1):

myLength(L) = myLength(L, 0).
  • Takes a single argument (the list) and calls a two-argument version with 0 as the initial count
  • This gives callers a clean interface - they don't need to know about the internal accumulator

Base case (line 2):

myLength([], Len) = Len.
  • Pattern matches when the list is empty []
  • Returns the accumulated count Len
  • When we've consumed every element, the accumulator holds the final answer

Recursive case (line 3):

myLength([_|Xs], Len) = myLength(Xs, Len+1).
  • Uses the same [Head|Tail] destructuring as Problem 1
  • Ignores the head with _ - we only care that an element exists, not what it is
  • Recurses on the tail Xs with Len+1, incrementing the count for each element

Note that Picat has a built-in length/1 function, so in practice you'd write length(L). The point here is to understand how accumulator-based recursion works.

Complete Example

Here's the full runnable code:

main =>
  go_04.

go_04 =>
  A = [1,2,3,4,5],
  B = myLength(A),
  println(B).

myLength(L) = myLength(L, 0).
myLength([], Len) = Len.
myLength([_|Xs], Len) = myLength(Xs, Len+1).

How it works:

  • myLength(A) calls the wrapper, which starts the count at 0
  • Each recursive call strips one element and adds 1 to the accumulator
  • println(B) outputs 5 (the list has five elements)

Example Execution

With A = [1,2,3,4,5]:

myLength([1,2,3,4,5])
→ myLength([1,2,3,4,5], 0)    (wrapper adds initial accumulator)
→ myLength([2,3,4,5], 1)      (ignore 1, increment count)
→ myLength([3,4,5], 2)        (ignore 2, increment count)
→ myLength([4,5], 3)          (ignore 3, increment count)
→ myLength([5], 4)            (ignore 4, increment count)
→ myLength([], 5)             (ignore 5, increment count)
→ 5                           (base case: empty list, return accumulator)

The accumulator carries the running total forward through each recursive call. When the list is empty, the accumulator holds the final count.

Takeaways

  1. Accumulator pattern: A wrapper function initializes an extra parameter that carries state through the recursion. The wrapper gives callers a clean single-argument interface while the helper does the real work with the extra parameter.
  2. Empty list as base case: Previous problems stopped at one or two elements. Here the base case is [] because we need to count every element, including the last one.
  3. Tail recursion: The recursive call myLength(Xs, Len+1) is the last operation - there's nothing left to do after it returns. This is called tail recursion, and Picat can optimize it to avoid growing the call stack.