For instance, to declare a function add which add up two numbers:
The name of the function is add
There will be 2 arguments, both of them are Num type
The output type will be Num
The body part should define the process of addition
def add(x: Num, y: Num): Num do
x + y
end
Declaration Syntax
"Do-Block" Declaration
If the body of the function is a do block, you should always end it with the keyword end. On the other hand, the return value of the function will be evaluated by the last line in the body of the function, which means that the example:
Will be compiled into:
"One-Liner Arrow" Declaration
Similar to conditional expressions in Wyrd, if the body of the function is simple enough to express the evaluation result using only one line, you can choose to use the arrow syntax:
Functions Without Arguments
Sometimes function can declared without input arguments. In this case you don't need to also provide the parentheses, only the output type is needed after the name of the function:
TODO: There's a bug where if you provide with empty parentheses, the compilation will stuck, check out the issue.
Returned Result Type Checking
If the function declared result aren't matched with the definition of the function, it will raise an error:
Function Overriding
Function Redeclaration is Prohibited
If a function (along with its argument types and output types) is declared twice, Wyrd will raise the error:
By inspecting the error message, we can actually instead of declaring the function, we can explicitly overriding it.
Overriding Function
To override a function, we just simply add the override keyword before the def keyword:
The reason why Wyrd demand this approach is because, not only to express that the function actually has predeclared, but also developer choose to intentionally overriding it.
Before and After Overrode Function
Wyrd will make sure that only after function overriding, the invoked function will be the overrode version.
Allows Change of Output Types
One benefit of overriding a function might be the ability of changing the output type of the function:
However, you might also need to be cautious about this kind of practice since the change of output type might result modified behavior of program.
Function Overloading
Identical Function Name with Different Arguments Pattern
Similar to function overriding, instead we can declare functions of same name with different input arguments type pattern.
This technique is called function overloading. In this case, function can have more possible ways to be invoked:
Overriding Overloaded Function
You can also override the overloaded function, the rule is the same as in overriding normal functions. Whenever there is an overloaded version of the function already been declared, to override it, you should add override keyword before the def keyword:
def example(x: Num, y: Num): Num do
Num foo = x + y
foo * 2
end
function example(x, y) {
const foo = x + y;
return foo * 2;
}
def add(x: Num, y: Num): Num => x + y
def greet: Str => "Hello world!"
# or
def greet: Str do
"Hello world!"
end
def shouldReturnNumber: Num => "123"
Return type of function `shouldReturnNumber` should be `Num`, instead got: `Str`
def add(x: Num, y: Num): Num => x + y
# Declare function `add` with same input arguments
def add(a: Num, b: Num): Num => a + b
ParserError: Overriding function `add` with existing input pattern `Num.Num`; to override the function, address it with `override` keyword before `def` token
def add(x: Num, y: Num): Num => x + y
# Declare function `add` with same input arguments
override def add(a: Num, b: Num): Num => a + b
def greet(msg: Str): Str => msg
# Invokes the original version of the function
greet("I'm Max!")
# => I'm Max!
override def greet(msg: Str): Str do
"Hello! ".concat(msg)
end
# Invokes the overrode version of the function
greet("I'm Max!")
# Hello! I'm Max!
# Original Function
def add(x: Num, y: Num): Num do
x + y
end
# Override Function
override def add(x: Num, y: Num): Str do
(x + y).toStr()
end
# Input Pattern: Num.Num => Num
def add(x: Num, y: Num): Num do
x + y
end
# Input Pattern Num.Num.Num => Num
def add(x: Num, y: Num, z: Num): Num do
x + y + z
end
# Invokes the Num.Num => Num version
add(123, 456)
# Invokes the Num.Num.Num => Num version
add(123, 456, 789)
def greet(msg: Str): Str => msg
# Overloaded Version
def greet(prefix: Str, msg: Str): Str do
prefix.concat(", ").concat(msg)
end
# Override the overloaded version
override def greet(prefix: Str, msg: Str): Str do
prefix.concat("! ").concat(msg)
end