Handling context and argument types

If you look through the function docs, you may notice that all of them define what a function accepts and what it returns. Additionally, every argument includes a type property that specifies the kind of data that can be used. These two types of values are actually the same, and can be used as a guide for how to deal with piping to other functions and using subexpressions for argument values.

To explain how this works, consider the following expression from the previous section:

image dataurl={asset 3cb3ec3a-84d7-48fa-8709-274ad5cc9e0b}

If you look at the docs for the image function, you’ll see that it accepts the null data type and returns an image data type. Accepting null effectively means that it does not use context at all, so if you insert anything to image, the value that was produced previously will be ignored. When the function executes, it will produce an image output, which is simply an object of type image that contains the information required to render an image.

The function does not render an image itself.

As explained in the "Fetch and manipulate data" section, the output of an expression is just data. So the image type here is just a specific shape of data, not an actual image.

Next, let’s take a look at the asset function. Like image, it accepts null, but it returns something different, a string in this case. Because asset will produce a string, its output can be used as the input for any function or argument that accepts a string.

Looking at the docs for the dataurl argument, its type is string, meaning it will accept any kind of string. There are some rules about the value of the string that the function itself enforces, but as far as the interpreter is concerned, that expression is valid because the argument accepts a string and the output of asset is a string.

The interpreter also attempts to cast some input types into others, which allows you to use a string input even when the function or argument calls for a number. Keep in mind that it’s not able to convert any string value, but if the string is a number, it can easily be cast into a number type. Take the following expression for example:

string "0.4"
| revealImage image={asset asset-06511b39-ec44-408a-a5f3-abe2da44a426}

If you check the docs for the revealImage function, you’ll see that it accepts a number but the string function returns a string type. In this case, because the string value is a number, it can be converted into a number type and used without you having to do anything else.

Most primitive types can be converted automatically, as you might expect. You just saw that a string can be cast into a number, but you can also pretty easily cast things into boolean too, and you can cast anything to null.

There are other useful type casting options available. For example, something of type datatable can be cast to a type pointseries simply by only preserving specific columns from the data (namely x, y, size, color, and text). This allows you to treat your source data, which is generally of type datatable, like a pointseries type simply by convention.

You can fetch data from Elasticsearch using essql, which allows you to aggregate the data, provide a custom name for the value, and insert that data directly to another function that only accepts pointseries even though essql will output a datatable type. This makes the following example expression valid:

essql "SELECT user AS x, sum(cost) AS y FROM index GROUP BY user"
| plot

In the docs you can see that essql returns a datatable type, but plot expects a pointseries context. This works because the datatable output will have the columns x and y as a result of using AS in the sql statement to name them. Because the data follows the convention of the pointseries data type, casting it into pointseries is possible, and it can be passed directly to plot as a result.