Wednesday, 15 January 2020

Tridash 0.8: Stateful Applications using Functional Programming

This post begins with a description of the State Management Problem and various solutions to it offered by today's programming languages. The final section details the solution provided by version 0.8 of the Tridash programming language. The section contains a complete code example of a simple application comprising a counter which is incremented whenever a button is pressed.

The State Management Problem

When developing an application with an interactive user interface, one of the core problems you'll have to deal with is managing and synchronizing the state of your application throughout all its components.

Let's consider a simple example, an application which takes two numbers, entered by the user, and displays their sum. The application consists of two text input fields. The sum should be recomputed and redisplayed whenever the values entered in the fields change. This application consists of four components:

  • The two input fields
  • The UI element in which the resulting sum is displayed, i.e the display component
  • The internal component which is responsible for computing the sum

The internal component needs to know what the values entered in the input fields are, in order to compute their sum. In other words the internal component is dependent on the state of the two input fields. The UI element in which the sum is displayed, needs to know what the sum is and is thus dependent on the state of the internal component, which is responsible for computing the sum.

When the values in the input fields are changed, the internal component needs to be notified of this change in order to recompute the sum. Likewise the display component needs to be notified of the new sum, in order for it to be displayed. This updating of the state in response to user events encompasses the State Management Problem.

Solutions

Today's programming languages offer a number of common solutions to the state management problem.

Imperative Programming

The most basic solution is that offered by imperative programming languages. An imperative language, such as Java or C/C++, provides direct access to the underlying memory. This means the programmer can read and write to memory with few restrictions. In an imperative language, an object references a location in memory where a value, or a series of values are stored and can be modified. A modification to that object will be visible to all references to the same object. In effect, the memory comprises the application's state.

With imperative programming, a typical implementation, of the sum application, involves attaching event listeners to both fields, which are called whenever their values change. In the event listener, the value entered in the text field is read from memory, and stored in a variable, a reference to another memory location, which is accessible to the internal sum component. A procedure is called to recompute the sum. This procedure reads the values of the internal variables, which store the values entered in the text fields, and computes the new sum. Finally this new sum has to be written to the memory, in which the value displayed to the user, is stored.

The problem with this approach is that the synchronization of the application state, across all its components, is left entirely up to the programmer. This quickly becomes repetitive and the application logic is buried under layers of state updating and synchronization code.

This approach is also inflexible to changes in the application's specification. For example, consider that we want to enhance the application, such that if the sum exceeds a limit, provided by the user, a "Limit Exceeded" message is displayed. In essence this involves the addition of a new application component. To do so we'd have to modify the code for the internal component, which is responsible for computing the sum, in order to inform the new component of changes to the sum.

Finally this approach is prone to bugs in which, if a component is not properly notified of a change in the state of another component, the application state is not properly updated. Further room for bugs is created, when multi-threading is added to prevent the user interface from becoming unresponsive in long-running computational or IO tasks. Now the programmer has to worry about synchronizing the application state across multiple threads.

Functional Programming

Functional programming differs from imperative programming in that it does not provide the notion of memory. In a functional programming language, an application is composed of pure functions, which take a number of inputs and produce an output. This output is then fed on to further functions which produce further outputs. In a functional programming language, objects do not reference a memory location where a value is stored, rather the object is the value itself. An object cannot be modified, only a new object can be created. By eschewing memory, functional programming eschews application state completely. Without state, applications which interact with the user, while they are running, cannot be implemented.

To workaround this limitation, the entire application is structured as a pure function of its input, which is an infinite stream of user events. The function maps this stream to the stream of resulting application states. It is this output stream which is observed by the user.

Using this approach the sum application would be implemented as a function which takes the values of the two text fields as input and produces an application object as output in which the sum of the two values is displayed. This function is called whenever the user interacts with the application, i.e. when the values entered in the text fields are changed, and the resulting application object, which is identical to the previous application object with the only difference being that the sum is updated, is displayed.

This approach improves on the imperative approach in that the application code consists of just the application logic, itself. There is no state updating, or state synchronization code as there isn't any state to begin with. The problem with this approach is that what is inherently a stateful problem, the application itself, has to be artificially contorted into a pure function on a stream of events. The programmer can no longer think of the application as it is at a given moment in time but rather has to think about computing what the application is at any moment in time.

Functional Reactive Programming

The third solution, which is the approach taken by Tridash, is closely related to the second, however the notion of memory is brought back. Instead of eschewing memory and state completely, each application component, called a node in Tridash, has a state. However unlike with the imperative approach, this state cannot be arbitrarily modified. Instead the state of each component is specified as a pure function of the state of the components on which it depends. Whenever the state of a component changes, the state of all components which depend on that component is recomputed. In Tridash, this relation between a component (node) and its dependencies is referred to as a binding.

The implementation of the sum application is thus a matter of declaring each component, declaring that the value of the internal sum component is the sum of the values entered in the fields, and declaring that the value displayed as output is the value of the sum component.

In Tridash the entire application, excluding the user interface, can be implemented with the following:

a <- input-a.value
b <- input-b.value

sum <- a + b

output <- sum

where the <- operator specifies that the value of the node on the left-hand side is bound to the value of the node/expression on the right hand side.

Functional reactive programming has the advantages of regular functional programming however a more natural, stateful, view of the application is presented. Instead of thinking about how the inputs map to the internal representation of the application object, and how that object maps to the output, which is the state of the user interface, the programmer can think in terms of how does the state of this component relate to the state of the remaining components.

Functional reactive programming (FRP) has the disadvantage however, that there is no way to cleanly specify that a component is dependent on its past states. As an example, implementing a counter, which is incremented by one whenever a button is pressed is impossible. Most FRP systems simply degenerate to the stream of user events approach, of regular functional programming when it is necessary to map a previous state of a component to a new state.

Node States and Stateful Bindings with Tridash 0.8

Tridash 0.8 introduces two new features, Node States and Stateful Bindings, which allow mapping a past state of a component (node) to its current state, without leaving the functional reactive programming paradigm.

