Best Practice Question - Passing multiple variables between functions

def foo1(settings)
[
    alpha,
    beta,
    gamma,
    theta,
    rho,
    lambda,
    epsilon,
    phi,
    zeta
    ] = settings
end
def baz1 do
    alpha = some operation
    beta = some operation
    gamma = some operation
    theta = some operation
    rho = some operation
    lambda = some operation
    epsilon = some operation
    phi = some operation
    zeta = some operation

    settings = [
        alpha,
        beta,
        gamma,
        theta,
        rho,
        lambda,
        epsilon,
        phi,
        zeta
    ] 
    
    foo1(settings)
end

VS.

def foo2(
    alpha,
    beta,
    gamma,
    theta,
    rho,
    lambda,
    epsilon,
    phi,
    zeta
    ) do
    
end
def baz2 do
    alpha = some operation
    beta = some operation
    gamma = some operation
    theta = some operation
    rho = some operation
    lambda = some operation
    epsilon = some operation
    phi = some operation
    zet = some operation

    foo2(
        alpha,
        beta,
        gamma,
        theta,
        rho,
        lambda,
        epsilon,
        phi,
        zeta
        )

end

Which pattern conforms with best practices, foo1/baz1 or foo2/baz2? If both are acceptable best practice, in your experience, which pattern is more advantageous to use and why?

If I really had to have a function that has so many things to pass in, I would take the second approach.

Lists carry some semantics that most of us assume as given when encountering them in code:

  1. Their length is undefined
  2. Their elements are of the same (or at least very similar) type

Therefore using it as a wrapping container just to hide complexity of a function definition is an antipattern.

If you really wanted to, you’d probably choose a tuple as container, as the semantics it carries are better suited:

  1. It has a fixed length
  2. Each element has its own type and meaning in the context of the tuple

Though when you use that, you again just hide the complexity of the function definition and move the complexity to the documentation.

Therefore, just use as many arguments as you need.

Though of course, not more than you need. If you realise during development, that phi is actually unused and will never be used, remove it.

2 Likes

I’m with @NobbZ that a list is likely not the datatype to choose. But besides tuples I’d also suggest looking into using a struct. This is likely more efficient in the case of updating just a subset of the values on the struct (less copying), which is not shown in your examples, but at least in my experience often the case in real world application.

4 Likes

That’s sensible. Thank you for your recommendations. :slight_smile:

Very intriguing. Thank you for your suggestion.

Any particular reasons why structs are to be preferred over maps for this use or is it just a matter of personal preference?

They’re easier to document, easier to have default values for, and it’s easy to see what all of the possible keys are.

4 Likes