DEV Community

BibleClinger
BibleClinger

Posted on

1 1

Does MiniScript Need Variadic Functions?

A relatively common question asked at the MiniScript Discord is about variadic functions and why MiniScript lacks this feature.

Variadic Functions

First of all, what even is a "variadic function?" This is a function that takes a variable number of arguments.

For those familiar with C, the standard library function printf is such a function. To a C newbie's surprise, the actual function signature of C's printf is:

int printf ( const char * format, ... );

The ellipsis (the three dots) represents an unknown number of arguments. You can print as many ints, floats, chars, or char *'s, etc. that you would like in one function call.

Why not in MiniScript?

What new MiniScript programmers are usually looking for is a way to process an unknown number of elements. They think variadic functions are the way of solving this, but let's reconsider such problems.

Let's say you have a function that needs to accept an X and a Y coordinate, and then optionally process an unknown amount of numbers. One solution is to write a function with three arguments. The first two can be Numbers, and the last one can be a list. For example:

f = function(x, y, arg_list)
    // arg_list is expected to be a list
end function
Enter fullscreen mode Exit fullscreen mode

This function f can be called like this, assuming the list is already known:

f 102, 215, [5, 6, 10, 4, 2, 6]
Enter fullscreen mode Exit fullscreen mode

You can create the list directly inside the function call as shown above. Such a list can also be obtained at runtime. The simplicity is here. Not only don't we need to fiddle with an unknown amount of arguments, but the question should be -- why would we want to do so when given the above?

Maps as Arguments

Let's say you're building a complicated GUI toolkit for Mini Micro. You want other programmers to be able to use it, so you are making an API. You want a complex function called createWindow that takes in all sorts of properties, such as the width, height, and title of the window in question. Do we need a whole bunch of arguments to accomplish this? Not necessarily. We can use a Map instead to hold our properties.

Although there are probably much better ways of implementing the guts of the function, this is one incredibly straightforward way to write it:

createWindow = function(properties)
    if properties.hasIndex("title") then
        // set title
    end if
    if properties.hasIndex("width") then
        // set width
    end if
    if properties.hasIndex("height") then
        // set height
    end if
end function
Enter fullscreen mode Exit fullscreen mode

This can be called like this by users of your API:

createWindow { "title":"My Window", "width":320, "height":240 }
Enter fullscreen mode Exit fullscreen mode

The map can be hardcoded or built dynamically at runtime. Easy!

Benefits of Maps as Arguments

Now imagine there is a team using your GUI toolkit, and they report back to you that while they love the API, they would like the ability to change the color of the title bar. You agree that this is a needed feature. You can add this in fairly easily, and the function becomes this:

createWindow = function(properties)
    if properties.hasIndex("title") then
        // set title
    end if
    if properties.hasIndex("width") then
        // set width
    end if
    if properties.hasIndex("height") then
        // set height
    end if
    if properties.hasIndex("title_color") then
        // set title bar color
    end if
end function
Enter fullscreen mode Exit fullscreen mode

Here's a serious benefit of this design: your function signature didn't change. It still expects the same number of arguments. This means all of the legacy code already written will still work exactly as before! Interestingly enough, new code for the new version of your toolkit should still run on the old version simply because your function ignores entries in the map that it doesn't recognize! If every property needed its own argument, this could be a nightmare for both you as the developer of this GUI toolkit as well as the users of your API.

Conclusion

Now obviously these examples are contrived, and may not be the best way of implementing GUI code, but the design pattern of using lists and maps in place of variadic arguments has been demonstrated to be incredibly useful within the design philosophy of MiniScript.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (1)

Collapse
 
joestrout profile image
JoeStrout

Great discussion! Your point about the forwards- and backwards- compatibility of the "parameter map" pattern is especially insightful. And on top of that, it makes the calling code clearer and more readable — it can be hard to know what's what if you're passing half a dozen or more arguments to a function call (something that drawImage is guilty of causing). But when they're named right where you're building the map to pass in, it's obvious!

A deeper design point is that we try to keep MiniScript simple by only adding features if they are really needed, i.e. if some existing feature can't do the job. For example, if we didn't have lists or maps, no simple use of string and number variables could adequately replace them. But here you've beautifully laid out how some sort of "varargs" feature isn't really needed, because a list or map can accomplish the same thing. So that's one less thing MiniScript needs to support, and one less thing users need to learn!

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

If you found this post helpful, please leave a ❤️ or a friendly comment below!

Okay