0

We want to create a DSL in Scala where you can declaratively list the ingredients that a product consist of. These ingredients can consist of for example "Create product a", "Create product b", "Send mail". The ingredients can depend on each other (e.g., "mail" can only be send once both product a and product b are created). The goal is that the definition of the ingredients does not include imperative information. The parser of the DSL needs to determine the correct execution order based on for example types.

So for example:

"CompletedProduct" consists of { Mail, ProductA, ProductB }

should result in ProductA and ProductB being executed first (preferably sequentially, but this is not necessary in a first step), and once this is finished Mail should be executed and a mail should be send.

What are possible ways to accomplish such a DSL that determined an execution plan?

1 Answers1

3

This isn't really specific to Scala DSLs. You have the same problem with the traditional Builder pattern, when you want a builder that needs to be given certain things. Instead of execution order it is then a dependency.

For example, you want a builder that can build either ProductA or ProductB, but when you choose ProductA you must specify a delivery mechanism, and for ProductB you need a customer id (basically just two different things).

What you can do to solve this is the same as for Scala DSLs: You create classes corresponding to the individual steps and instead of returning this (or self), you return a new object with the next possible options.

So Builder.createProductA returns a ProductABuilder with a "setDeliveryMechanism" method, whereas Builder.createProductB returns a ProductBBuilder.

In your case, you probably don't want your DSL users to start declaratively define a product via "Mail". Instead, you have a DSL main class which allows creation of ProductA or ProductB, but returns a "MissingProductB", or "MissingProductA" class, on which the corresponding other product can be specified. Once you have both, the next class may be MissingMail.

Note that this class structure statically corresponds to the possible sentences of your DSL grammar.

Something that's hard to realize via this approach is when you want to be able to arbitrarily mix and match those three things. You can then either add some sort of validation in the end (but that's runtime not compile time validation), or you would have to create specific classes for all the different variations of possible calls at which time you will probably call no-joy.

Frank
  • 14,437