# Custom functions

While Clause9 provides an array of powerful features to build documents, it can sometimes be useful to resort to a full-fledged programming language.

For such situations, Clause9 allows you to develop functions and conditions in (a subset of) the [Clojure programming language](http://www.clojure.org/), and its close sibling [ClojureScript](https://clojurescript.org/).

## How to get started

Clojure is one of the most powerful programming languages in the world. Although it is much less popular than the mainstream programming languages — Java, C#, C, Python, etc. — and its LISP-based, functional nature will be quite unfamiliar to many developers, it is actually not so difficult to get started with in the context of Clause9.

* For a quick introduction, we recommend to read the [ClojureDoc introduction tutorial](https://clojure-doc.org/articles/tutorials/introduction/).
* For a more in-depth introduction, we recommend to read Chapters 3, 4 and 5 of the excellent (and free) book [Clojure for the Brave and True](https://www.braveclojure.com/clojure-for-the-brave-and-true/).

## Technical setup and limitations

Clause9 exposes only a subset of the Clojure / ClojureScript, through the [Small Clojure Interpreter](https://github.com/borkdude/sci). What you write, will run in either a browser environment (for the graphical user interface), or in a server environment (when exporting documents, e.g. to .DOCX). For the sake of conciseness, we will however only refer to Clojure in the remainder of this document.

Most of the core functions of Clojure are supported. In addition, many other Clause9-specific functions are available to you (see below), to make use of the advanced features of Clause9.

The following Clojure features are either irrelevant, or simply not available to you, when developing in Clojure from within Clause9. When reading about Clojure, you can therefore completely skip any discussions about them:

* namespaces — within Clause9, your functions are hosted in more confined containers that are given a specific name
* the so-called “REPL” — instead you can get some interactive output through your browser’s development tools
* multi-threading tools, such as “futures”, “promises”, threads, pmaps, etc.
* calls to the host environment (the JDK at server side, the DOM/JS environment at browser-side)
* any asynchronous function calls, with the exception of some HTTP calls in the Q\&A mode at browser-side
* most functions that cause side-effects

{% hint style="info" %}
Be aware that the invocation of custom functions is handled as a black box. With the exception of the *println* function for debugging, and a few exceptions in the Q\&A environment (e.g., calls to set-answer, focus, and show-error/warning/info), the execution of Clojure-functions cannot modify the Document/Binder/questions, and will not cause side effects.
{% endhint %}

## Accessing custom functions within a clause

If your user profile allows you to do so, you can add one or more custom functions to any clause. A custom function must be given a unique name within the file, and can then be called from the content title, content body or enabled-condition, using either the special function `@clj` or `@cljr`.

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FEvLl88xsWoYJFG8Z0J5v%2Fimage.png?alt=media&#x26;token=e7cbb403-ad9c-4484-9027-5db481fc4e55" alt="" width="563"><figcaption></figcaption></figure>

The only difference between those @functions is that the `@cljr` will always re-execute upon any recalculation of the underlying Document/Binder, which can be useful if the output of the custom function does not exclusively depend on the other arguments passed to `@clj`. (Clause9 will automatically recalculate when one of the arguments passed to `@clj` would change, but since the Clojure-functions act as a kind of “black box” towards the recalculation engine, it cannot know in which other situations it should recalculate — hence the need for `@cljr`).

* The optional first argument should be a hashtag that refers to a file. When left out, the invoked custom function will be presumed to be present in the same clause.
* The second argument should be the name of the custom function.
* The optional other arguments act as parameters to the custom function.

For example, `@clj(#xxx, "alpha", 5, 1 day)` would call custom function “alpha” within the file referenced by hashtag #xxx, passing as arguments the number 5 and the duration *1 day* to that custom function. Conversely, `@clj("beta", 6)` would call custom function “beta” in the same clause file, passing argument 6 to that custom function.

Within the custom function (i.e., within the Clojure environment), arguments passed to it can be accessed through the vars `$1`, `$2`, `$3`, etc. If several parameters are used, you probably want to define another var for the sake of clarity — e.g., `(def contract-value $1)` — and then use Clojure-var contract-value instead of the cryptic `$1`.

## Using custom functions in the Q\&A environment

Custom functions can be used in several places in the Q\&A environment.

### Condition attached to a card, question, predefined answer or change set

Any (sub)condition can refer to a custom function in Clojure. You simply choose “custom function” in the condition type, and insert some Clojure code. This code eventually needs to return a “truthy” value in the traditional Clojure sense (i.e., anything besides `false` or `nil` will result in true).

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FTSheGB0fjs3EbGpWpKCw%2Fimage.png?alt=media&#x26;token=991d8284-e944-4af9-bc5a-f422c587ee5e" alt="" width="563"><figcaption></figcaption></figure>

### Customising the properties of a question, card or predefined answer

While Clause9 allows you to finetune the properties of a card(e.g., its title, color or indentation), a question (e.g., its title or help text) or predefined answer (e.g., its label or value), it is not possible to change these properties dynamically. Custom functions can provide relief, however.

The customisations, if set, are calculated right before the card/question/predefined-answer is being shown. The Clojure code gets passed the current record (card, question or predefined answer), can optionally modify that record, and return it.

{% hint style="danger" %}
As is customary in Clojure, Clause9 does not hide the fact that there are several other fields present in the record besides the fields mentioned below. Please refrain from changing these properties, as they are internal implementation details that are crucial for a correctly functioning Q\&A.
{% endhint %}

You **customise a card** by showing the card’s options and clicking on the *add card customization* button. The Clojure code you insert, should then return a modified version of the predefined `card` var that is made available to the Clojure runtime.

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FhmqWmxHRYoHtN5AOuvtu%2Fimage.png?alt=media&#x26;token=bf9e7728-e0be-4287-878f-76bc1010ddc7" alt="" width="563"><figcaption></figcaption></figure>

The following card properties can be changed:

* `:title`, an i18-map
* `:separator?` to show a dividing line above a card
* `:color` to determine the color of the card — `:green`, `:red`, `:orange`, `:grey`, `:black`, `:brown`, `:purple`, `:magenta`, `:light-blue`, or `:dark-blue`
* `:indent-left`, which can be set to 1, 2 or 3 to indent the card

Similarly, you can **customise a question** by showing the question’s options and clicking on the *add question customization* button. The Clojure code you insert should then return a modified version of the predefined `question` var that is made available to the Clojure runtime.

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FaOEQBjMR5as23X0mig3l%2Fimage.png?alt=media&#x26;token=443ff363-924f-4932-b0df-d65cb2f027d3" alt="" width="563"><figcaption></figcaption></figure>

The following question properties can be changed:

* `:title` and `:help` are i18-maps
* (number questions only) the `:min-value` and `:max-value` integer properties
* (text questions only) the `:textarea?` boolean property, which corresponds to the *show a large answer box* setting of a question
* `:storage-only?` hides a question, even if it is active (i.e., its own condition and the condition of its card, if any, is met)
* `:disallow-free-answering?` can be used to disable free answers, allowing only predefined answers
* `:on-apply-service-instance` is a function that takes the following arguments: the question from which a service-integration (e.g., spreadbase) is being launched; the row-index (zero-based, `nil` if the question is not a table-based answer), the col-index (also zero-based and `nil` if the question is not a table-based answer) and a map with data that is selected by the end-user.

  This custom function is useful to modify how the value that is selected by the end-user through the service)-integration, gets “distributed” (pasted onto) the other answers in the Q\&A — e.g., for situations where the standard [*receive* tags](https://help.clause9.com/integrations/spreadbases) mechanics are not sufficient for your purposes. In such case, you could create a custom-function that directly performs several `set-answer` to modify the answer.

  If this custom function returns a *truthy* value, the normal distribution of the selected value will follow its course (i.e., copying the relevant value to those questions that have an appropriate *receive* tag). If instead a non-truthy value is returned, the normal distribution is skipped.

In addition, the following properties can be set for **table-based questions**:

* `:force-direction` can be set to `:horizontal` or `:vertical` to force the table to be shown in a horizontal or vertical manner. Please note that when you set `:column-pred-fn` or `:column-caption-fn`, the direction will be automatically forced to `:vertical`.
* `:column-pred-fn` is a function that receives as arguments a question, row-index (integer), column-index (integer) and answers-map (map from row-index to (map of col-index to value)). It should return true/false to indicate whether the column should be shown.
* `:column-caption-fn` is a function that receives as arguments a question, row-index (integer), column-index (integer), answers-map (map from row-index to (map of col-index to value)), the default caption, and the language (keyword) in which the questions are currently displayed. It should return a string.
* `:on-add-row-fn` is triggered when the user clicks the green “+” button to add a new row. It receives as arguments the current question, the new number of rows (i.e., the old number of rows + 1) and the answers-map. It is expected to return a (probably updated) version of the answers map in which, presumable, at least one new row is inserted.

You can **customise a predefined answer** by clicking on the customisation icon at the right side. The Clojure code you insert, should then return a modified version of the predefined `predef` var that is made available to the Clojure runtime.

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FK5y5C1A2OLxyElwJ0IV9%2Fimage.png?alt=media&#x26;token=ab0f8de8-440c-47f0-b34e-5e45149badeb" alt=""><figcaption></figcaption></figure>

The following properties can be set:

* the `:value` field, for which the datatype depends on the type of question (boolean, integer, FloatValue, CurrencyValue, string, i18-map, Date or Duration)
* the `:title`, which is an i18-map. Note that if no `:title` is available, Clause9 will use a string-representation of the value as the title (label) to be presented towards the end-user.

Instead of customising an already-defined predefined answer, you can also dynamically **change the list of predefined answers** that should be shown. This is done at the level of the question, by setting the `:predef-values|labels-fn` field of the `question` var that is passed to the Clojure runtime.

* The arguments it receives are the Question, row-index (integer), column-index (integer), answers-map (map from row-index to (map of col-index to value)), default predefined values and default predefined labels.
* It should return a tuple of `[predefined-values, predefined-labels]`.

### Validating answers

It is possible to validate “free text” answers of by setting the `:validate-fn` field of a question. When set, this function receives as its arguments the question and the new value. It should then return a “truthy” value to indicate whether or not the value should be accepted.

{% hint style="success" %}
If the value is not accepted, it is probably also a good idea to invoke the *(show-error …)* or *(show-warning …)* functions discussed below, to alert the user that the value was rejected.
{% endhint %}

### Executing actions upon setting an answer

When an answer is set (optionally preceded by a validation phase), it is possible to execute a custom function. The typical scenario is that some other answers should also be changed, e.g. to avoid inconsistency.

Such additional action can be triggered by setting the `:action-fn` field of a question. The arguments it receives are the question that was answered, as well as the value that was set. After the function has executed, recalculation is automatically performed, so it is not necessary to invoke `(recalc)` manually.

### Building a custom question interface

You can build custom interfaces for questions through a [custom interface function](https://help.clause9.com/dev/broken-reference).

### Centralising custom functions

When a custom function should be invoked by different parts of a Q\&A, it is probably a good idea to store it centrally, to avoid having to manually change the same function in multiple locations.

Custom functions are centrally managed in the *repository* pane, subsection *custom functions*.

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FyvDHWhKOCDRPMaIcy17K%2Fimage.png?alt=media&#x26;token=8155ac19-ebc3-43c5-b811-210b896720d7" alt="" width="375"><figcaption></figcaption></figure>

Once centrally stored, custom functions can be invoked through `(call ...)`. For example, to invoke the custom function called “custom-function2” in the screen shot above, with arguments 5 and 33, you would use `(call "custom-function2", 5, 33)`.

## Executing custom functions

Within the custom function you can write Clojure functions however you like — within the limitations set forth above. The result of the custom function should be one of the following:

* in the Q\&A environment for conditions: a “truthy” value in the traditional Clojure sense (i.e., anything besides `false` or `nil` will result in true)
* in the Q\&A environment for a custom interface: a Hiccup-style vector (see explanations below)
* in the clause environment:
  * nil
  * a string
  * an IntValue, FloatValue or CurrencyValue
  * Clojure integer or double
  * a Date or Duration
  * any of the Clause9 grammar data structures (see below)
  * a vector of any of the above

## Accessing Clojure functions

* All `clojure.core` functions are accessible without a namespace alias.
* The `clojure.string` functions are aliased as `str`.
* Printing output to the browser’s console is done using `pprint`.

In addition, see the specific Clause9 functions described below.

## Clause9 grammar data structures

The following data structures for constructing grammars are available, to allow you to programmatically define paragraphs, bullets, tokens etc. — as if you would be constructing them using the regular Clause9 grammar style.

{% hint style="info" %}
Terminology for understanding the functions below: a “token” is a part of a sentence, such as a defined term or some plain text, while a “record” is any kind of element that can be created using the functions below.
{% endhint %}

* **paragraph construction**
  * `->Paragraph` creates a plain paragraph block without a number or bullet. Parameters: one or more tokens.
  * `->Paragraphs` creates a collection of (plain, numbered or bulleted) paragraphs. Parameters: one or more paragraphs.
  * `->NrParagraph` creates a numbered paragraph. Parameters:
    * either a number, or a collection of numbers
    * one or more tokens
  * `->BulletParagraph` creates a bulleted paragraph. Parameters:
    * the bullet-level (integer)
    * one or more tokens
  * `->Snippet` creates a snippet, which is a container for various records. The parameters consist of one or more tokens.
  * `->InsertionGroup` is a container for various other records. Parameters:
    * a vector of elements
  * `->Endnote` and `->Footnote` create an endnote or footnote, respectively. The sole parameter is an insertion-group.
* **token constructionin general**
  * `->Alert` creates an alert record, e.g. for warnings. Its sole parameter is the body of the alert (string).
  * `->DynamicNr` creates a dynamic number, i.e. a number that is either printed as a number or spell out in full. The sole argument is an integer.
  * `->ImageFile` creates an image token that refers to an existing file. The sole parameter is a defined-term that links to that file (see `term` below).
  * `->ImageURL` creates an image token that refers to some URL on the internet. The sole parameter is a string with the URL.
* **references creation**
  * `->ConceptImplReference` and `->ConceptDefReference` create a reference, respectively to a Concept’s implementation clause or definition. Parameters:
    * a defined term, retrieved through `term`
    * the capitalization — either `:none`, `:initial`, `:all-words` or `:all`
  * `->MainBodyReference` creates a reference to the main body of a Binder. No parameter.
  * `->TagReference` creates a reference to a clause that implements a tag. The sole parameter is this tag (string).
* **token modification**
  * `->Capitalizator` modifies the capitalisation of the text within its element. Parameters:
    * some record
    * one of the following keywords: :none, :initial, :all-words or :all
  * `->Bold`, `->Italic` and `->Underlined` creates a special element in MS Word. The parameters should consist of one or more tokens.
* **tableconstruction**
  * `->Table` constructs a table. It takes one or more table-rows as its parameters.
  * `->Row` constructs a table-row. It takes one or more cells as its parameters.
  * `->Cell` constructs a table cell. It takes one or more tokens as its parameters.
* **predefined answers in Q\&A**
  * The following functions create predefined answers, for pre-populating a question. For each of those functions, the ID parameter must be a negative integer between 0 and -100000, and this ID must be unique among the predefined values of that question.
  * `->BoolAnswer` takes an ID and true/false
  * `->IntAnswer` takes an ID and an integer
  * `->FloatAnswer` takes an ID and a FloatValue
  * `->CurrencyAnswer` takes an ID and a CurrencyValue
  * `->StringAnswer` takes an ID and a string
  * `->i18StringAnswer` takes an ID and an i18-map
  * `->DateAnswer` takes an ID and a Date value
  * `->DurationAnswer` takes an ID and a Duration value

## Other data structures

* `->IntValue` creates an IntValue. The sole parameter is an integer.
* `->FloatValue` creates a FloatValue. The sole parameter is an integer that represents the floating value with 4 decimals — e.g. 123456 represents 123.456
* `->CurrencyValue` creates a CurrencyValue. The parameters are:
  * an integer that represents the value with 4 decimals — e.g. 123456 represents 123.456
  * a keyword that refers to the currency — currently `:EUR`, `:GBP`, `:USD`, `:JPY`, `:INR` or `:CAD`
* `->Duration` creates a Duration value. The parameters are:
  * an amount, a positive integer
  * a time-unit: either `:year`, `:month`, `:day`, `:week` or `:quarter`
* `->Date` creates a Date value. The parameters are three integers, respectively for year / month / day.
* an “i18-map” is a Clojure map in which strings are stored for multiple languages. The key is a two-letter keyword: depending on the subdomain on which Clause9 is hosted, this will be `:en`, `:fr`, `:nl`, `:de`, `:es` or `:lt`

## Clause9-specific functions

### Debugging

* `?` prints its argument to the browser console, and then returns its argument
* Clojure’s standard `println` function is also available for printing to the browser’s console

### Data structures

* check for identity with any of the following functions:
  * `Alert?`
  * `Bold?`
  * `BoolAnswer?`
  * `BulletReference?`
  * `Capitalizator?`
  * `Cell?`
  * `ConceptDefReference?`
  * `ConceptImplReference?`
  * `Conjugation?`
  * `CurrencyAnswer?`
  * `CurrencyValue?`
  * `Date?`
  * `DateAnswer?`
  * `DefinedTerm?`
  * `Duration?`
  * `DurationAnswer?`
  * `DynamicNr?`
  * `Enumeration?`
  * `EnumSnippet?`
  * `FloatAnswer?`
  * `FloatValue?`
  * `i18StringAnswer?`
  * `Image?`
  * `IntAnswer?`
  * `IntValue?`
  * `Italic?`
  * `LineBreak?`
  * `MainBodyReference?`
  * `NrsetReference?`
  * `Paragraph?`
  * `PlainText?`
  * `Row?`
  * `Snippet?`
  * `StringAnswer?`
  * `Superfluous?`
  * `Tab?`
  * `Table?`
  * `TagReference?`
  * `TermField?`
  * `ThisArticleReference?`
  * `Underlined?`

### Q\&A

* `card?` checks whether the given identifier refers to an enabled card
* `question?` checks whether the given identifier refers to an enabled question
* `change-set?` checks whether the given identifier refers to an enabled change-set
* `answer` results in the current value (answer) of the question referred to by the given identifier. Note that the answer to a table-based question is structured as `{row-index {col-index value}}`.
* `set-answer` allows you to modify the change the answer to a given question. The first argument should be the question-identifier (string), the second parameter either a value or an update-function on the current value. You should also invoke `recalc` once you are done changing answers (except if the `set-answer` was invoked as part of an `:action-fn`, because action-fn automatically invokes recalc).
* `show-error`, `show-warning` and `show-info` allow you to show alerts at the bottom of the browser screen, in different styles. Their sole argument is the message (string).
* `focus` (sole argument is the question’s identifier) allows you to highlight and then focus on a specific question
* `gui-lang` and `output-lang` return the current language used in the cards or output, respectively

{% hint style="info" %}
In the bullets above, “identifier” refers to the optional identifier that can be given to cards and questions (accessible through the card’s or question’s options). The identifier should be a unique string that allows to immediately pinpoint a certain card or question.
{% endhint %}

### Export of documents

* `export-docx`  (no arguments) renders the document at the server and then downloads the document as DOCX in the user's browser
* `export-pdf`  (no arguments) renders the document at the server and then downloads the document as PDF in the user's browser
* `export-docx-in-browser`  (no arguments) renders the document within the browser and downloads the document as DOCX in the user's browser
* `export-pdf-in-browser`  (no arguments) renders the document within the browser downloads the document as PDF in the user's browser
* `export-post` renders the document at the server and subsequently sends the document to some webhook. The following arguments must be passed in a map:&#x20;
  * `:url` mandatory, the URL where to perform the POST
  * `:format` mandatory: either `:docx` or `:pdf` or `:html`
  * `:additional-data` optional, a map with data with some custom internal information that will be passed on to the webhook. You  may, for example, want to pass on some internal identifier as a string,  or perhaps a map with numbers, or ... Note that the `exportIdentifier` that you can include when creating a magic-link through the API (called the *identifier for reporting purposes* in the GUI dialog box for creating a magic-link) will automatically be included as the *:export-identifier* in this map)&#x20;
  * `:on-success` optional, a function (no params required) that will be executed client-side when the rendering & submission is successful
  * `:sign-positions?` optional: if set to `true`, then a map with `sign-positions` will be included describing the positions of all `@sign` invocations

Example of how you may want to use `export-post`:

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FJABEhqByfhDAklIqbD5Y%2Fimage.png?alt=media&#x26;token=e278503a-961a-4215-bd61-2721b147d265" alt=""><figcaption></figcaption></figure>

The POST-call that will be performed, will have the following structure:&#x20;

* `document` contains the Base64-version of the document (PDF or DOCX)
* `additional-data` contains the additional data described above
* `qna-id` contains the file-ID of the Q\&A
* `answers` contains the answers given by the end-user for the non-disabled questions. The structure is equivalent to the `QnaValue` data structure described in [Swagger](https://help.clause9.com/dev/clause9-api#using-the-swagger-sandbox).
* `sign-positions` (only present if `:sign-positions?` was set to `true`) will be a JSON dictionary containing keys:

  * `page-width` and `page-height`, both measurements in points&#x20;
  * for each identifier passed to `@sign`, a sub-dictionary containing keys `x`, `y`, `width`, `height` (all measurements in points) and `page`&#x20;

  For example, when `@sign("licensee")` and `@sign("licensor")` were used somewhere in the document, the following example output could follow:

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FcDMqnxV6A22vLV0MqJBW%2Fimage.png?alt=media&#x26;token=8baa26d0-472a-4dbc-b791-e819049702a7" alt="" width="325"><figcaption></figcaption></figure>

### Datafields, defined terms and custom function calls

* `call` allows you to call another custom Clojure-function. The first argument should be a simple argument (see below), the rest of the arguments are the actual parameters for the called function.
* `datafield` (only available within the environment of a clause) allows you to retrieve a certain datafield. Its argument should be a compound argument.
* `value` (with, as its sole argument, a datafield obtained through `datafield`) allows you to retrieve the current value of a datafield
* `term` (only available within the environment of a clause) allows you to refer to a certain defined term. Its argument should be a string with the defined term.
* simple and compound arguments are always Clojure strings
  * in the environment of a clause:
    * a simple argument should refer to one of the custom functions defined in the same file — for example, `(call "xxx", :alpha)` would call custom function “xxx” (defined in the same file) with as its single argument the keyword `:alpha`.
    * a compound argument should consist of the name of the referenced file, a slash (/) or circonflex (^), and the name of the custom function or datafield within the referenced file. For example, `(call "alpha/xxx", :alpha)` would call the custom function “xxx”, with the single argument keyword `:alpha`.
  * in the Q\&A environment:
    * a simple argument should refer to one of the custom functions defined in the Q\&A’s repository pane
    * a compound argument should consist of the name of the file (as defined in the *file links* of the Q\&A’s repository pane), a slash (/) or circonflex (^) and the name of the custom function within that file. For example, `"alpha/beta"` would refer to the custom function called “beta” within file “alpha”, whereby file “alpha” would be present in the *file links* repository.

### Conversion functions

The following functions are part of namespace `convert`:

* `Duration->months`, `Duration->days`, `Duration->weeks`, `Duration->quarters` and `Duration->years` take a Duration value, and return the number of months/days/weeks/quarters/years as an integer.
* `FloatValue->int`, `FloatValue->IntValue` and `FloatValue->float` convert a FloatValue.
* `float->FloatValue`, `IntValue->FloatValue`, `Amount->FloatValue` convert to a FloatValue. (An Amount can be either a FloatValue or an IntValue).
* `int->CurrencyValue`, `IntValue->CurrencyValue`, `CurrencyValue->float`, `float->CurrencyValue`, `CurrencyValue->FloatValue`, `CurrencyValue->int` and `CurrencyValue->IntValue` convert to/from a CurrencyValue.

### String functions

The following functions are part of namespace `ustr`:

* `quoted` takes a string and returns that string surrounded by double (straight) quotes.
* `one-else` takes nr, one-string and else-string als parameters. Returns one-string if nr is equal to 1, otherwise the else-string.
* `one-else-nr` takes nr, one-string and else-string als parameters. Returns nr concatenated by either one-string (if nr is equal to 1), otherwise the else-string.
* `sub` takes a string, a start (integer) and an optional end (also integer). Return substring. Ignores indexes out of bounds.
* `upper-case?` returns true if the string parameter is entirely in upper-case.
* `initial-cap?` returns true if string has an initial cap, but is not fully capitalized (e.g., ‘Dog’ but not ‘DOG’).
* `initial-cap` puts an initial cap on s. Note that all letters after the first one are left untouched, so that if those contain uppercase letters, they will remain in the result.
* `capitalize-words` capitalize each of the separate words
* `capitalization` returns whether string is not capitalized in any way (`:none`), or has initial caps (`:initial`), or is all-caps (`:all`).
* `apply-capitalization` takes a capitalization keyword (`:none`, `:initial`, `:all-words` or `:all`) and applies that capitalization style to the second parameter (string).
* `uncapitalize` returns a string with the first letter forced to lower (the rest is untouched).
* `clean-curly-quotes` replaces curly quotes and guillemets by straight ones.
* `str->int` converts a string to an integer.
* `str->float` converts a string to a float.
* `float->str` converts a float to a string. The arguments are a float, metric style? (boolean) and the decimals count (positive integer).
* `str->bool` converts ‘true’, ‘false’, ‘1’ or ‘0’ strings to boolean. nil if some other input was given.
* `extract-int` extracts the first occurrence of some integer from anywhere in the string.
* `int->str takes` as arguments an integer and a minimum-numbers-count. Convert the integer to a string, padding the result with zeros up to the minimum-numbers-count. Note that no thousands-grouping is applied.
* `comma-join` takes as arguments a combiner string and a collection of strings. Joins the different elements of the collection as strings with each other, separated by comma’s. The last element is joined with the specified combiner argument.
* `group-by-thousands` takes either an integer or a string, as well as a thousands-separator character. It returns a string in which the thousand-separators are added.
* `month->string` takes the number of the month (integer) and a language keyword, and returns the month in the specified language.
* `weekday->string` takes a weekday-number (integer: Monday is 1, Sunday is 7) and a language keyword, and returns the weekday as a string in the specified language.
* `date->str` takes year (integer), month (integer), day (integer), a date-style-kw and a language keyword, and returns the formatted date in the specified language. The date-style-kw can be any of the following: `:d-m-yyyy :slashed-d-m-yyyy :m-d-yyyy :slashed-m-d-yyyy :dd-mm-yyyy :slashed-dd-mm-yyyy :mm-dd-yyyy :slashed-mm-dd-yyyy :dd-mm-yy :slashed-dd-mm-yy :mm-dd-yy :slashed-mm-dd-yy :yyyy-mm-dd :slashed-yyyy-mm-dd :d-mmmm-yyyy :mmmm-d-yyyy :mmmm-d-comma-yyyy :dd-mmmm-yyyy :wwww-dd-mmmm-yyyy :wwww-d-mmmm-yyyy :wwww-comma-d-mmmm-yyyy :wwww-mmmm-dd-yyyy`.
* `ellipsis` takes two arguments (string input and a max integer) and truncates string with … after specified number of characters.
* `drop-last-character` drops the last character of a string. Returns empty string if nothing is left in the string.
* `drop-surrounding-characters` drops the characters surrounding a string. Returns empty string if nothing is left in the string.
* `drop-last-n-chars` takes an input string and a number of characters (integer). Returns empty string if nothing is left in the string, or n is simply too high.
* `get-last-n-chars` takes an input string and a number n (integer). Returns string with last N characters.
* `trim-if-string` returns its sole argument if it is not a string, otherwise returns the trimmed argument.
* `lower-if-string` returns its sole argument if it is not a string, otherwise returns the lower-cased argument.
* `trim|lower-if-string` returns its sole argument if it is not a string, otherwise returns the lower-cased & trimmed argument.
* `when-s` returns the string if it is not empty, else return nil.

### Mathematical functions

The following functions are part of namespace `math`:

* `sqrt` returns the square root
* `log` returns the logarithm
* `E` returns the constant e
* `acos` returns the arc cosine of a value
* `asin` returns the arc sine of a value
* `atan` returns the arc tangent of a value
* `atan2` returns the angle theta from the conversion of rectangular coordinates to polar coordinates
* `cos` returns the trigonometric cosine of an angle
* `sin` returns the trigonometric sine of an angle
* `tan` returns the trigonometric tangent of an angle
* `exp` returns Euler’s number *e* raised to the power of a
* `PI` returns the constant pi
* `pow` returns the value of the first argument raised to the power of the second argument
* `random` returns a random float value between 0 and 1. (You will probably want to invoke the host function using @`cljr`, otherwise the value will not be updated).

### Collection-related additional functions

The following functions are part of namespace `coll`:

* `i18sv` takes an i18-map and a language-keyword, and extracts the string value for the requested language. If the requested language is not available, then the next successive language is tried (hence the name: -sv refers to successive). Only returns a string if it is non-empty.
* `find-first` takes a predicate and a collection, and returns the first item that meets the predice. Essentially it is an optimized version of `(first (filter ...))`
* `intersects?` takes two collections and returns true if there is at least one common element between the two collections.
* `keepv` is similar to Clojure core’s keep function, but returns a vector.
* `indexed` returns a collection that consists of \[index, item] of the original coll.
* `index-of` returns index of first item that meets the predicate. Nil if not found.
* `index-of-value` returns first index of value within the collection. Nil if not found.
* `present?` takes a value and a collection, and returns true if value is present in the collection. Otherwise false.
* `singleton?`returns true if collection contains exactly one item.
* `dissoc-in` (which takes a map and a collection of keys) dissociates an entry from a nested associative structure returning a new nested structure. Note that entire branches may get wiped out. For example, `(dissoc-in {:a {:b {:c {:d 5}}}} [:a :b :c :d])` results in `{}`.
* `dissoc-in-leaf`is like dissoc-in, but only wipes out the “leaf”, preventing intermediary branches from being removed. For example, `(dissoc-in {:a {:b {:c {:d 5}}}} [:a :b :c :d])` results in `{:a {:b {:c {}}}}`
* `remove-element-v` takes a vector and an item. It removes item from vector, and returns updated vector.
* `remove-elements-v` takes a vector and one or more items. Removes those items from vector. Returns updated vector.
* `remove-atindex-v` takes a collection and a position. Removes the item with the specified index from the vector. Returns updated vector.
* `insert-v` takes a vector, a position and an item. It inserts item into vector at position. If the position is invalid, then the item is simply conj’ed. Returns updated vector.
* `cons-v` is like Clojure core’s cons, but returns a vector.
* `concat-v` is like Clojure core’s concat, but returns a vector.
* i`tems-before-pred` takes a predicate and a collection. Returns the vector of all items positioned before the first item that meets the pred (*excluding* the pred-meeting item itself). If pred is never met, then the entire coll is returned.
* `items-before-or-at-pred` takes a predicate and a collection. Returns the vector of all items positioned before the first item that meets the pred, *including* the pred-meeting item itself. If pred is never met, then the entire coll is returned.
* `items-after-pred` takes a predicate and a collection. Returns the vector of all items positioned *after* the last item that meets the pred (excluding the pred-meeting item itself). If pred is never met, then the entire coll is returned.
* `items-at-or-after-pred` takes a predicate and a collection. Returns the vector of all items positioned after the last item that meets the pred, *including* the pred-meeting item itself. If pred is never met, then the entire coll is returned.
* `split-around` takes a predicate and a collection. Splits collection into a tuple of three vectors, where:
  * the first vector contains all elements up to (but not including) the first element that matches pred;
  * the second item is the matching element itself;
  * the third item is a vector that contains all elements after the matching element (which may contain other matching elements, but this is not checked).
  * If no match exists, then the second item and third item will be nil.
* `split-in-two-vectors` takes a predicate and a collection. Splits collection into a tuple of two vectors:
  * the first vector contains all elements up to (but not including) the first element that matches pred;
  * the second vector is the rest of the items.
  * If no match exists, then the second item will be nil.
* `remove-fields` takes a predicate and a map. Remove those map fields for which (pred value) meets the pred. If no keys are left, an empty map is returned.
* `de-nil` takes a map. Remove keys with nil-values from the map. If no keys are left, nil is returned.
* `de-nil-map` takes a map. Remove keys with nil-values from the map. If no keys are left, empty map is returned.
* `nnmerge` takes one or more maps. Merges the first map with the de-nil’ed other maps.
* `merge-vectors` takes vec1, vec2 and extract-identity-fn. Merge elements of two vectors. If two values conflict, then the latter vector’s element will take precedence. extract-identity-fn should be a function that takes one parameter, and extracts the ‘identity’ of a value, to determine conflicts.
* `merge-missing` takes two maps. Merge those fields of map2 that are missing in map1, into map1
* `keep-first` takes a function and a collection. Like keep/keepv, but immediately stops upon the first hit, and returns that one. Returns nil when no match.
* `mapcat-v` is like Clojure core’s mapcat, but returns a vector.
* `flatten-one` flattens the given collection one level deep.
* `update-el` takes v, pred and f. Updates the first el of the vector that matches pred (leaves the rest untouched).
* `replace-el` takes v, pred and new-el. Replaces the first el of the vector that matches pred, with the new element.
* `replace-or-add` takes v, pred and replacement-el. Replaces the first element of the vector that matches pred, by the specified replacement. If pred does not match anywhere, then conj the replacement to the vector.
* `any-field-equal?` takes a map, fields (collection of keywords) and ref-value. Returns true if any of the specified fields in map m is equal to ref-value.
* `any-field?` takes a map m, fields (collection of keywords) and a predicate. Returns logical true if (pred field) is true for any of the specified fields in map m.
* `drop-until-nth-pred` takes n (integer), pred (function) and a collection. Drop items until pred is met for the nth time.If successful, the first item of the returned coll will meet n. Returns nil if pred is not met at least n times.
* `index-of-subcoll` takes a large collection and a sub-collection. Returns the position (0-based) of the sub-coll within big-coll. nil if not found.
* `initial-subvec?` takes a vector and a subvector. Returns true if subv is a subcollection of v, at index 0. Note that if v and subv are equal, the result will also be true.
* `distinct-by` takes a function and a collection. Returns a lazy sequence of the elements of coll, removing any elements that return duplicate values when passed to a function f.
* `remove-v` like Clojure core’s remove, but returns a vector.
* `removev-with-id` takes an ID and a collection. Removes all elements that have the specified ID.
* `remove-first-v` takes a predicate and a collection. Removes first element from the collection that meets the specified pred. Unlike remove-v, it does not continue looking once a match is found. Always returns a vector.
* `sort-by-other-coll` takes a collection to sort, a reference collection and an optional key-function. Sorts the items in the given collection on the basis of the ordering of items in reference collection. If an item is not present in the reference collection, then it will be appended to the end of the sorted-result-so-far. If a key-fn is given, it will be used to extract the key from each item, for use in the ordering vis-à-vis the reference collection. Examples:
  * (sort-by-other-coll \[:c :b :a :d] \[:a :b :c]) => (:a :b :c :d)
  * (sort-by-other-coll \[{:key :c} {:key :a}] \[:a :b :c] :key) => ({:key :a} {:key :c})
* `conj-set` like Clojure core’s conj, but creates a set if the set-to-add-to is nil.
* `conj-vec` like Clojure core’s conj, but creates a vector if the vec-to-add-to is nil.
* `find-first-with-id` takes an ID and a collection. Returns the first element from the collection whose :id field matches the given id.
* `find-first-equalto` takes an object and a collection. Returns the first element from the collection that is equal to the given object.
* `swap-elements` takes a vector, and two indices. Swap the vector’s elements with the two specified indices.
* `submap?` takes two maps. Returns true if a is a submap of b, i.e.: a only has fields that are also present in b, and those fields are identical to those of b.
* `update-map-values` takes a map and a function. loops through the map, and call f with the key & value on each iteration. The value will then be updated with the result of f.
* `update-mapv` takes a map, a field-keyword and a function f. Updates the vector in map m’s field-kw, by calling f on each of its elements.
* `update-kv` takes a map, a field-keyword and a function f. Updates the map in map m’s field-kw. f should be a function to be used in a reduce-kv, so taking three elements.

### AJAX/get

The `ajax/get` function allows you to fetch information from external servers, using a GET call for HTTP. Note that, due to the asynchronous nature, it is currently only available in the Q\&A environment. The parameters are:

* a URL (string)
* a map with the following optional keys:
  * `:on-success` is a function that is called with the result of the call. If it is nil, then `ajax-get` will simply return the success-result.
  * `:on-error` is a function that is passed a map (see cljs-ajax documentation on ‘Error Responses’) and should either return `:error`, or some other value
  * `:options` is a map of options. See the [documentation for ajax-get](https://github.com/JulianBirch/cljs-ajax).

### Other functions <a href="#building-interfaces" id="building-interfaces"></a>

`exec-js` internally calls JavaScript's `eval` function and executes the sole string-parameter that gets passed to it.

## Building Q\&A interfaces using “custom blocks” <a href="#building-interfaces" id="building-interfaces"></a>

You can build custom mini-interfaces by adding a new “custom block” question in the Q\&A, and inserting code. You can develop these interfaces interactively by testing the cards (showing the *test cards* pane in your design Q\&A environment and either hitting the *refresh* button, or shortcut *Ctrl-U*).

The interfaces are built using a subset of the [Blueprint.js](https://blueprintjs.com/) library, combined with ClojureScript’s [Hiccup syntax](https://reagent-project.github.io/). The following Blueprint-widgets are available: button, callout, checkbox, menu, menuItem, menu-divider, radio-button, slider, switch, tag, table and tooltip. In addition, you can create any DOM-element you like through the standard Hiccup syntax.

For example, the following would create a DIV (10 pixel padded, with a 2 pixel blue border and 5 pixel external margin) with a single paragraph with red text, and a button that prints “hello” to the console when clicked:

{% code overflow="wrap" %}

```clojure
[:div 
 
 {:style {:padding "10px" :border "2px solid blue" :margin "5px"}}
 
 [:p 
  {:style {:color "red"}} 
  "I am a paragraph"]
 
 [:> Button {:text "I'm a button..." 
             :on-click (fn [event] 
                           (println "I'm clicked!"))}]]
```

{% endcode %}

<figure><img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2FOXLBZyQ8FuXvrrSaWBLv%2Fimage.png?alt=media&#x26;token=c01419a9-b514-4aec-b98b-1fac1c8fdcfa" alt=""><figcaption></figcaption></figure>

## Tips & Tricks

* You can reformat the Clojure-code you have written by pressing the Ctrl-B shortcut.
* When developing in the *Design Q\&A* environment, you probably want to show the *Test cards* pane, to interactively check what your Clojure code is doing.&#x20;
* When developing in *Assemble Document*, you probably want to activate the [Focus mode](https://help.clause9.com/assemble-document/focus-mode) <img src="https://1353649376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaTEDNbiFdDa6DW2eNG17%2Fuploads%2F0j8kX7HHiNnxbEhWReVI%2Fimage.png?alt=media&#x26;token=83d76494-9be6-4793-8c0d-d176a39ffb93" alt="" data-size="line">, so you can interactively see the changes to your Clojure-code in the currently focused clause.
