Parameters
May 2, 2022 ยท View on GitHub
Parameters define the expected inputs of some declaration that can be called. We refer to such declarations as callables. We distinguish between
- required parameters, which must always be passed,
- optional parameters, which use a default value if no value is passed explicitly, and
- variadic parameters, which can accept zero or more values.
Required Parameters
Required parameters must always be passed when the declaration is called. Let us look at an example:
requiredParameter: Int
Here are the pieces of syntax:
- The name of the parameter (here
requiredParameter). This can be any combination of upper- and lowercase letters, underscores, and numbers, as long as it does not start with a number. However, we suggest to uselowerCamelCasefor the names of parameters. - A colon.
- The type of the parameter (here
Int).
Optional Parameters
Optional parameters have a default value and, thus, need not be passed as an argument unless the default value does not fit. Here is an example:
optionalParameter: Int = 1
These are the syntactic elements:
- The name of the parameter (here
optionalParameter). This can be any combination of upper- and lowercase letters, underscores, and numbers, as long as it does not start with a number. However, we suggest to uselowerCamelCasefor the names of parameters. - A colon.
- The type of the parameter (here
Int). - An equals sign.
- The default value of the parameter (here
1). This must be a constant expression, i.e. something that can be evaluated by the compiler. Particularly calls usually do not fulfill this requirement.
Variadic Parameters
Variadic parameters can consume arbitrarily many arguments. Here is an example:
vararg variadicParameter: Int
Let us break down the syntax:
- The keyword
vararg - The name of the parameter (here
variadicParameter). This can be any combination of upper- and lowercase letters, underscores, and numbers, as long as it does not start with a number. However, we suggest to uselowerCamelCasefor the names of parameters. - A colon.
- The type of the parameter (here
Int).
Complete Example
Let us now look at a full example of a step called doSomething with one required parameter and one optional parameter:
step doSomething(requiredParameter: Int, optionalParameter: Boolean = false) {
// ...
}
The interesting part is the list of parameters, which uses the following syntactic elements:
- An opening parenthesis.
- A list of parameters, the syntax is as described above. They are separated by commas. A trailing commas is permitted.
- A closing parenthesis.
Restrictions
Several restrictions apply to the order of parameters and to combinations of the various categories of parameters:
- After an optional parameter all parameters must be optional.
- A single variadic parameter can be added at the end of the parameter list.
- Implied by this: A callable cannot have both optional parameters and variadic parameters.
Corresponding Python Code
Note: This section is only relevant if you are interested in the stub language.
Parameters must be ordered the same way in Python as they are in Simple-ML. Moreover, for each parameter the following elements must match:
- Name
- Type
- Kind (required vs. optional vs. variadic)
- Default value for optional parameters
Let's look at these elements in turn.
Matching Name
By default, parameter names in Simple-ML must be identical to their names in Python. If this is not desired, for example due to clashing name conventions in Simple-ML and Python, the @PythonName annotation can be used to link a Simple-ML parameter to a Python parameter with a different name. Here is an example:
# Python code
def accuracy(x_pred: Dataset, x_test: Dataset) -> float:
pass
// Simple-ML code
fun accuracy(
@PythonName("x_pred") xPred: Dataset,
@PythonName("x_test") xTest: Dataset
) -> accuracy: Float
In this case, the Simple-ML parameters xPred and xTest refer to the Python parameters x_pred and x_test respectively.
Matching Type
The Simple-ML type of a parameter should capture the legal values of this parameter accurately. Ideally, the Python parameter should also have a matching type hint.
Matching Kind
Parameters kinds must match on the Simple-ML and Python sides as well. Concretely, this means:
- All required parameters in Simple-ML must be required in Python.
- All optional parameters in Simple-ML must be optional in Python.
- All variadic parameters in Simple-ML must be variadic in Python (
*args).
Moreover, it must be possible to pass
- required parameters by position,
- optional parameters by name,
- variadic parameters by position.
These rules allow us to restrict required parameters to positional-only or optional parameters to keyword-only. We can also keep both unrestricted.
The following three examples show valid pairs of Python and Simple-ML programs.
Required Parameter
# Python code
def required(a: int):
pass
// Simple-ML code
fun required(a: Int)
Optional Parameter
# Python code
def optional(a: int = 1):
pass
// Simple-ML code
fun optional(a: Int = 1)
Variadic Parameter
# Python code
def variadic(*a: int):
pass
// Simple-ML code
fun variadic(vararg a: Int)
Matching Default Value
Most commonly, default values in Python are literals, since default values are only evaluated once in Python rather than every time the function is called. The following table shows how Simple-ML literals and Python literals correspond:
| Simple-ML Literal | Python Literal |
|---|---|
1 (int) | 1 |
1.0 (float) | 1.0 |
"hello" (string) | "hello" or 'hello' |
false (boolean) | False |
true (boolean) | True |
null (null) | None |