Skip to content

Use a config struct to make the implementation more functional #5

@countvajhula

Description

@countvajhula

At the moment, the cli forms make extensive use of unhygienic macros as well as mutation of module scope variables to track configuration changes. This is an artefact of the need to keep the configuration forms separate rather than unify them into one giant macro (which is what Racket's command-line already is). But it makes me a little suspicious just on principle that there could be cases where unexpected things may happen, in particular, in multithreaded settings. Obviously, if cases are encountered in practice that reveal such problems, they can be investigated then, so there's no need to jump the gun and fix vague hypothetical problems that may never arise. But at such a time, here are some possible alternatives to consider:

  • instead of module-level variables keeping track of configuration, we could define a single struct for this purpose
  • each form could simply result in an identifier (the form name) being assigned the result of the form
  • we could, prior to running the command, use another form like (config param ...) which accepts each individually named aspect of the configuration (e.g. the flags and constraints) and yields a named configuration object, an instance of the configuration struct type as output
  • define a new command form that takes a function specified using program and a configuration object, to yield the actual program that could be executed using run

Assessment:
This would make the implementation functional / immutable, but would still rely on unhygienic identifiers (which may be fine -- the only thing this could affect is composability rather than robustness), and not sure what this would mean for the parameters that get defined for each flag. After all, two distinct configuration objects could refer to the same parameters which are dynamic and stateful. But maybe that's OK too. Finally, such an implementation would be syntactically less lightweight (and backwards-incompatible), but potentially more flexible since it could make composability (see #3) easier by allowing independent definitions of composition for the programs and the configuration (e.g. "run program p3 composed from p1 and p2 (run consecutively), and parametrized by this configuration object that is composed from c1 and c2 using union composition / override composition"). It also avoids having to rely on submodules to be able to define commands with distinct or conflicting configurations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions