I dearly miss the year that I spent talking about shapes and math with elementary and middle school students through the lens of Madeup and 3D printing. Would that those days return! While I wait for the global health crisis to subside, I might as well fix a few bugs in Madeup—by reimplementing it without them.
There are a few significant changes in this new Madeup. In this update, I will focus on one: positional parameters are no longer a thing. In the old Madeup, you could generate a dowel with this code:
Positional parameters are ordered lists of raw data sent to a function. Here, the positional parameters are 10 and 45. These actual parameters are implicitly mapped to the formal parameters of
dowel merely by their order of appearance in the call. I think the implicitness of this serial mapping is unfriendly to learners. A first-time reader of code with positional parameters is unlikely to understand it. What do 10 and 45 mean?
The documentation reveals that the first parameter is
maxBend, which is used to smooth sharp bends, and the second parameter is
twist, which rotates the polygonal cross section of the dowel about its axis. The gulf between the documentation and the editor is not small. The folks who understand positional parameters are the ones who have memorized the API. I want Madeup to be welcoming to those who haven’t.
In the new Madeup, you generate a dowel with named parameters:
The names are not optional. This reflects my new philosophy of programming: everything should be named.
Named parameters have benefits. They hint at the meaning of the formerly magic numbers. They can appear in any order, freeing the programmer from having to memorize extraneous details and freeing me from having to lock down the interface of builtin functions in the name of backward compatibility.
Named parameters also have a cost: they make the code longer and more verbose. I want to mitigate this cost, and following are a few of my plans to do so.
Consider the following program, which renders an L-shaped bracket.
Often I build 3D objects in the XY plane, and explicitly setting
z = 0 in the
moveto commands as I do here feels like a waste of time. Therefore I have made a decree. When a parameter has a reasonable default value, that default may be defined in the function definition. A programmer who wishes to employ that default value can omit the parameter from the call. In the following version of the code, we employ the defaults for
Consider the following program, which renders a row of cubes.
I think that
x = x is silly. Therefore I have made a decree. When a variable is passed as an actual parameter to a formal parameter of the same name, the assignment syntax for the parameter is not necessary. It can be written in shorthand as just the shared name. In the following version of the code, we have variables for
z and our
moveto call is much more concise.
We can take that shorthand a step further. If a variable with the same name as a formal parameter is in scope, then we can automatically transfer it along as a parameter—leaving it out of the function call altogether. These are called implicit parameters.
In this program, we implicitly pass
y to three
Implicit parameters allow us to factor out repetitive code. We set the shared
y parameter just once, leaving the
moveto calls uncluttered. We clearly see the differences between the calls: the varying
Suppose we have a position
p. We could render a sphere centered on this position with the following program.
The syntax here feels clumsy. I have to break down the list manually and spread it across the
z parameters. How shall we fix this? I could just have
moveto accept a list instead of three separate parameters, but I don’t want lists to be a prerequisite for building interesting shapes in Madeup. I could add another version of
moveto that accepted a list. Or I could give the existing
moveto an alternative
position parameter. Neither of these feels general enough. Therefore I have decreed that we need a splatting syntax for assigning multiple parameters at once from a list.
In this version of the program, we automatically decompose
p and pass its elements as values for