A primary goal of the scripting work is that it should be easy to do easy things. You shouldn’t have to specify all the options if you just want to play a sound or show a picture, but you should still be able to get at them when you need
For the case of a sound effect, all of the following data may be specified:
Wav file – URI to a .wav file with audio samples.
Volume – Scale factor for the wav samples.
Position – 3D point for HRTF spatialized audio processing.
Looping – Flag to cause the wav file to loop continuously.
Name – An identifier to allow the parameters on a playing sound to be updated later.
Time – Absolute time for the sound to start, necessary for synced background audio in drop-in multiplayer servers and glitch free transitioning between wav files.
There are four broad strategies for exposing all that.
Multiple functions for different sets of parameters:
(+sound-positioned Wav-string position-vec3)
(+named-sound wav-string position-vec3 sound-name)
(+sound-update sound-name new-position-vec3)
This has a combinatorial explosion problem.
Optional parameter count with implicit type by position, C++ style:
(+sound wav-string position-vec3 name-int volume-float looping-bool time-float)
Need to define special values for parameters that are essentially skipped – POSITION_NONE, NAME_NONE, etc, since it is possible to want to set later values without all the preceding ones. Not very self-documenting, and not feasible for
large numbers of options like GPU state.
Keyword delimited parameters, command line parsing style:
(+sound ‘wav wav-string ‘position position-vec3 ‘name name-int ‘volume volume-float ‘looping looping-bool ‘time time-float)
A typo in an option symbol name will not be detected at compile time if done as a function, but I guess that is a good argument for a macro.
(+sound (opt-wav wav-string) (opt-position position-vec3) (opt-name name-int) (opt-volume volume-float) (opt-looping looping-bool) (opt-time time-float))
Simple to do transformations or validation on the inputs, but the most verbose.
Bad option names will be detected at compile time, but you could still compile, say, graphics options into a sound command, which would have been detected with the keyword delimited parameters.
In some cases, parameters can be inferred by type. For sounds, a parameter that is a string is the wav, a float is the volume, a bool is looping, a vec3 is position, an int is name. That is sheer luck – other commands would very likely
have multiple parameters with common types, and even here there would be an ambiguity with time. Still, it would be possible to go type-system-happy and explicitly have types for everything. I suppose that would syntactically degenerate to option functions.
It is tempting to use flags that are just signaled by their presence – just add ‘looping instead of ‘looping #t or (looping #t), but that can be awkward when the state of a flag is programmatically evaluated.
Currently I am using a hybrid form, where the first parameter is an implicit type (and second parameter for gfx commands), and all following parameters are evaluated and appended as options.