In Tridash, bindings are established using the -> operator, or the <- operator, as seen above, which is the same operator but with the arguments reversed.

a -> b

In this example, a binding is established between node a and node b. Whenever the value of a changes, the value of b is automatically updated to it.

However, this does not allow mapping a previous state to the current state, i.e. a cannot be a function of b. Implementing a counter with the following will not work.

counter + 1 -> counter

The reason being, that this specifies that whenever the value of counter + 1 changes, the value of counter is updated to it. However when the value of counter is updated, the value of counter + 1 is also recomputed and updated. This results in the value of counter being updated again which results in yet another recomputation of counter + 1. Its obvious that the simple rule of updating the value of counter whenever the value of its dependency, counter + 1 in this case, changes will not do. We need a way to tell the language when we actually want counter's value to be updated.

Node states allow a node to be given an explicit named state at a given moment in time. The state is named by a symbol identifier. A stateful binding is a binding which only takes effect when a node switches to a particular named state. A stateful binding is established when the observer node in a binding, the node on the right hand side of the -> operator, is given an explicit state, using the :: operator.

a -> b :: state

In this example, a stateful binding is established which takes effect when b switches to the state with identifier state. a can be a function of b as the binding only takes effect when the state of b changes to state and not when the value of a is changed.

A counter can be implemented with the following stateful binding:

counter + 1 -> counter :: increment

Node counter is thus incremented when its state changes to increment.

All that remains is to actually set the state of counter. What determines the state of a node? Simple, the value of the special node /state(node), where node is the node identifier. To set the state of counter we simply establish a binding with /state(counter) as the observer.

We want counter to be incremented whenever a button is pressed. Let's say we have another node clicked? which has the value true while the button is being pressed and false when it is released. We can thus bind /state(counter) to an expression which evaluates to the literal symbol increment when clicked? is true and to something else, such as the symbol default when clicked? is false. The following is the expression we require (to which /state(counter) is bound):

case (
    clicked? : '(increment),
    '(default)
) -> /state(counter)

The ' operator simply returns its argument as a literal symbol, similar to the ' or quote operator in Lisp.

User Inteface

The application logic is complete, the only thing missing is the user interface. The interface can be defined with the following HTML:

<div>Value of counter is <?@ counter ?></div>
<button id="increment">Increment</button>

With the current version of Tridash the value of the clicked? node has to be set manually via JavaScript when the button is clicked. In the next version, you'll be able to bind to a node that is automatically set to true when the button is pressed and false when it is release.

To be able to reference the clicked? node from JavaScript the following attribute declaration are required:

/attribute(clicked?, input, 1)
/attribute(clicked?, public-name, "is_clicked")

This designates clicked? as an input node and gives it the identifier is_clicked, with which it is referenced from JavaScript.

The following JavaScript script tag is required to attach an event listener to the button and set the value of the node.

<script>
  var button = document.getElementById('increment');

  button.addEventListener('click', function() {
      Tridash.nodes.is_clicked.set_value(true);
      Tridash.nodes.is_clicked.set_value(false);
  });
</script>

The first line gets a reference to the HTML button element. The remainder of the code attaches the event listener for the click event, and sets the value of the clicked? node to true and then immediately false. We're setting to false after setting it to true in order to mimic the behaviour of a button.clicked? node, which will be added in the next release.

To put it all together we place the Tridash code in a Tridash code tag at the top of the HTML file:

<?
 /import(core)

 counter + 1 -> counter :: increment

 case (
     clicked? : '(increment),
     '(default)
 ) -> /state(counter)

 # Initial Value of Counter
 0 -> counter

 # Attribute for reference `clicked?` node from JavaScript
 /attribute(clicked?, input, 1)
 /attribute(clicked?, public-name, "is_clicked")

?>
<!doctype html>
<html>
  <head>
    <title>Counter</title>
  </head>
  <body>
    <h1>Counter</h1>

    <div>Value of counter is <?@ counter ?></div>
    <button id="increment">Increment</button>

    <script>
      var button = document.getElementById('increment');

      button.addEventListener('click', function() {
          Tridash.nodes.is_clicked.set_value(true);
          Tridash.nodes.is_clicked.set_value(false);
      });
    </script>
  </body>
</html>

This is the complete application implemented using the Functional Reactive Programming paradigm (excluding the JS script tag which is only necessary in the current version):

The following command builds the application:

tridashc counter.html : node-name=ui -o app.html -p type=html -p main-ui=ui

Here a snapshot of the initial state (with the initial value of 0 given to counter):

Value of counter is 0

After pressing Increment once:

Value of counter is 1

After pressing Increment again:

Value of counter is 2

Conclusion

Tridash 0.8 adds two novel features which extends the simple Functional Reactive Programming paradigm to allow for implementing stateful applications, in which the state of an application component depends on its previous state rather than the state of another component. This retains all the advantages of functional programming however provides a natural model of application state.

For more information about Tridash (installation instructions, documentation tutorials) visit https://alex-gutev.github.io/tridash/.

For a more detailed and feature rich example, as well as examples of stateful bindings with explicit From and To states, visit: https://alex-gutev.github.io/tridash/tutorials/ar01s10.html.

For

Friday, 27 September 2019

Reactive Web Applications with Tridash

In this post we'll be implementing a simple reactive web application with Tridash. We'll start off with a very simple specification and gradually add features to improve its functionality.

This post is not a full in-depth introduction to the Tridash language. For a detailed introduction to its syntax and core concepts, check out the Tutorials.

Visit the homapage for download links and installation instructions.

Tridash: A Brief Introduction

In Tridash an application is composed of a set of computational components, called nodes. Each node has a value which is a function of the values of one or more dependency nodes. Whenever the value of at least one of the dependency nodes changes, the node's value is recomputed. This relation between a node and its dependency nodes is referred to as a binding.

Bindings can be established explicitly, with the -> operator, in which the left hand side specifies the expression, of the dependency nodes, for computing the value of the node on the right hand side. The left hand side is referred to as the source of the binding and the right-hand side as the target of the binding.

