Transformers
| < Formatters | Selectors > |
Object Transformers
Transformers apply an arbitrary transformation to an object. They can be applied to any object but are most useful when dealing with collection types. Strictly speaking, both converters and formatters are transformers. A converter takes an object and returns another object of a specified type; a formatter takes an object and returns a string.
Transformers come in two major flavors: scalar and vector transformers.
Scalar Transformers
Scalar transformers are created by implementing the Scalar interface. A scalar transformer takes a collection and transforms it into one object. Think of sums, averages, minimum or maximum calculations, or concatenations as perfect examples of scalar transformations. A collection of objects is transformed into a single object.
Let's look at examples of scalar transformers. The examples below demonstrate some built-in scalar transformers.
C:\terp\bin>terp -e "{0,1,2,10,-4,12}[max]"
12
C:\terp\bin>terp -e "{0,1,2,10,-4,12}[min]"
-4
C:\terp\bin>terp -e "{0,1,2,10,-4,12}[sum]"
21
C:\terp\bin>terp -e "{0,1,2,10,-4,12}[count]"
6
C:\terp\bin>terp -e "{'test','abc','hello'}[maxlength]"
5
The complete list of scalar transformers follows below.
| Name | Arguments | Description |
|---|---|---|
| concat, concatenate |
[sep] | Concatenates all elements in a collection, using the optional argument as a separator. Example: {1,2,3}[join('-')] becomes 1-2-3 |
| count | none | Transforms to number of elements. |
| join | [sep] | Synonym for concatenate |
| max | none | Transforms to largest element according to registered comparison operators. |
| maxlength | none | Transforms to the number of characters in the longest string in the collection. |
| min | none | Transforms to the smallest element according to registered comparison operators. |
| sum | none | Transforms to the sum of elements according to registered addition operators. |
Vector transformers
Vector transformers are created by implementing the Transformer interface. A vector transformer transforms every element of a collection into another element and returns a new collection containing the transformed elements. Vector transformers can be chained. When chaining them, pay attention to the sequence.
Consider the following examples:
C:\terp\bin>terp -e "{0,1,2}[prefix(' ')]"
0 1 2
C:\terp\bin>terp -e "{0,1,2}[suffix('_')]"
0_1_2_
C:\terp\bin>terp -e "{0,1,2}[indent(4)]"
0 1 2
C:\terp\bin>terp -e "{0,1,2}[indent(2,'.')]"
..0..1..2
C:\terp\bin>terp -e "{0,1,2}[indent(2,'.')][suffix('\n')]"
..0
..1
..2
C:\terp\bin>terp -e "'this is a test'[split('[ ]')][suffix('\n')]"
this
is
a
test
In the first example, we convert every element in the collection to a string and prefix a space to it.
In the second example, we append an underscore to every string representation of the elements.
In the third example, we indent all elements by four characters.
In the fourth example, we use the optional indent sequence argument to specify that we wish to indent with periods rather than spaces.
In the fifth example, we chain a suffix transformer that creates linebreaks after every indented element.
In the sixth and final example, we split a string on space characters and append a linebreak to each segment.
The following table contains a complete list of the built-in vector transformers.
| Name | Arguments | Description |
|---|---|---|
| ascii | Converts the object's string representation to an ASCII-only string. This is very useful when generating source code for programming languages that don't tolerate non-ASCII characters in identifiers. Example: ^char(0xD6)[ascii] becomes OE |
|
| capitalize | [count] | Capitalizes the first count (default 1) characters of the object's string representation. See upper/uppercase for a complete conversion to upper case. Example: "this"[capitalize(2)] becomes THis |
| cut | char or string | Removes all occurrences of a character or string in text. Example: "a b c"[cut(' ')] becomes abc |
| expand | template-spec | Expands the template given by template specifier with the object available as 'this'. Template specifiers need not be strings but can be ^file(), ^uri(), or ^url() elements as well. In all these cases, the template specifier is interpreted as a resource from which the template is read.Example: {0,5}[expand('${this+1}*')] becomes 1*6* |
| export | template-spec, output-spec, [append] |
Expands the template given by template specifier with the object available as 'this' and writes the expanded template to the output given by the output specifier. You can also optionally pass a boolean flag that is taken into account for ^file() destinations. The default value is false. |
| indent | count, [obj] | Indents the element the specified number of times with the optionally specified indentation object (default of one space character). |
| linebreak | [keep-eol] | Similar to split, but keeps the end of lines and replaces them with the configured metadata value for eol. |
| lower lowercase |
none | Converts each element to string and lowercases the result. |
| pad padleft |
int,[object] | Pads the item with spaces (by default) until the specified width is reached. The padding can optionally be specified as the second argument. Example: 4[pad(3,'*')] becomes **4 |
| padright | int,[object] | Pads the item with spaces (by default) on the right until the specified width is reached. The padding can optionally by specified as the second argument. Example: 4[padright(3,'_')] becomes 4__ |
| prefix | obj | Prefixes the specified object to each element. |
| remove | char or string | Synonym for cut |
| replace | char, char or |
Replaces all occurrences of a character or string in text with another character or string. Example: "a b c"[replace('b','B')] becomes a B c |
| split | pattern | Splits each element into segments in accordance with the given pattern and returns the segments as a list. |
| slug slugify |
none | Trims and collapses spaces and replaces them with dashes. Example: "a small test"[slug] becomes a-small-test |
| suffix | obj | Suffixes the specified object to each element. |
| trim | obj | Trims leading and trailing whitespace off each element. |
| upper uppercase |
none | Converts each element to string and uppercases the result. |
| xmlencode | none | Replaces the active characters in XML with their entity values. Example: "<p>"[xmlencode] becomes <p> |
Custom Transformers
In addition to the predefined transformers, you can use your own custom transformers via ^xform converter. The ^xform() converter takes one argument, which is the expression that calculates the new element, possibly taking the old element and its position in the input collection into account via the this and index variables.
The following example returns a new list containing the doubled integer values of the source list that is then joined together with comma separators:
C:\terp\bin>terp -e "{0,1,2,3,4,5,6}[^xform( this * 2 )][join(',')]"
0,2,4,6,8,10,12
C:\terp\bin>
The following example creates a list containing Boolean values indicating whether the corresponding integers are even and joins the resulting list values together with comma separators:
C:\terp\bin>terp -e "{0,1,2,3,4,5,6}[^xform( this % 2 == 0 )][join(',')]"
true,false,true,false,true,false,true
C:\terp\bin>
The following example uses both this and index to create a numbered list:
C:\terp\bin>terp -e "{0,1,2}[^xform( ''+index+':'+(this % 2 == 0) )][join(eol)]"
0:true
1:false
2:true
C:\terp\bin>
While there currently is no mechanism to declare custom scalar transformers, you can very often achieve the desired effect by chaining a predefined scalar transformer to a custom vector transformer. Let's say for example that you are interested in the maximum name length occuring in a collection of named objects. You could write:
myCollection[ ^xform(this.getName().length) ][ max ]
