Changing the “main” function
“main” functions that accept a single string array or string rest parameter, are the named entry points to programs we are all quite used to.
With the latest release of Ballerina (0.982.0), we’ve introduced several changes to the traditional main
function!
Before we explore the changes introduced to the main
function, let’s look at some common ways in which one would implement a main
function.
Please note that these examples are quite basic and are just for demonstration.
- Not making use of the arguments
This is the case where we would not use args
, and the fact that we have to declare the string rest parameter despite not using it itself becomes an annoyance!
2. Checking for specific values at specific positions and/or attempting conversion from string to other types before further use
This is the case where we would expect the user to specify non-string arguments such as ints, floats, booleans, etc. but since what we get is a string array we would have to explicitly try converting/parsing them to values of the expected types.
One might also check for a particular value at a particular position, like the example does in line 5, checking if the 3rd argument specified is equal to “add”.
3. Using default values if an argument is not specified
This is where we would expect input from the user, but if the user has not specified an argument, we would use a default value instead.
Looking at these examples, it is clear that the single string array or rest parameter may not always be developer friendly, introducing multiple requirements such as:
- having to specify the parameter even when not used
- having to explicitly handle insufficient or too many arguments
- having to explicitly handle/propagate incompatible values, where the value doesn’t match the type expected
- having to explicitly set default values, when the user does not specify certain arguments
This could also leave some room for unnecessary errors and introduce restrictions, with the checks for particular values at particular positions.
Enter Ballerina!
With the latest changes introduced to the main
function, Ballerina minimizes the argument processing required to be implemented with the main
function, allowing usage of its powerful type system, similar to any ordinary function.
With these changes,
- the
main
function could have zero or more parameters. Yes, you don’t have to declare the string rest param/array if you’re not planning on using it. The following is now a valid Ballerinamain
function:
- the
main
function would be “data binding” — the parameters could be of any supported type (e.g., int, float, boolean, json, xml, arrays, maps, records, etc.) and could be a combination of required parameters, defaultable parameters and/or a single rest parameter - the
main
function could either return an int or have no returns
These changes address pretty much all the issues identified with the traditional main
function.
Now, the following main
function with three parameters (two ints and a single string) is a valid Ballerina main
function:
Note how the function definition itself defines default values. If no value is specified for operation
as an argument (in the format -operation=myOperation
) , the default value addition
would be assigned.
The function definition also indicates the expected types, removing the requirement to explicitly handle conversion/parsing. Ballerina does that for you, and fails prior to reaching the main
function if invalid (non-int) values are specified.
Moreover, since the expected argument count is now known beforehand, Ballerina would also handle insufficient or too many argument scenarios.
Given these changes, the following is also a valid main
function now:
Running this main
function (say is in a file name main_demo.bal
) with the following command:
$ ballerina run main_demo.bal http://localhost:9090/orderservice/place -epTimeoutMillis=120000
"{\"name\": \"Pizza\"}"
would result in an HTTP POST request
- being sent to “http://localhost:9090/orderservice/place/”
- with the JSON payload “{\”name\”: \”Pizza\”}”
- via the client endpoint defined (with the timeout value set to 120000 milliseconds)
No More “Main”!
But, that’s not all!
Ballerina also allows you to run any public function, instead of just the main
function.
$ ballerina run arithmetic_ops 4 5
While the above command runs the main
function and or services in the arithmetic_ops
package, the following command runs the add
function in the arithmetic_ops
package instead (and starts services if available).
$ ballerina run arithmetic_ops:add 4 5
Do check out the official example Functions as Entry Points which also demonstrates the capabilities introduced with these changes.
Thoughts?
We love feedback, and would appreciate your thoughts on these changes. Do let us know what you like or don’t like about them!
Feel free to leave a comment or join in on the discussion in the ballerina-dev Google Group. :)
Thank you!