Examples

The following establishes a simple binding in which node b is set to the value of node a:

a -> b

The following establishes a binding in which node c is set to the sum of the values of nodes a and b:

a + b -> c

Whenever a or b changes, a + b is reevaluated and the value of c is recomputed.

Budgeting Application

We'll implement a simple budgeting application. In the first iteration, we'd like the functionality to enter an amount of money allocated to a number of predefined expense categories. The total should be computed after the amounts are entered and recomputed whenever the amounts are changed. This will allows us to see whether the total amount allocated exceeds the budget.

Let's start off with the user-interface. We have three predefined expense categories:

  • Food
  • Electricity
  • Water

Create a simple HTML file app-ui.html containing the usual HTML boilerplate. Add three input elements, where the amounts allocated to the three expense categories are entered and a fourth readonly input element where the total is displayed.

<!doctype html>
<html>
  <head>
    <title>Budget App</title>
  </head>

  <body>
    <div>
      <label for="food">Food:</label>
      <div><input id="food"/></div>
    </div>
    <div>
      <label for="water">Water:</label>
      <div><input id="water"/></div>
    </div>
    <div>
      <label for="electricity">Electricity:</label>
      <div><input id="electricity"/></div>
    </div>
    <hr>
    <div>
      <label>Total:</label>
      <div><input id="total" readonly/></div>
    </div>
  </body>
</html>

Now we have a nice interface which doesn't actually do anything. This is where Tridash comes into the picture.

What we require is that the sum of the values, entered in the input elements, is computed and displayed in the total field. Additionally we require that the sum is recomputed and that the new total is displayed whenever an amount is changed.

If we were to implement this behaviour in raw JavaScript we'd first have to write the initialization code which retrieves references to the input elements, making sure that it is run at the correct moment in time, that is after the document has been loaded. An event listener has to be attached to each input element, which is called whenever the element's value changes. In the event listener callback function, each input's value has to be converted to a number after which the total sum is computed. The value displayed in the total input element has to be manually updated to the new sum.

All in all, this would require something similar to the following:

var input_food = document.getElementById("food");
var input_water = document.getElementById("water");
var input_electricity = document.getElementById("electricity");
var input_total = document.getElementById("total");

function update_total() {
    var food = parseFloat(input_food.value);
    var water = parseFloat(input_water.value);
    var electricity = parseFloat(input_electricity.value);

    input_total.value = food + water + electricity;
}

input_food.addEventListener("change", update_total);
input_water.addEventListener("change", update_total);
input_electricity.addEventListener("change", update_total);

While this may not seem like much, the only part which actually implements our application logic is food + water + electricity. The rest is boilerplate which distracts from the core application logic. Event listeners for changes in the state of each of the UI elements have to be manually setup and the application state has to be manually updated (the computation of the new total) and manually synchronized across the remaining components of the application (the total input element which displays the output total). This leaves a lot of room for bugs. Furthermore, this code does not perform any error checking or handling of any sort. If you enter a non-numeric value in any of the input elements, NaN is displayed as the total. The bigger issue, however, is that this code is inflexible to changes in the application logic.

With Tridash this can be implemented in a single line of code:

food + electricity + water -> total

This Tridash declaration results in the creation of the nodes food, electricity and water which serve as the inputs. The node total is bound to the sum of the values of the nodes food, electricity and water. total is said to be bound to the sum, rather than simply being set to the sum, as its value is automatically recomputed whenever the value of one of food, electricity and water changes. It is this automatic recomputation of the values of nodes, which forms the core of the Tridash language.

Whilst that implements our application logic, we still need to bind the nodes food, electricity and water to the values entered in the input elements. It turns out, we can do that simply by adding a piece of Tridash code in each input element's value attribute, but first let's take care of converting the string values to numbers.

The to-real function, referred to as a meta-node in Tridash nomenclature, converts its argument to a real (floating point) number. For now we can simply replace food with to-real(food), and do the same for electricity and water, in the expression, which computes the total sum.

to-real(food) + to-real(electricity) + to-real(water) -> total

Now to bind the node food to the value of the food input element, we can simply set its value attribute to the Tridash node food with the following:

<input id="food" value="<?@ food ?>"/>

The <?@ ... ?> tag establishes a binding between the value of an HTML element's attribute and a Tridash node.

We can repeat this procedure for the water, electricity and total fields.

To put it all together we simply need to add the code, which implements our core application logic, to the HTML file within a Tridash code tag <? ... ?>.

The <? ... ?> tag allows Tridash code to be inserted directly in the HTML file.

The following is the complete application:

<?
:import(core)

to-real(food) + to-real(electricity) + to-real(water) -> total
?>
<!doctype html>
<html>
  <head>
    <title>Budget App</title>
  </head>

  <body>
    <div>
      <label for="food">Food:</label>
      <div><input id="food" value="<?@ food ?>"/></div>
    </div>
    <div>
      <label for="water">Water:</label>
      <div><input id="water" value="<?@ water ?>"/></div>
    </div>
    <div>
      <label for="electricity">Electricity:</label>
      <div><input id="electricity" value="<?@ electricity ?>"/></div>
    </div>
    <hr>
    <div>
      <label>Total:</label>
      <div><input id="total" value="<?@ total ?>" readonly/></div>
    </div>
  </body>
</html>

The :import(core) line at the top of the file imports the core module which contains the to-real and + functions.

Build the application with the following command:

tridashc app-ui.html : node-name=ui -o app.html -p type=html -p main-ui=ui

See the Building section of Tutorial 1 for an explanation of the command.

Open the output app.html file in a web browser and enter some values in the input fields.

Snapshot of application with entered values: 10,20,30 and total 60.

Notice how the total is automatically computed. Now try changing some of the values and you'll notice that the total is automatically recomputed.

This is an improvement over the JavaScript version in many ways:

  • We've eliminated the boilerplate in establishing event listeners and manually updating the application state, which involves recomputing the total and updating the value of the total field. Instead we've specified our application state in a declarative manner, and let the language take care of updating the application state in response to user events.

  • You don't get NaN as a result if an invalid value is entered, though we'll add proper error handling later.

  • It's clear which part of the code is responsible for implementing the application logic as it is not buried in event listener callback functions. As a result the application logic can be easily changed or extended when the specification changes.

In order to convince you of the last point, let's say we'd also like to display a message with the total underneath the total input element. To do so we can simply add the following to the HTML file after the total input element:

You have a total of <?@ total ?>!

<?@ total ?> is automatically replaced with the value of the total node and automatically updated whenever the node's value changes. The value of the total node is itself recomputed whenever the values, entered in the input elements, change.

Improvements

Believe it or not, this application can be made even more succinct. The to-real function is special in that if it occurs as the target of a binding, a number is parsed from the value of the source node, not the argument. The argument node is, instead, set to the parsed real value. This allows us to place the conversion logic directly in the value attributes of the input elements. As an example value="<?@ food ?>" can be replaced with value="<?@ to-real(food) ?>".

Thus the code implementing our main application logic can be simplified to:

food + electricity + water -> total

If you really want to be succinct, the total node can be removed entirely and value="<?@ total ?>" can be replaced with the sum expression directly:

<input id="total" value="<?@ food + electricity + water ?>"/>

However, we'll keep the total node as it will simplify the implementation of the other features of our application.

Budget Application version 2.0

The application we've implemented is quite rudimentary. We have to keep the budget in mind and manually check whether the resulting total exceeds the budget. It would be nice if we could enter the budget and have the application tell us whether it was exceeded.

It was promised that Tridash allows the application logic to be easily modified and extended. Now we'll prove it.

As in the first version, let's begin with the UI. We need a new input element for entering the budget. Let's add it above the first expense field. While we're at it, let's bind its value, converted to a real number, to a node called budget.

<div>
  <label for="budget">Budget:</label>
  <div><input id="budget" value="<?@ to-real(budget) ?>"/></div>
</div>

Now we need to display a message which tells use whether the total is within the budget or the budget was exceeded. We can do this using the case macro.

The arguments to the case macro are of the form condition : value in which condition is the condition expression and value is the value expression. The case expression evaluates to the value of the first argument for which the corresponding condition evaluates to true. The last argument may simply be of the form value, in which case it becomes the default value, to which the case expression evaluates, if the conditions of the preceding arguments evaluate to false.

Example:

case(
  a > b : 1,
  a = b : 0,
  -1
)

The above evaluates to 1 if a is greater than b, 0 if a is equal to b and -1 otherwise.

We need the message "Within Budget" to be displayed if total is less than budget and the message "Budget Exceeded!!!" to be displayed otherwise. This is implemented by the following case expression:

case(
  total < budget : "Within Budget",
  "Budget Exceeded!!!"
)

Now how do we actually display the message? Simple, we just place this declaration inline, within a <?@ ... ?> tag somewhere in the HTML file.

The following is the complete code for version 2.0 of the budgeting application:

<?
 :import(core)

 food + electricity + water -> total
?>
<!doctype html>
<html>
  <head>
    <title>Budget App</title>
  </head>

  <body>
    <div>
      <label for="budget">Budget:</label>
      <div><input id="budget" value="<?@ to-real(budget) ?>"/></div>
    </div>
    <hr>
    <div>
      <label for="food">Food:</label>
      <div><input id="food" value="<?@ to-real(food) ?>"/></div>
    </div>
    <div>
      <label for="water">Water:</label>
      <div><input id="water" value="<?@ to-real(water) ?>"/></div>
    </div>
    <div>
      <label for="electricity">Electricity:</label>
      <div><input id="electricity" value="<?@ to-real(electricity) ?>"/></div>
    </div>
    <hr>
    <div>
      <label>Total:</label>
      <div><input id="total" value="<?@ total ?>" readonly/></div>
    </div>

    <p>
      <?@
       case(
           total < budget : "Within Budget",
           "Budget Exceeded!!!"
       )
       ?>
    </p>
  </body>
</html>

Let's try it out entering some values such that the total is within the budget:

Snapshot with total within budget.

"Within Budget" is displayed as we wanted.

Now change the amounts such that the total exceeds the budget:

Snapshot with total exceeding budget.

The message automatically changes to "Budget Exceeded!!!". This demonstrates the reactive nature of Tridash.

That's all we had to do to implement the improvements to our application logic.

Note: The node total can be replaced directly with the expression food + electricity + water. It makes no difference in efficiency as the expression is only computed once when it is first used.

Adding Color

We have a basic working application, which informs us whether the total amount allocated exceeds the budget, however it can do with some improvements. It would be better if there is a visual indication, in the form of a color change, for whether the budget was exceeded or not rather than having to read out the message in full.

What we want is the background, of the total input field, to turn red when the budget is exceeded and turn green if the total amount is within the budget. In other words the background color of the total input element should be bound to red if the budget is exceeded and bound to green if the total is within the budget.

HTML elements can be referenced from Tridash using self.<id>, where <id> is replaced with the HTML ID of the element. The . operator references a subnode of a node, where the node is on the left-hand side and the subnode identifier on the right hand side. Attributes of the element can be referenced as subnodes of the HTML element node, with the style attributes as subnodes of the style subnode.

Thus we can implement the desired behaviour with the following:

case(total < budget : "green", "red") -> self.total.style.backgroundColor

self.total references the total input element, which has its id set to total. style is the identifier of the style subnode under which all style attributes of the element are grouped. Finally backgroundColor is the identifier of the style attribute which controls the element's background color.

Additionally, the text should be changed to white in order for it to be legible. We can do that using an inline style attribute in the HTML element or using CSS classes, however we can also bind the element's color style attribute to the constant "white", in Tridash. This is useful if later on we'd like the text color to also change dynamically.

"white" -> self.total.style.color

These two Tridash declarations can be added to the <? ... ?> tag at the top of the file.

Snapshot: within budget, green total.

The background color of the total input element is green when the total is within the budget.

Budget exceeded, red total.

When the amounts are changed such that the budget is exceeded, the background color changes to red, which provides an immediate visual cue that the budget has been exceeded.

Error Handling

It was mentioned at the beginning of the article that you get a form of error handling for free. If a non-numeric value is entered in one of the input elements or some of the elements are left empty, the total remains unchanged. This is a step up from getting a total of NaN as the result, however there is no indication to the user that something went wrong.

An error message needs to be printed, next to the field containing the invalid numeric value. The message should prompt the user to correct the value.

Failures

Failures are a special type of value that, when evaluated by a function, the evaluation of the function is aborted and the failure value is returned. They can be used to represent the absence of a value or the failure of an operation. In this case the to-real meta-node returns a failure if a number could not be parsed from the string value. When the failure value is evaluated, by the + function in the computation of the total, the evaluation of the expression is aborted and the total node is set to the failure value.

We can check whether a node evaluates to a failure value using the fails? meta-node. Thus we can, for example, determine whether an invalid numeric value was entered in the food input element, with the expression fails?(food).

With the case macro, we can construct a simple expression which evaluates to the error message, if a non-numeric value was entered, and evaluates to the empty string otherwise:

case(
    fails?(food) : "Please enter a valid number!",
    ""
)

Since we'll be repeating the same expression for the budget, food, water and electricity nodes, we can extract the expression in a function of our own.

error-prompt(value) : {
    case(
        fails?(value) : "Please enter a valid number!",
        ""
    )
}

Functions are defined with the : operator. The left-hand side consists of the function name followed by the list of argument nodes, to which the function arguments are bound, in parenthesis. The right-hand side contains the declarations forming the body of the function. The value of the last expression in the body becomes the return value of the function.

With this function we can get the error prompt for a particular field, say food, with the expression: error-prompt(food). Thus to add the error messages to our interface we simply add an error-prompt expression next to each input field.

<div>
  <label for="budget">Budget:</label>
  <div>
    <input id="budget" value="<?@ to-real(budget) ?>"/>
    <?@ error-prompt(budget) ?>
  </div>
</div>
<hr>
<div>
  <label for="food">Food:</label>
  <div>
    <input id="food" value="<?@ to-real(food) ?>"/>
    <?@ error-prompt(food) ?>
  </div>
</div>
<div>
  <label for="water">Water:</label>
  <div>
    <input id="water" value="<?@ to-real(water) ?>"/>
    <?@ error-prompt(water) ?>
  </div>
</div>
<div>
  <label for="electricity">Electricity:</label>
  <div>
    <input id="electricity" value="<?@ to-real(electricity) ?>"/>
    <?@ error-prompt(electricity) ?>
  </div>
</div>

Invalid value entered for water, prompt displayed next to it.

The error message is displayed next to the field with the invalid value, and the total is not computed.

With this small addition the user is now clearly informed of when an invalid number has been entered in the text input fields. However, this does not stop the user from entering valid numbers which do not make sense in the context of the application, such as negative numbers.

We'll create a new function which parses a real number from a string value and ensures that the real number is greater than or equal to 0. To keep the current code, for displaying the error messages, unchanged, we require this function to return the number if it is greater than or equal to 0, and return a failure if the number could not be parsed or is less than 0. This can be achieved using conditional bindings.

A conditional binding is a binding which is only active if the value of another node, the condition node, is true. If the value of the condition node is false, the target node of the binding evaluates to a failure value rather than evaluating to the value of the source node.

Example:

A conditional binding in which a node y evaluates to the value of x only if x >= 0, is established with the following:

x >= 0 -> (x -> y)

Notice, in this expression, that the binding x -> y is itself treated as a node which is the target of a binding. A binding becomes a conditional binding whenever the binding, itself, is a target of a binding, with the source node becoming the condition node.

Our function can thus be implemented with the following code:

check-valid(str) : {
    num <- to-real(str)
    num >= 0 -> (num -> self)
}

<- is the same as -> however the arguments are reversed, with the target on the left-hand side and the source on the right-hand side.

self is a special node, occurring inside functions. If a binding to self is established in the body of a function, the function returns the value of the self node rather than the value of the last expression in its body.

The only remaining task is to incorporate this function in our application. We can of course surround each of the nodes, bound to the values of the expense input elements in check-valid(...), in the computation of the total, however we can do better.

Target-Nodes

Remember to-real is special in that if an expression of to-real appears as the target of a binding, the value of the source node is converted to a real number and the argument node is bound to it. It turns out to-real is not that special since we can do the same for our own functions. This is done by means of a target-node function. The target-node function is the function which is used to compute the value of the argument node, given the value of the source node, whenever an expression of the function appears as the target of a binding. For to-real this is simply to-real itself. That is why the following two declarations are equivalent:

to-real(x) -> z
x -> to-real(z)

This is achieved by setting the target-node attribute of to-real to to-real:

:attribute(to-real, target-node, to-real)

Attributes are key-value pairs which control various properties of nodes. Attributes are set with the :attribute special operator, in which the first argument is the node, the second argument is the attribute identifier and the third argument is the attribute value.

To obtain the same behaviour for our check-valid function, we simply set its target-node attribute to check-valid.

:attribute(check-valid, target-node, check-valid)

As a result all that is necessary to implement this new error handling logic, is to replace to-real(...) with check-valid(...) in the value attributes of the input elements.

Example:

<input id="food" value="<?@ check-valid(food) ?>"/>

We should also change the message, to inform the user that negative valued inputs are invalid:

"Please enter a valid integer \u{2265} 0!"

\u{2665} represents the unicode character with code 2265, which is the character ≥

Negative value entered for water, prompt displayed next to it.

Final Version Full Source Code

<?
 :import(core)

 error-prompt(value) : {
     case(
         fails?(value) : "Please enter a valid number \u{2265} 0!",
         ""
     )
 }

 check-valid(str) : {
     num <- to-real(str)
     num >= 0 -> (num -> self)
 }

 :attribute(check-valid, target-node, check-valid)

 food + electricity + water -> total

 case(total < budget : "green", "red") -> self.total.style.backgroundColor
 "white" -> self.total.style.color
?>
<!doctype html>
<html>
  <head>
    <title>Budget App</title>
  </head>

  <body>
    <div>
      <label for="budget">Budget:</label>
      <div>
        <input id="budget" value="<?@ check-valid(budget) ?>"/>
        <?@ error-prompt(budget) ?>
      </div>
    </div>
    <hr>
    <div>
      <label for="food">Food:</label>
      <div>
        <input id="food" value="<?@ check-valid(food) ?>"/>
        <?@ error-prompt(food) ?>
      </div>
    </div>
    <div>
      <label for="water">Water:</label>
      <div>
        <input id="water" value="<?@ check-valid(water) ?>"/>
        <?@ error-prompt(water) ?>
      </div>
    </div>
    <div>
      <label for="electricity">Electricity:</label>
      <div>
        <input id="electricity" value="<?@ check-valid(electricity) ?>"/>
        <?@ error-prompt(electricity) ?>
      </div>
    </div>
    <hr>
    <div>
      <label>Total:</label>
      <div><input id="total" value="<?@ total ?>" readonly/></div>
    </div>

    <p>
      <?@
       case(
           total < budget : "Within Budget",
           "Budget Exceeded!!!"
       )
       ?>
    </p>
  </body>
</html>

Conclusion

This post shows how easily an application, developed with Tridash, can be amended to changes in the specification. The state management boilerplate has been eliminated allowing you to focus on the core logic of your application. The creation of a new application component, which depends on the state of an existing application component, such as the total sum in this application, is simply a matter of declaring the component and declaring its dependency on the previous component.

Specifying the application state in a declarative can lead to fewer bugs related to state management and more maintainable code.

For

Thursday, 5 September 2019

What's new in Tridash 0.5

Recently I released version 0.5 of the Tridash programming language. You can read more about why I wrote Tridash in my previous post. This post provides an overview of the new features this version brings.

Official website: https://alex-gutev.github.io/tridash/

Improved Semantics

This version brings a significant refinement to the semantics of the language.

Non-Strict Evaluation Strategy


The previous version did not have a formal evaluation strategy. Generally all nodes were strictly evaluated, that means their values were always computed, with some special exceptions made for if, and, or expressions. The new version formalizes a non-string evaluation strategy for all nodes, which means the value of a node is only computed if it is actually used, and the special exceptions have been removed. if, and, or are now ordinary functions (meta-nodes).
A strictness analysis phase determines whether the value of an argument to a function is always used and thus may be evaluated prior to being passed to the function. This is an optimization step which allows arguments to be by value which is more efficient than passing a thunk which computes the value later.
The new evaluation strategy also allows for proper tail-call elimination of any function call in tail position. This means a constant amount of stack space is used regardless of the depth of the recursion. Coupled with strictness analysis, this ensures that a constant amount of stack space is used by arguments which serve as accumulators.

Visit Evaluation Strategy for more information.

Failure Values


Failure values are a special class of values which trigger a failure of the current operation, when evaluated. When a function argument, which evaluates to a failure, is evaluated, the evaluation of the function is terminated and a new failure value is returned. Failures are used to represent the absence of a value, failure of an operation or special classes of values such as the empty list.
The idea behind using a special failure value is that the main application logic can focus on the actual computation taking place without having to check whether an error occurred. Instead the error handling code can be separated from the main application logic.

Example

Consider that an integer needs to be parsed from an input x. The parsed integer value is then used in some computation, for simplicity let's say we add 1 to the value and display the result. An integer value is parsed from a string with the int function.

    int(x) + 1 -> output

If an integer cannot be parsed from the string value entered in x, the int function returns a failure value. As a result the evaluation of int(x) + 1 will also result in a failure value, and no output being displayed.

To display an error message, prompting the user to enter a correct value, we simply need to check whether output evaluates to a failure. The fails? function returns true if its argument evaluates to a failure:

    if(fails?(output), "Please enter a valid integer!", "") -> error

The node error evaluates to the string "Please enter a valid integer!" if the node output evaluates to a failure, which happens when an integer cannot be parsed from x, otherwise it evaluates to the empty string.

Failure values may also have an optional type which allows the cause of the failure to be distinguished.

Visit Failures for more information.

Handling Failures with Explicit Contexts


Each binding is established to a particular context of a node. This version allows this context to be specified explicitly using the @ operator. The left-hand side of the operator is the node and the right-hand side is the context identifier, which can be any valid identifier.

When a multiple bindings are established to the same context, the bindings established later in the source code are only activated if the result of all previous bindings is a failure value. This is the means by which failures are handled.

Example
    x -> y @ c
    1 -> y @ c

In the example, above, node y is bound to the value of x in the explicit context with identifier c. If x evaluates to a failure value, the next binding in the context is activated thus y is set to the value 1.

Variants of the @ operator allow a binding to be activated only if it is of a particular type.

Visit Contexts for more information.

List Data Structure

A linked list data structure was added. The list is also used to represent the argument list, of functions taking a variable number of arguments, and is used to represent Tridash expressions when passed to macros.
The empty list is represented by a failure value with a special type Empty. Representing the empty list as a failure value simplifies the implementation of certain list processing functions.

Example: Implementation of map
   map(f, list) : 
       list !- cons(f(head(list)), map(f, tail(list)))

The !- function checks whether the first argument evaluates to a failure value, if so the failure value is returned otherwise the value of the second argument is returned. In the example, above, if list is empty it will evaluate to the failure value with type Empty thus this value is returned from the function. Otherwise a new list is created with apply f on the first element of the list and applying f on the remaining elements of the list, using a recursive call to the map function.

Visit Lists for more information.

Macros

A function can be marked as a macro. As a result the function is invoked at compile-time with the arguments being the raw expressions rather than the computed argument values. The return value of the function is interpreted as a Tridash expression which replaces the macro expression. Identifiers are represented by a special symbol type and function call expressions are represented by a list with the function/operator in the first element of the list and the arguments in the remaining elements. This representation is heavily inspired by the representation of S-Expressions in the Lisp languages.

Macros can be used to extend the language in ways which is not possible with simple functions.

Example: Implementation of <- macro
    <-(a, b) : list(&(->), b, a)

This allows bindings to be specified in the reverse order, e.g. x -> y can be specified as y <- x.
The & operator is a special operator that returns the node object, at compile-time, for a given node which can then be substituted in an expression returned by the macro function. In the example above, the -> meta-node is returned, thus the expression returned by the <- function is an expression of the -> operator.

Another form of macros are offered, in which a bind -> expression with a function expression on the right-hand side, can be replaced by a set of one or more bind expressions. This is used in pattern matching.

Visit Macro Nodes for more information.

Pattern Matching

A new unique form of pattern matching is added in version 0.5. Nodes can be matched to patterns by specifying a binding with the pattern (a function expression) on the right-hand side of the -> operator. The source node, on the left hand side of ->,  is then matched to the pattern. Matching of a pattern means that the argument nodes of the pattern are bound to values for which the function returns a value that is equivalent to the source node. If there is no such value, the argument nodes evaluate to failures.

Example
    x -> int(y)

Node y is bound to the value of x if x is an integer, otherwise it evaluates to a failure.

Example
    x -> list(1, int(y), z)

This example demonstrates constant patterns, and nested patterns. Nodes y and z are bound to the second and third elements of the list stored in x, if the value of x is a list of three elements, of which the first is the number 1 and the second is an integer. Otherwise both y and z evaluate to failures.

Multiple binding patterns involving a single argument node can be established, in which case the node evaluates to the value corresponding to the first pattern that matched.

Visit Pattern Matching for more information.
For

Friday, 30 August 2019

Error Handling via Failure Values with Tridash 0.5

Version 0.5 of the Tridash programming language has released. If you want to know more about why I wrote Tridash, check out https://alex-gutev.blogspot.com/2019/06/tridash-why-yet-another-programming.html. This new version brings a significant improvement in the semantics of the language.

Failures

Ad hoc null values have been replaced with special failure types. Failures values automatically trigger a failure of the current operation, thus creating a new failure value, when evaluated. These are used to represent the absence of values, which were previously represented by null's, failure of an operation or special classes of values, such as the empty list.

Example:
int(input) -> x
The node input stores the value retrieved from an input text field. An integer value is parsed, using the int function, from the value of input (a string), and stored in the node x.

Previously, and in some other languages, you would have to check whether an integer value was successfully parsed from input, and only then make use of the value of x. With failures, if the string value does not contain a valid integer, x is set to a failure value. All nodes which evaluate x will automatically evaluate to failures, thus terminating whatever operation was being performed with the value of x.
x + y -> sum
If an integer was successfully parsed from input, x evaluates to the integer value and the node sum is set to the sum of x and y. If however input does not contain a valid integer, x is set to a failure and the sum of x and y is not computed, instead x + y evaluates to a failure.

This allows the value of x to be treated as though it is guaranteed that an integer is always parsed successfully from input, since if an integer cannot be parsed from input, any usage of x will simply trigger a new failure rather than resulting in undefined behaviour or incorrect results being computed.

This propagation of failures removes the need for littering the main application logic with error handling/checking code.

The error handling code can be separated from the application logic, since Tridash allows any node to be bound to any other node, with the state of each node automatically updated when the state of its dependency nodes changes. As a result, indicating to the user that the value entered is not a valid integer can be as simple as adding the following line:
if(fails?(x), "Invalid integer entered!", "") -> error
The node error evaluates to the string "Invalid integer entered!" when x evaluates to a failure, thus an integer could not be parsed from input. Otherwise, when an integer is successfully parsed from input, error evaluates to the empty string.

This error handling technique isn't just for a single value entered for input, but works even when the value of input is changed by the user. Remember input can represent the value of a text input field, thus its value changes when the user changes the contents of the text field. When the value of input is changed, the value of x is recomputed and likewise the value of sum and error is recomputed. If the new value is a valid integer, error will change to the empty string and sum will be set to the sum of x and y.

This is all made possible due to Tridash's non-linear nature, rather than composing a program out of a linear sequence of instructions, a program is composed out of a set of dependencies (bindings) between nodes. The task of automatically updating and recomputing the value of nodes is taken care of by Tridash, rather than having to be performed manually by the programmer. This, along with the new failure value semantics, added in version 0.5, presents a new error handling technique which simplifies the error handling logic and may, hopefully, lead to more robust applications being written in the future.

Tuesday, 4 June 2019

Tridash: Why yet another programming language?

Another Programming Language?

I recently released version 0.4, the first version that is remotely usable, of Tridash, a programming language I've been working on.

You're probably wondering, with all the existing programming languages available supporting a variety of programming paradigms ranging from low-level imperative programming to logic programming, why on earth would I create a new programming language. What problem do I aim to solve with this new language that has not been solved already by the hundreds of programming languages that came before it. To tell you the truth I mainly created it because I like writing software and trying out new ideas. Creating a programming language was an interesting and fun exercise in itself. However this a legitimate reason for creating a new language, besides the programming exercise.

I've tried many languages ranging from low-level C, object oriented languages such as C++, C#, and Java, scripting languages such as Python, PHP and JavaScript and languages which implement entirely different programming paradigms such as Common Lisp, Prolog and Haskell. Whilst all languages excel at different points, they are all rather lacking when it comes to creating robust and interactive applications. Specifically they are lacking when it comes to managing the state of the application and the changes in its state triggered by the user interaction or external events such as a data arriving on the network.

State Management Problem

Imperative programming languages allow for raw unrestricted mutable access to the underlying memory, that means you can read and write to virtually any address in the process's memory space. These languages generally provide few tools for managing the state of the application. It is entirely up to the programming to establish "listeners" for each interesting event, such as the user entering text in a text field or the arrival of data on the network, and then manually update the state, by mutating memory directly, of the entirely application. 

