# Mixing data types

While drafting clauses in Clause9 is certainly not “programming” in the traditional sense, Clause9 borrows some best-practices from traditional programming languages. Legal experts who have never done any traditional programming are often confused by these practices.

One such issue is the concept of *data types* — aka the issue of *not mixing apples and oranges*. This page deliberately takes a deep-dive into dealing with these types, to fully explain how they work in Clause9.

## Natural language versus conditions & calculations

\
A first important idea to grasp is the distinction between *natural language mode* and *conditions/calculations mode*.

The standard mode in Clause9 is the natural language mode. This is the mode you will implicitly arrive in when starting to type something in a clause. It will consist of “human” language stuff, such as words in English/French/Dutch, punctuation and numbering, etc. For example, the following clause entirely consists of the natural language mode elements:

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2F9MDyxnxV2KJnpNsggPvz%2Fimage.png?alt=media&#x26;token=90f8126f-cd06-475f-9ed4-e390f6dfa0ed" alt=""><figcaption></figcaption></figure>

A clause that consists entirely of natural language mode elements will be completely static, i.e. aside from the numbering and formatting of the clause, this clause will not change appearance. To insert dynamic elements, you insert conditions and calculations, for example:

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FjK1u8luenofTOIUJYEk5%2Fimage.png?alt=media&#x26;token=4786988f-1bd8-4791-a0bd-e31ac132817a" alt=""><figcaption></figcaption></figure>

As soon as you type in an opening accolade **`{`** you will leave the natural language mode, and enter either

* the **condition mode**, for which the result’s type is always true or false); or
* the **calculation mode** (for which the result’s type depends on the kind of calculation being made).

In the example above, `#contract^value < 500 EUR` and `#contract^value < 2000 EUR` are written in the condition mode, while `apples^amount * #apples^unit-price` is written in the calculation mode.

After the closing accolade **`}`**&#x79;ou will in any case leave these modes, and return to the natural language mode. However, the switch between the modes is more complex than just looking at the opening and closing accolade. For example, in paragraph 1. above, the parts between the colon (`:`) and the vertical bar (`|`) are once again in the natural language mode, i.e. the words *low* and *medium* and *high*.

## Calculation mode

As the name implies, calculation mode expects to perform calculations. The input to these calculations consists of a mix of **countable elements** and optional **operators** — e.g. `5 + 24` or `5 * 4.5 EUR`, but also `12 months * 4` or `2020_11_23 + 3 days`, because you can perform interesting calculations with durations and dates.

Instead of using directly countable elements, you can also work with elements that ultimately boil down to numbers. For example, in `apples^amount * #apples^unit-price`, the datafields “`amount`” and “`unit-price`” can be assumed to contain countable things. When, for example, the number 5 would be assigned to `apples^amount` and the `#apples^unit-price` would be assigned the value 0.4 EUR, Clause9 will happily perform the calculation for you and return the result (2 EUR).

Note that natural text cannot, as such, be used in calculation mode. After all, text is — as such such — not countable. It does not make sense to, for example, perform a calculation to divide the words *“the Buyer buys an apple”* by the words *“the Seller sells a pear”*.

## Condition mode

Writing in the condition mode will be writing in calculation mode, with one exception. Condition mode is meant to ultimately result in *true* or *false*, and will therefore contain a **left side** **with a calculation**, a **comparison operator** and a **right side** **with yet another calculation**.

For example, in the condition `apples^amount * #apples^unit-price < 2000 EUR`, you will see a left side (containing a calculation on apples), a comparison-operator (smaller than <), and a right side (with a single currency-value).

### Data type

In Clause9, as in most programming languages, you can only calculate with elements of the same data type, and you can only compare elements of the same data type. For example, it does not make sense to add 25 EUR to a date, or to compare the text “alpha” to the duration of 5 months.

Clause9 offers the following basic data types:

| Data type             | Examples                               |
| --------------------- | -------------------------------------- |
| whole number          | `0`; `5`; `21456`                      |
| floating point number | `4.56`; `2457.8975`                    |
| currency number       | `0 EUR`; `56.34 EUR`                   |
| text                  | `"alpha"`; `"Main Street 56 Brussels"` |
| date                  | `5 January 2020`; `8 July 2022`        |
| duration              | `3 years`; `4 months`; `2 days`        |
| true/false            | `true`                                 |

In addition, the following special data types are also offered.

| Data type                                         | Example                                                                         |
| ------------------------------------------------- | ------------------------------------------------------------------------------- |
| list of elements (any of the other types allowed) | `5`, `6 EUR`, `3 January 2020`                                                  |
| clause text                                       | <p><code>1. Alpha</code><br><code>\* Beta</code><br><code>\*\* Gamma</code></p> |
| clause part                                       | `@ALPHA`                                                                        |
| defined term                                      | `#contract`                                                                     |
| datafield reference                               | `#contract^value`                                                               |
| nothing / undefined                               |                                                                                 |

The three different modes result in three different data types:<br>

| Mode                  | Result                                                                                  |
| --------------------- | --------------------------------------------------------------------------------------- |
| natural language mode | always results in *clause text*                                                         |
| calculation mode      | result type will depend on the elements used — e.g. `3 + 3` results in a *whole number* |
| condition mode        | always results in *true/false*                                                          |

## Supported currencies

Clause9 currently supports the following currencies:

| Currency             | Symbol used in Clause9 |
| -------------------- | ---------------------- |
| euros                | EUR                    |
| British pound        | GBP                    |
| United States dollar | USD                    |
| Japanese Yen         | JPY                    |
| Australian dollar    | AUD                    |
| Canadian dollar      | CAD                    |
| Swiss franc          | CHF                    |
| yuan                 | CNY                    |
| Kenyan shilling      | KSH                    |
| Hong Kong dollar     | HKD                    |
| New Zealand dollar   | NZD                    |
| Swedish krona        | SEK                    |
| South Korean won     | KRW                    |
| Singapore dollar     | SGD                    |
| Norwegian krone      | NOK                    |
| Mexican peso         | MXN                    |
| Indian rupee         | INR                    |
| Russian ruble        | RUB                    |
| South African rand   | ZAR                    |
| Turkish lira         | TRY                    |
| Brazilian real       | BRL                    |
| New Taiwan dollar    | TWD                    |
| Danish krone         | DKK                    |
| Polish złoty         | PLN                    |
| Thai baht            | THB                    |
| Indonesian rupiah    | IDR                    |
| Hungarian forint     | HUF                    |
| Czech koruna         | CZK                    |
| Israeli shekel       | ILS                    |
| Chilean peso         | CLP                    |
| Phillipine peso      | PHP                    |
| UAE dirham           | AED                    |
| Colombian peso       | COP                    |
| Saudi riyal          | SAR                    |
| Malaysian ringgit    | MYR                    |
| Romanian leu         | RON                    |

## Conversions between data types

While it is not possible to perform calculations or comparisons with elements of different data types, it is possible to convert an element to another data type. This conversion can either be done **explicitly** or **implicitly**.

### Explicit conversions

Explicit conversions can be achieved using [special functions](https://help.clause9.com/special-functions). For example, the special function `@extract-number` will take a *currency number* (e.g., `5.5 EUR`) and return the *floating point number* (`5.5`). Similarly, the sole purpose of the special function `@str` is to convert the argument passed to it into *text* — e.g. `@str(3 months)` will, depending on the styling settings, result in the *text* `3 months` when the active language is English.

{% hint style="info" %}
At first glance, this may look like nothing changed; under the hood, however, the type of this element changed from a *duration* to a *text*, meaning that the operations that can be applied to a *duration* element (e.g., addition or subtraction) will suddenly no longer work, while the operations that can be applied to a *text* element (e.g., capitalization) will suddenly become possible.\
\
If the active language is not English, the conversion will be much more visible. For example, `@str(3 months)` may also be converted to *“trois (3) mois”* in French, with a styling setting where numbers are always converted to both letters and numbers.
{% endhint %}

Most special functions will perform something more than solely converting an argument from one data type to another data type. Examples:

* `@round` and `@floor` will convert the *floating point number* passed to them, and then either round that number or truncate the decimal part, returning a *whole number*
* `@comma-split` will take a *text* element and return a *list* element that contains individual text elements (e.g. `@comma-split("alpha, beta, gamma")` will return a *list* with *text* elements `"alpha"`, `"beta"` and `"gamma"`.

### Implicit conversions of basic data types

It would be cumbersome to always have to explicitly convert data types — e.g., imagine that in order to take 5.5 times the duration of a contract, you would have to write `5.5 * @float(@months-in(#contract^duration))`

{% hint style="info" %}
The underlying reasoning is as follows: you are performing a multiplication of a *floating point number* and a *duration*, which is not possible. There exists a special function `@months-in` that takes a duration and returns a *whole number* that corresponds to the amount of months in that duration. However, you would then have to perform yet another conversion from this *whole number* to the *floating point number*. You would therefore have to use the hypothetical `@float` function.
{% endhint %}

To avoid these situations, Clause9 will implicitly perform conversions for you when no ambiguity is involved:

| Data type 1       | Data type 2       | Resulting data type | Example                                                                         |
| ----------------- | ----------------- | ------------------- | ------------------------------------------------------------------------------- |
| whole nr          | floating point nr | floating point nr   | `5 + 5.5` results in `10.5`                                                     |
| whole nr          | currency nr       | currency nr         | `200 + 300 EUR` results in `500 EUR`                                            |
| floating point nr | currency nr       | currency nr         | `229.5 + 300 EUR` results in `529.5 EUR`                                        |
| date (\*)         | duration          | date                | `2018_7_12 + 1 month` results in `2018_8_12`                                    |
| list (\*\*)       | (any data type)   | list                | `@list("alpha", "beta") + "gamma"` results in `@list("alpha", "beta", "gamma")` |

* (\*) When mixing a date with a duration, note that the order and operation matters. The conversion will only be applied with `date +/- duration`. If you change the ordering (e.g., duration first) or the operation (e.g. multiplication), the result will be an error.<br>
* (\*\*) When mixing a list with, the order and operation matters: the conversion will only be applied with `list +/- element`, not with `element +/- list`.
  * When using the `-` operator, the element(s) at the right side are removed from the list at the left side. For example, `@list("alpha", "beta") - "alpha"` and `@list("alpha", "beta") - @list("alpha")` both result in `@list("beta")`.
  * When using the `+` operator, the result depends on the right-side:
    * If both the left & right side are lists, then the result will be a *concatenation* of the two lists, with all the elements of the right list appended to the left list, irrespective of whether they were already present in the left list. For example, `@list("alpha", "beta", "gamma") + @list("alpha", "delta")` will result in `@list("alpha", "beta", "gamma", "alpha", "delta")`. (If you want a *union* of the list, where elements-already-present are not added again, use the `@union` special function instead of +).
    * If the right side is not a list, then it will be added as a new element of the left list, irrespective of whether the right side element was already present in the list. For example, `@list("alpha", "beta") + "alpha"` will result in `@list("alpha", "beta", "alpha")`. (If you want a *union* of the list and the single element, where the right-side element is not added again to the left list, use the `@union` special function instead of +).

### Implicit conversions of undefined

When using datafields, values will often not be present, because they have not (yet) been filled in by the end-user. Within a calculation/condition, to avoid errors, Clause9 will try to convert this undefined value to a sensible default value:

| **Datatype** | **Converted into**     | **Example**                                                                                                                           |
| ------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| number       | 0                      | `55 * undefined` results in *0*                                                                                                       |
| currency     | 0 (same valuta)        | <p><code>5 EUR + undefined</code> results in <em>5 EUR</em><br><em><code>5 EUR \* undefined</code></em> results in <em>0 EUR</em></p> |
| duration     | duration with length 0 | `5 days + undefined` results in *5 days*                                                                                              |
| text         | empty text             | *empty text is simply ignored in the output*                                                                                          |
| list         | empty list             | `@list("alpha") + undefined` results in `@list("alpha")`                                                                              |

{% hint style="danger" %}
Note that the date field is missing from the table above: an undefined will never be implicitly converted to a date field. (After all, there exists no date that would make sense here: what could possibly be considered “date zero”?)
{% endhint %}

{% hint style="info" %}
Tip: when you do not like these implicit conversions of unavailable values inside a calculation, you may want to use [an exclamation point after the hash](https://help.clause9.com/special-codes#exclamation-marks-before-datafields).\
\
For example, while you may be happy with `{#apples^amount * 0.2 EUR}` resulting in 0 EUR when the amount of apples has not yet been completed by the end-user, it may equally be the case that you absolutely need the user to fill in this amount. If so, then use `{#apples^!amount * 0.2 EUR}` instead — this will result in a box that invites the user to fill in this value, signaling that the calculation simply cannot be completed without a value assigned to the amount of apples.
{% endhint %}

### Implicit conversions to true/false in a condition

In condition mode, the following implicit conversions are carried out to convert a data type to true/false:

| Data type                                 | Converts to *true* when | Converts to *fals*e when           |
| ----------------------------------------- | ----------------------- | ---------------------------------- |
| Text                                      | Non-empty text value    | Equal to the empty-text value (“”) |
| (Whole/floating/currency) number          | Not equal to 0          | Equal to 0                         |
| Duration                                  | Amount higher than 0    | Amount equal to 0                  |
| List                                      | Not empty               | Empty (no elements)                |
| Date                                      | Assigned some value     | Never                              |
| Undefined (e.g., datafield without value) | Never                   | Always                             |

Note that in an *if-then-else* condition, you can omit the operator and right-hand side of the comparison for the sake of brevity; Clause9 will then automatically insert `= true`. For example:

* Instead of writing `{#contract^is-dutch-law = true: ... }` you can also write `{#contract^is-dutch-law: ... }`. If the datafield `is-dutch-law` is a *true/false* datafield, then no implicit conversions will occur.
* Instead of writing `{#contract^value > 0: ... }` you can also write `{#contract^value = true: ... }` or the shorter version`{#contract^value: ... }`. In both of these cases, the `contract-value` *whole number* datafield will be converted into a true/false, meaning it will result in *true* if a non-zero value is assigned to this datafield; it will instead result in *false* when no value is assigned at all, or when the value that is assigned to this datafield, is equal to zero.

### Implicit duration conversions

When combining *duration* elements of different units in a calculation, conversions may be necessary — e.g., when you add `2 days` to `3 months`. You should be aware that such conversions will in many cases result in rounding errors and unexpected results, because a duration does not contain any context about the month or year it relates to.

Clause9 will convert durations with different units into the lowest time unit, e.g. *year + months* will be converted to months, *year + days* will be converted into days, and *months + weeks* will be converted into weeks. Clause9 tries to use sensible averages during this conversion, but unexpected results are bound to happen due to the lack of context.

**The bottom line is that you should try to avoid these implicit conversions as much as possible.**

{% hint style="info" %}
For example, Clause9 happens to convert `27 months + 1 day` to 822 days, because it first converts 27 months to two years (= 730 days) and 3 months (= 3 times average of 30.417 days, so 91 days), and then adds yet another day. An equally sensible result would, however, be 811 days (= 27 \* 30 days + 1 day).\
\
Similarly, Clause9 happens to convert a month into 4.345 weeks, so that `3 months + 1 week` gets converted to 14 weeks. Other software or people would perhaps answer 13 weeks.
{% endhint %}

### Implicit conversions to clause text

Clause9 allows you insert a datafield directly into natural text. For example:

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FxQNwOq3mhq39KP8Hd1VS%2Fimage.png?alt=media&#x26;token=408d9e63-419a-42d3-88a4-6081e1ae6465" alt="" width="375"><figcaption></figcaption></figure>

While perhaps not immediately obvious, this is also a situation where apples (clause text) are combined with oranges (number datafield). To avoid that you would have to insert all kinds of ugly codes to allow this, Clause9 will implicitly convert this datafield into clause text for you.

In most situations, this conversion will be very straightforward. However, do note the following.

* A (whole/floating point/currency) *number* and a *date* value be converted into text in accordance with the locale styling rules (e.g., for the decimals style, currency symbol placement, short/long date format, etc.).
* A *true/false* value will get translated — e.g., `Alpha {true}.` will be converted into `Alpha true` in English and `Alpha vrai` in French.
* A *list* value will have its elements printed consequentially with spaces in between — e.g. `@list("alpha", "beta", "gamma")` will be converted into `alpha beta gamma`. If you want to have comma’s plus and/or etc. in such list, or perhaps convert it into a bullet-list, then you need to use one of the special functions — e.g., `@enumerate-andor(@list("alpha", "beta", "gamma"))`.

### Avoided implicit conversions

Some conversions are deliberately not performed, because they would be ambiguous:

* Adding a (whole/floating/currency) number to a duration or date. For example, `3 months + 3` results in an error because it will be difficult for the software to figure out whether you want the result to be a duration (6 months) or a whole number instead (6).
* Adding a number to a date. For example, `2020_04_07 + 3` results in an error, because it is not clear whether you would like to add 3 years, 3 months, 3 weeks or 3 days instead.

Other conversions are deliberately not performed because they make no sense:

* Mixing *text* and *whole/floating/currency numbers*. It will usually be obvious that this does not make sense — e.g. `"alpha" + 6` — but this may not always be intuitive to those new to Clause9.\
  \
  For example, if you create a *text* datafield `#contract^value`, then Clause9 will treat the contents of this datafield as text, and issue an error when you try to do a calculation such as `#contract^value * 2`. This error will make perfect sense when the end-user would type in “real” text (such as the word *“Paris”*), because you can obviously not multiply Paris by two. However, when an end-user would type in a number (e.g., 3500), then it will not be so obvious why the software is complaining.

### Disallowed operations

While not a data type conversion issue, you should also note that some operations are not allowed between elements of the same data type:

* You cannot mix different currencies — e.g., adding `{200 EUR + 300 USD}` results in an error.
* You cannot add dates to each other — e.g. `{2020_04_03 + 2020_05_3}` results in an invalid operation error.

## Dealing with the data type of if/then/else

An if/then/else construction will normally result in clause text. For example,

{% code overflow="wrap" %}

```
1. Upon drafting @CONTRACT, the parties agreed to have @CONTRACT screened by the authorities. If @CONTRACT would turn out to be ...

CONTRACT = {#contract^with-annexes: this Employment And Restructuring Contract (ERC) including its annexes | else: this ERC}
```

{% endcode %}

The contents of the [internal snippet](https://help.clause9.com/clauses/snippets) CONTRACT will be clause text, because its sole element is an if/then/else construction between curly braces. Such clause text can be inserted into the main body of the clause without any conversion being necessary.

However, it is also possible to use the if/then/else construction to return other data values. You can do this by wrapping the content of the if/then/else after the colon (:) between curly braces. For example:

{% code overflow="wrap" %}

```
1. Buyer will pay an amount equal to {@INTEREST * 1.5} before 1st January. If this payment is not successfully performed, it will be automatically increased to {@INTEREST * 2}.

INTEREST = {#contract^jurisdiction = "dutch": {0.05 * #contract^value} | else: {0.08 * #contract^value} }
```

{% endcode %}

It is interesting to analyse why you will get a *“value is not a number”* error when you omit the two pairs of curly braces in the if/then/else construction:

{% code overflow="wrap" %}

```
1. Buyer will pay an amount equal to {@INTEREST * 1.5} before 1st January. If this payment is not successfully performed, it will be automatically increased to {@INTEREST * 2}.

INTEREST = {#contract^jurisdiction = "dutch": 0.05 * #contract^value | else: 0.08 * #contract^value }
```

{% endcode %}

The reason is that Clause9 will do the following:

* When encountering the `{@INTEREST * 1.5}`, it will replace the @SNIPPET with the contents of the internal snippet, arriving at `{#contract^jurisdiction = "dutch": 0.05 * #contract^value | else: 0.08 * #contract^value } * 1.5`
* It will then execute the if/then/else construction, and check whether the contract’s jurisdiction is equal to “dutch”. Assuming this is indeed the case, Clause9 will notice that the associated fragment it has to insert into the main part of the clause is `0.05 * #contract^value`.
* Because this fragment is not wrapped in curly braces, Clause9 will treat the fragment as clause text. For example, if the contract’s value is currently set to 1000, and the current styling happens to be metric, it would convert the fragment into the text *“0.05 \* 1.000”* . Notice that:
  * because the fragment is treated as clause text, Clause9 will treat the 0.05 literally, i.e. not consider it to be a number. Accordingly, despite the fact that the styling settings are set to metric (so that a floating point number such as 0.05 would be printed with a comma as “0,05”), Clause9 will print it as “0.05”
  * the contract’s value (1000) is a *whole number* that is inserted into clause text, and will therefore get converted to clause text, respecting all the styling settings (such as the metric style’s dot between the 1 and the three zeroes)
* Next, it will try to multiply the clause text *“0.05 \* 1.000”* by the number 1.5, which obviously does not make sense because you cannot multiply text by a number. It will therefore issue a warning *“value is not a number”*.

`Pursuant to article 3§4 of the Civil Code, #Buyer shall ...`

## Examples

Why is `shall pay 10.20 EUR` printed as “shall pay 10.20 EUR”, while my styling settings dictate metric style with a euro-symbol?

Why do I see an error message with `Pursuant to article 3§4 of the Civil Code, #Buyer shall ...` ?

I get an *“incompatible argument types”* error when using the following clause:\
\
`#Buyer shall pay interest equal to @days-between(#contract^start-date, @today)`

The software does not accept the following clause (shows a yellow error):\
\
`#Buyer shall pay interest equal to @days-between({#contract^prolonged: #contract^prolongation-date | else: #contract^start-date}, @today)`
