The Warewolf domain specific language: simple but powerful

Warewolf was designed to allow developers to rapidly prototype complex systems using a simple flow-based programming paradigm. Applications built using flow-based languages are self-documenting and easily understood by both developers and other stakeholders. Traditionally, most other flow-based languages have been adequate for creating simple systems but cumbersome and inadequate when modelling complex applications. With Warewolf however, we have managed to create a flow language that is succinct and easy to understand.

How does Warewolf succeed where other flow-based languages have failed?

The answer lies in two different but equally important Warewolf features:

Reuse via composition

Composition allows Warewolf workflows to be succinct and incredibly easy to understand. Composition of Warewolf workflows has been spoken about in other blog posts and articles.

The purpose of this blog is to explain the Warewolf language and how it can be used to simplify flow-based programming.

Warewolf domain specific language

The Warewolf domain specific language (DSL) allows for data to be manipulated with ease and without the need for loop structures. The overlying intention of the language is to allow users to think in sets of data rather than imperatively.

The Warewolf domain specific language explained

Before explaining the Warewolf language, I must first explain the types of variables available within a Warewolf workflow or service. Warewolf variables can either be scalars or recordsets.

Scalars are simple atomic values that are dynamically typed and scoped to the currently executing workflow.

Recordsets, on the other hand, contain tabular data which is analogous to tables in a SQL database. Recordsets are stored in column oriented in-memory data structures and contain columns of dynamically typed data. Types are inferred at run-time.

Scalars are referenced using the following syntax:

  • [[Name]] This is a reference to a scalar variable.

Recordsets are referenced using the following syntax:

  • [[RecordsetName(*)]] This references all rows and columns of a Recordset
  • [[RecordsetName()]] This expression references the last row of Recordset within the scope of the executing workflow
  • [[RecordsetName(n)]] This is a reference to the nth row of a Recordset within the scope of the executing workflow
  • [[RecordsetName(*).ColumnName]] Reference an entire column of a Recordset
  • [[RecordsetName().ColumnName]] Reference to the last cell of a column
  • [[RecordsetName(n).ColumnName]] Reference to the nth cell of a column

Complex expressions can combine valid DSL expressions in almost any way imaginable. Given a variable [[Name]] with a value of Bob, for example, the expression “Hello my name is [[Name]]” will evaluate to “Hello my Name is Bob”

How does this syntax make processing data easier?

It’s all about context. The Warewolf data DSL behaves intuitively given the context of its use. The Assign connector, for instance, can be easily used to map data transformations over entire Recordsets without the need for looping. Given a Recordset with columns of names and surnames, the Assign tool can be used to concatenate all names and surnames without the need for a loop. The example below shows this:

Assign tool can be used to concatenate all names and surnames without the need for a loop

The For Each tool connector will substitute the * in all Recordset expressions with the iteration index given index while processing.  The example below will create an XML string using simple concatenation in combination with * notation:

create an XML string using simple concatenation

The Calculate will automatically aggregate data as is appropriate. Given a Recordset [[Rec().Val]] with values 1,2,3 the expression Sum([[Rec(*).Val]]) will evaluate to the number 6.

warewolf domain specific language recordset

Each tool given a * input will automatically map its functionality over an entire Recordset without the need to specifically iterate. The example below shows how to write a list of files into the file system without specifically needing a For Each:

write a list of files into the system without needing a For Each tool connector

Conclusion

The Warewolf domain specific language allows users to minimize iterations and create succinct, readable flow-based services without the need for repetition and complexity. Traditional programming languages are mostly imperative. The task that you are trying to accomplish is rarely separable from the micro-steps involved in how you accomplish it. Warewolf’s domain specific language fixes this by minimizing iterations. It really is as simple as letting the workflow run-time handle iteration and aggregation while you worry about the important things like business logic.

Using the Warewolf DSL effectively allows you to write concise software that is easily readable by both business stakeholders and developers. It is one of the reasons that you should be choosing Warewolf as your next development platform. You can find out more on our homepage.

FacebookTwitterLinkedInGoogle+RedditEmail

Leave A Comment?