As a simple example, consider an application consisting of a text field, in which the user enters his/her name, after which a greeting (with the user's name) is displayed.

We want something similar to the following:


In an imperative programming language you would have to setup a listener for the event which is fired when the user enters text in the field, and then manually update the label below the field, by writing to the memory location in which the text is stored, either directly or by some setText method/function, and then calling a redraw method/function. The actual mechanics may differ, depending on the language and GUI framework, however the point is that it is up to the programmer to update the state of the components, which comprise the application, when the state of a component changes. Besides being both tedious and error-prone, the resulting application is usually inflexible with the actual application logic intertwined with the event listener and state updating boilerplate. As a result, changes in the application logic often require an infrastructural change in the code. The problem is exasperated when concurrency is involved. Suddenly the application logic is buried in layers of thread synchronization logic.

Functional programming languages eschew state completely. In a pure functional programming language, memory does not exist. Instead the entire application is structured as a pure function, i.e. without side effects, of its input, which produces the application's output. In order to build interactive applications using a pure functional programming language, all application events (both user and external) are grouped into an infinite list, referred to as a stream, and the application is structured as a pure function taking the stream as input. The output is a new "application" object containing the updated GUI and any IO actions which are to be performed. Whilst this approach offers a lot of benefits, such as being amenable to parallelisation due to the application being structured as a pure function without side effects and thus without concurrent writes to the same memory location, it requires restructuring the application logic as a function that takes an old application object as input and produces a new application object as output. Effectively you have to think of an interactive application as though it is a non-interactive application, which simply takes an input, produces an output and exits. Furthermore you still have to manually compute a new component from the old component for each component comprising your application. It is also up to you to keep track of which components are affected by the event. The addition of new application components, which are affected by some events, requires a change to the application "main" function.

Neither pure functional programming nor imperative programming allow you to declaratively specify the application state as a set of components which are dependent on the state of other components. Imperative programming grants you too much access to the underlying memory, allowing you to mutate the memory as you see fit. If not done carefully this can result in hard to find bugs, moreover manually updating the state in response to events is tedious and distracts from the application logic. Functional programming, on the end of the spectrum, completely hides the concept of memory forcing you to write your application as a pure function taking the events and old application state as input and producing the new application state. This forces you to think of your application in non-interactive terms, and you still have to manually make sure to compute the new state of each computed affected by the event.

Bindings and Reactive Programming

A binding between two components A and B is an assertion that whenever the state (value) of one component A changes, the state of the other component B is updated to match the state of A. Bindings can also involve more complex functions, e.g. if C is bound to A + B, then whenever the value of either A or B changes, C is set to the result of recomputing A + B. This paradigm is actually most widely used in spreadsheets where the value of a cell is a function of the values of other cells. 

Most GUI toolkits provide some support for simple bindings however they either lack the functionality for specifying bindings involving an arbitrary function of two or more components, or implementing such a binding requires implementing value "converter" or "transformer" interfaces in a lower-level language. This is usually so cumbersome that most programmers prefer to simply drop down to imperative programming.

Functional reactive programming languages are based on the idea of bindings involving arbitrary functions. Admittedly I haven't tried that many FRP languages, however those which I have tried seem to stick more closely to the traditional functional programming paradigm of implementing your application as a pure function. Few allow you to implement an application as a set of distinct nodes with bindings between the nodes.

Enter Tridash

The Tridash language aims to provide a simple and intuitive solution to the State Management Problem, which allows you to think of your application as an interactive application composed of live stateful, meaning they hold a particular value at a given moment in time, components called nodes.

Nodes can correspond to purely computational components or other stateful components such as UI elements, the network or the file system. Bindings between nodes, involving arbitrary functions of other nodes can be declared, using the '->' operator. Examples:
  • a -> b
  • a + b -> c
The first example demonstrates a simple binding in which: when the value of a changes, the value of b is updated to it.

The second example demonstrates a binding involve a function of two nodes. When the value of either a or b changes, c is set to the sum of a and b.

What sets Tridash apart is the free-form manner in which nodes can be declared. There is no main function just a set of declarations. Bindings can be declared between any pair of nodes.

More than just bindings between nodes, Tridash allows you to treat the bindings as nodes in themselves. Binding to a binding allows you to control which bindings are active. 

Example:

cond -> (a -> b)

In this example if cond evaluates to true the binding a -> b is active, whereas if it evaluates to false it is as if the binding does not exist, meaning changes in the value of a will not be propagated to b. This functionality is used to build a unique error handling scheme, in which bindings are deactivate in the case of an error.

In the next major release you'll also be able to establish bindings between a node and its past states.

The hello example presented earlier can be implemented simply using a single binding declaration.

"Hello: " + name-field.value -> greeting.textContent

where name-field.value is a node corresponding to the value of the text field UI node and greeting.textContent corresponds to the content of the UI node in which the greeting is displayed.

Programs as a whole are composed as a collection of a set nodes and bindings between the nodes. Changes in the value of a node, are automatically propagated to the nodes which are dependent on the node's value. This allows you to focus on the core application logic rather than the mechanics of propagating changes in state. The benefit of this is that the values of nodes which are not dependent on each other can automatically be updated concurrently by the underlying framework, without any additional work.

In conclusion the Tridash language presents a new view of your program, as a collection of live inter-connected components, which provides numerous benefits over the traditional view of your program as a linear sequence of instructions or a linear composition of functions.

Status

Tridash is currently at version 0.4 however it is still an alpha product and lacks the necessary features for building real-world applications, such as data-structures and a standard library. Currently only a JavaScript backend is implemented which uses HTML to provide a user interface. Other backends are planned for a future release.

Tutorials demonstrating the basic functionality of the language. Advanced tutorials and a reference manual are in the works.

Features planned for the next major release:
  • Data Structures: Lists, Maps, etc.
  • Macro System
  • Standard library containing math functions and other commonly used functions.
For installation instructions and tutorials head over to the project's wiki:
The name is a portmanteau of the words triangle and dash which are the two symbols comprising the bind operator ->, the main operator in the language. The > symbol somewhat looks like a triangle, right?