Changing the “main” function

Maryam Ziyad
Ballerina Swan Lake Tech Blog

--

“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.

The traditional main function

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.

  1. 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 Ballerina main 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!

--

--