Skip to content

Discussion around optional arguments to functions #60

Open
@hinshun

Description

As we develop common modules in: https://github.com/openllb/modules

We want to expose as many knobs to ensure that it is reusable. However, at the same time we want to limit the number of required arguments so that you can invoke the module without being exposed to the full spectrum of options.

There's two approaches I've been thinking about:

  1. Optional arguments
  2. Option signatures

Optional arguments

Starting with some implementations from some languages:

# Named arguments in ruby
def test(var1: "var1", var2: "var2", var3: "var3")
  puts "#{var1} #{var2} #{var3}"
end

test(var3:"var3-new", var1: 1111, var2: 2222) # ok => 1111 2222 var3-new
# Default values for arguments in ruby
def test(var1="var1", var2="var2", var3="var3")
  puts "#{var1} #{var2} #{var3}"
end

test(var3:"var3-new", var1: 1111, var2: 2222) # ok but ... {:var3=>"var3-new", :var1=>1111, :var2=>2222} var2 var3

or python optional arguments

def info(object, spacing=10, collapse=1):
  # ...

info(odbchelper)
info(odbchelper, 12)
info(odbchelper, collapse=0)
info(spacing=15, object=odbchelper)

The key features extracted from the examples is:

  • Positional arguments strictly before named arguments
  • Named arguments can be in any order
  • Values can be assigned to arguments even if they don't have default values set

In HLB, this may look like:

fs foo(string first) {
    # ...
}

fs bar(string first, string second="world") {
    # ...
}

group default() {
    foo "hello"
    foo first="hello"
    bar "hello"
    bar second="world" first="hello"
}

Option signatures

Currently, builtin functions like run can take options that add optional behavior to a function. And you can define functions that wrap these builtin options too:

option::run commonOptions() {
    env "key" "value"
    dir "/src"
}

fs default() {
    image "alpine"
    run "echo foo" with commonOptions
}

User defined functions cannot have options, which makes for a odd experience. Here's some explorations into how we can make this work:

Idea 1

fs foo(string requiredArg) {
    image baseImage="alpine:3.9"
}

fs default() {
    foo "hello" with option {
        baseImage "alpine:3.9"
    }
}

Idea 2

# Looking awful like optional arguments
fs foo(string requiredArg) optional (string baseImage="alpine:3.9") {
    image baseImage
}

fs default() {
    foo "hello" with option {
        baseImage "alpine:3.9"
    }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    designDesign for a feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions