From 28cedfdb3d44e73e195a94fed887798c8de18545 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 28 Dec 2024 10:18:00 -0800 Subject: [PATCH 1/7] Add base apidoc and overview articles --- apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md | 5 +++++ apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md | 5 +++++ apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md | 5 +++++ articles/scripting-expressions-overview.md | 4 ++++ 4 files changed, 19 insertions(+) create mode 100644 apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md create mode 100644 apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md create mode 100644 apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md create mode 100644 articles/scripting-expressions-overview.md diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md new file mode 100644 index 00000000..5b13f05d --- /dev/null +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md @@ -0,0 +1,5 @@ +--- +uid: Bonsai.Scripting.Expressions.ExpressionCondition +--- + +[!include[](~/articles/scripting-expressions-overview.md)] \ No newline at end of file diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md new file mode 100644 index 00000000..d974bd0f --- /dev/null +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md @@ -0,0 +1,5 @@ +--- +uid: Bonsai.Scripting.Expressions.ExpressionSink +--- + +[!include[](~/articles/scripting-expressions-overview.md)] \ No newline at end of file diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md new file mode 100644 index 00000000..a201eba6 --- /dev/null +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md @@ -0,0 +1,5 @@ +--- +uid: Bonsai.Scripting.Expressions.ExpressionTransform +--- + +[!include[](~/articles/scripting-expressions-overview.md)] \ No newline at end of file diff --git a/articles/scripting-expressions-overview.md b/articles/scripting-expressions-overview.md new file mode 100644 index 00000000..b368b3f5 --- /dev/null +++ b/articles/scripting-expressions-overview.md @@ -0,0 +1,4 @@ +The `Scripting.Expressions` operators use the [expression language](https://dynamic-linq.net/expression-language) provided by the [dynamic-linq](https://dynamic-linq.net/) library. + +> [!Note] +> Inside the `Expression` editor, the default expression `it` represents the value of the input node. To access a specific field in the input, reference it by name — for instance, `it.Item1` or `Item1`. Right-click the input node to view available fields. \ No newline at end of file From fbcc8b0672313b3a91e0dd01e5691ab13c8b2ed2 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 28 Dec 2024 14:47:15 -0800 Subject: [PATCH 2/7] Add ExpressionTransform examples and modify relative links --- ...ripting_Expressions_ExpressionCondition.md | 2 +- ...ai_Scripting_Expressions_ExpressionSink.md | 2 +- ...ripting_Expressions_ExpressionTransform.md | 19 ++++++++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md index 5b13f05d..1fbb3bd3 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md @@ -2,4 +2,4 @@ uid: Bonsai.Scripting.Expressions.ExpressionCondition --- -[!include[](~/articles/scripting-expressions-overview.md)] \ No newline at end of file +[!include[](../articles/scripting-expressions-overview.md)] \ No newline at end of file diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md index d974bd0f..a81c63e5 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md @@ -2,4 +2,4 @@ uid: Bonsai.Scripting.Expressions.ExpressionSink --- -[!include[](~/articles/scripting-expressions-overview.md)] \ No newline at end of file +[!include[](../articles/scripting-expressions-overview.md)] \ No newline at end of file diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md index a201eba6..20795128 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md @@ -2,4 +2,21 @@ uid: Bonsai.Scripting.Expressions.ExpressionTransform --- -[!include[](~/articles/scripting-expressions-overview.md)] \ No newline at end of file +[!include[](../articles/scripting-expressions-overview.md)] + +### Examples + +The following examples demonstrate common [Transforms](../articles/operators.md#transform) achievable with this operator. + +| Category | Example | Description | +| ---------------------- | ------------------------------- | ----------- | +| Arithmetic Operations | `1.0 / (it + 2.0)` | Transforms an element using [arithmetic operators](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators). | +| Arithmetic Operations | `Math.Sqrt(it)` | Transforms an element using functions provided by the [Math](https://learn.microsoft.com/en-us/dotnet/api/system.math?view=net-7.0) class. | +| Attribute Renaming | `new(it.Item1 as X, it.Item2 as Y)` | Transforms an element's field name. Commonly used to rename column headers for the [`CsvWriter`](xref:Bonsai.IO.CsvWriter) node. | +| Conditional Expression | `it ? 1 : 0 ` | Transforms an element by returning the first value if `it` is `true`, and the second value otherwise, using the conditional operator [`?`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator). It can be placed directly after an node that outputs a Boolean value such as [`Equal`](xref:Bonsai.Expressions.EqualBuilder). It can also be used for type conversion. | +| Conditional Expression | `it < 3 ? 1 : 0 ` | Transforms an element by returning the first or second value after performing an inline comparison. Inline comparisons can be set using [comparison](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/comparison-operators), [logical](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators), or [equality](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators) operators. | +| Type Conversion | `Convert.ToDouble(it)` | Transforms an element's type using the [Convert](https://learn.microsoft.com/=en-us/dotnet/api/system.convert?view=net-7.0) class. | +| Type Conversion | `TimeSpan.FromSeconds(it)` | Transforms an element's type by directly invoking an output type's method. Simplifies the required input formatting in some cases. | + +> [!Note] +> The expressions can be combined for additional flexibility. \ No newline at end of file From 6d224c332025588959d021d9bf406df1b40e291a Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 28 Dec 2024 16:11:23 -0800 Subject: [PATCH 3/7] Add ExpressionCondition examples --- ...sai_Scripting_Expressions_ExpressionCondition.md | 13 ++++++++++++- ...sai_Scripting_Expressions_ExpressionTransform.md | 2 +- articles/scripting-expressions-overview.md | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md index 1fbb3bd3..c91f0df5 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md @@ -2,4 +2,15 @@ uid: Bonsai.Scripting.Expressions.ExpressionCondition --- -[!include[](../articles/scripting-expressions-overview.md)] \ No newline at end of file +[!include[](../articles/scripting-expressions-overview.md)] + +### Examples + +The following examples demonstrate common [Condition](../articles/operators.md#condition) filters achievable with this operator. Elements that evaluate to `true` will pass the filter, while elements that evaluate to `false` will be dropped. + +| Category | Example | Description | +| -------------------- | --------------------------- | ----------- | +| Comparison Filtering | `it < 3` | Filters an element by performing an inline comparison. Inline comparisons can be set using [comparison](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/comparison-operators), [logical](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators), or [equality](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators) operators. | +| Predicate Filtering | `Double.IsPositive(it)` | Filters an element by calling a type predicate method. For more examples, refer to the C# type documentation - for instance, [Doubles](https://learn.microsoft.com/en-us/dotnet/api/system.double?view=net-7.0#methods). | +| NaN Filtering | `Double.IsNan(it) == false` | Filters an element by calling the `IsNan` predicate method. This is a special case of predicate filtering, notable because the output must be inverted to exclude `NaN` values. | + \ No newline at end of file diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md index 20795128..9d3f929b 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md @@ -15,7 +15,7 @@ The following examples demonstrate common [Transforms](../articles/operators.md# | Attribute Renaming | `new(it.Item1 as X, it.Item2 as Y)` | Transforms an element's field name. Commonly used to rename column headers for the [`CsvWriter`](xref:Bonsai.IO.CsvWriter) node. | | Conditional Expression | `it ? 1 : 0 ` | Transforms an element by returning the first value if `it` is `true`, and the second value otherwise, using the conditional operator [`?`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator). It can be placed directly after an node that outputs a Boolean value such as [`Equal`](xref:Bonsai.Expressions.EqualBuilder). It can also be used for type conversion. | | Conditional Expression | `it < 3 ? 1 : 0 ` | Transforms an element by returning the first or second value after performing an inline comparison. Inline comparisons can be set using [comparison](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/comparison-operators), [logical](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators), or [equality](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators) operators. | -| Type Conversion | `Convert.ToDouble(it)` | Transforms an element's type using the [Convert](https://learn.microsoft.com/=en-us/dotnet/api/system.convert?view=net-7.0) class. | +| Type Conversion | `Convert.ToDouble(it)` | Transforms an element's type using the [Convert](https://learn.microsoft.com/en-us/dotnet/api/system.convert?view=net-7.0) class. | | Type Conversion | `TimeSpan.FromSeconds(it)` | Transforms an element's type by directly invoking an output type's method. Simplifies the required input formatting in some cases. | > [!Note] diff --git a/articles/scripting-expressions-overview.md b/articles/scripting-expressions-overview.md index b368b3f5..2a8e552e 100644 --- a/articles/scripting-expressions-overview.md +++ b/articles/scripting-expressions-overview.md @@ -1,4 +1,4 @@ The `Scripting.Expressions` operators use the [expression language](https://dynamic-linq.net/expression-language) provided by the [dynamic-linq](https://dynamic-linq.net/) library. > [!Note] -> Inside the `Expression` editor, the default expression `it` represents the value of the input node. To access a specific field in the input, reference it by name — for instance, `it.Item1` or `Item1`. Right-click the input node to view available fields. \ No newline at end of file +> Inside the `Expression` editor, the default expression `it` represents the value of the input node. To access a specific field in the input, reference it by name - for instance, `it.Item1` or `Item1`. Right-click the input node to view available fields. \ No newline at end of file From 35a475582a0ad241df623e2c3ce131bc11f7e7ad Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 28 Dec 2024 16:12:06 -0800 Subject: [PATCH 4/7] Remove extra line space --- apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md index c91f0df5..fe2fd8e4 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md @@ -12,5 +12,4 @@ The following examples demonstrate common [Condition](../articles/operators.md#c | -------------------- | --------------------------- | ----------- | | Comparison Filtering | `it < 3` | Filters an element by performing an inline comparison. Inline comparisons can be set using [comparison](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/comparison-operators), [logical](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators), or [equality](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators) operators. | | Predicate Filtering | `Double.IsPositive(it)` | Filters an element by calling a type predicate method. For more examples, refer to the C# type documentation - for instance, [Doubles](https://learn.microsoft.com/en-us/dotnet/api/system.double?view=net-7.0#methods). | -| NaN Filtering | `Double.IsNan(it) == false` | Filters an element by calling the `IsNan` predicate method. This is a special case of predicate filtering, notable because the output must be inverted to exclude `NaN` values. | - \ No newline at end of file +| NaN Filtering | `Double.IsNan(it) == false` | Filters an element by calling the `IsNan` predicate method. This is a special case of predicate filtering, notable because the output must be inverted to exclude `NaN` values. | \ No newline at end of file From 742b90456b0d2bc9e2eb0b55d48b2d96f6427468 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Thu, 9 Jan 2025 15:12:30 +0000 Subject: [PATCH 5/7] Add complete scripting expression overview --- articles/scripting-expressions-overview.md | 121 ++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-) diff --git a/articles/scripting-expressions-overview.md b/articles/scripting-expressions-overview.md index 2a8e552e..a9db17ee 100644 --- a/articles/scripting-expressions-overview.md +++ b/articles/scripting-expressions-overview.md @@ -1,4 +1,121 @@ -The `Scripting.Expressions` operators use the [expression language](https://dynamic-linq.net/expression-language) provided by the [dynamic-linq](https://dynamic-linq.net/) library. +## Expression Language + +The `Scripting.Expressions` namespace uses an early version of the [Dynamic LINQ library](https://dynamic-linq.net/) to assemble expression trees directly into the workflow by using a [special syntax](#expression-language). > [!Note] -> Inside the `Expression` editor, the default expression `it` represents the value of the input node. To access a specific field in the input, reference it by name - for instance, `it.Item1` or `Item1`. Right-click the input node to view available fields. \ No newline at end of file +> This expression language aims to be a simple and convenient way of writing arithmetical and value manipulation operations without having to create a separate project or manage local extensions, but it is not a complete query or programming language. If you require more elaborate type or value manipulations, please consider writing a custom [scripting extension](xref:scripting-extensions). + +### Literals + +The expression language supports boolean, integer, real, string, and character literals. Literals are textual representations of constant values and are one of the most important building blocks of an expression. + +| Type | Examples | Description | +| --------- | -------------------| -------------------------------------------------------- | +| boolean | `true`
`false` | A [`Boolean`](xref:System.Boolean) value which can be either `true` or `false`. | +| integer | `0`
`1L`
`2U`
`3UL` | A sequence of digits. The type of an integer literal is [`Int32`](xref:System.Int32) unless a qualifier character is used to specify the type of the integer (`U` - [`UInt32`](xref:System.UInt32), `L` - [`Int64`](xref:System.Int64), `UL` - [`UInt64`](xref:System.UInt64)). | +| real | `1.0`
`2.25`
`1e10F`
`1.2345E-4` | An integral part followed by a fractional part and/or an exponent. The fractional part is a decimal point followed by one or more digits. The exponent is the letter `e` or `E` followed by an optional `+` or `-` sign followed by one or more digits. The type of a real literal is [`Double`](xref:System.Double) unless the `F` qualifier is used, in which case the type of the literal will be [`Single`](xref:System.Single). | +| string | `"hello"`
`""`
`"""quoted"""`
`"'"` | Zero or more characters enclosed in double quotes. A double quote character can be represented inside a string literal using two consecutive double quotes. The type of a string literal is [`String`](xref:System.String). | +| character | `'A'`
`'1'`
`''''`
`'"'` | A single character enclosed in single quotes. A single quote character can be represented inside a character literal using two consecutive single quotes. The type of a character literal is [`Char`](xref:System.Char). | +| null | `null` | The `null` literal represents a null reference. The type of the `null` literal is [`Object`](xref:System.Object). | + +### Types + +The expression language defines special keywords representing the primitive types and a small set of accessible types from the `System` namespace of the .NET Framework Base Class Library. + +These accessible types can be used to create new values, convert a value to another type, or to call public static methods available from the type class, as detailed in the documentation reference page of each type. + +|
Type
| Description | +| ---------------------------------------------- | ----------- | +| [`Boolean`](xref:System.Boolean) | Represents a Boolean (`true` or `false`) value. | +| [`Byte`](xref:System.Byte) | Represents an 8-bit unsigned integer. | +| [`Char`](xref:System.Char) | Represents a character as a UTF-16 code unit. | +| [`DateTime`](xref:System.DateTime) | Represents an instant in time, typically expressed as a date and time of day. | +| [`DateTimeOffset`](xref:System.DateTimeOffset) | Represents a point in time, typically expressed as a date and time of day, relative to Coordinated Universal Time (UTC). | +| [`Decimal`](xref:System.Decimal) | Represents a decimal floating-point number. | +| [`Double`](xref:System.Double) | Represents a double-precision floating-point number. | +| [`Guid`](xref:System.Guid) | Represents a globally unique identifier (GUID). | +| [`Int16`](xref:System.Int16) | Represents a 16-bit signed integer. | +| [`Int32`](xref:System.Int32) | Represents a 32-bit signed integer. | +| [`Int64`](xref:System.Int64) | Represents a 64-bit signed integer. | +| [`Object`](xref:System.Object) | Supports all classes in the .NET class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all .NET classes; it is the root of the type hierarchy. | +| [`SByte`](xref:System.SByte) | Represents an 8-bit signed integer. | +| [`Single`](xref:System.Single) | Represents a single-precision floating-point number. | +| [`String`](xref:System.String) | Represents text as a sequence of UTF-16 code units. | +| [`TimeSpan`](xref:System.TimeSpan) | Represents a time interval. | +| [`UInt16`](xref:System.UInt16) | Represents a 16-bit unsigned integer. | +| [`UInt32`](xref:System.UInt32) | Represents a 32-bit unsigned integer. | +| [`UInt64`](xref:System.UInt64) | Represents a 64-bit unsigned integer. | +| [`Math`](xref:System.Math) | Provides constants and static methods for trigonometric, logarithmic, and other common mathematical functions. | +| [`Convert`](xref:System.Convert) | Converts a base data type to another base data type. | + +> [!Note] +> [Nullable value types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types) can be specified by writing a `?` after the type name. For example, `Int32?` refers to the nullable form of `Int32`. + +### Conversions + +The expression language allows explicit conversions between value types using the syntax `type(_expr_)` where `type` is one of the [primitive types](#types) listed above, optionally followed by `?`, and `_expr_` is an arbitrary expression, e.g. the expression `Int32(22.5)` will convert the real number `22.5` to an integer with the type `Int32`. + +> [!Note] +> This syntax can be used to convert between the nullable and non-nullable forms of any value type. + +### Identifiers + +When parsing an expression with a single input element, all members in that element are automatically in scope of the expression string, including public fields, public properties, and public methods. This means any specific member on the input can be accessed by writing an identifier corresponding to the name of that member, e.g. `Item1`. + +> [!Warning] +> The casing of identifiers is ignored when resolving members, e.g. `item1` or `ITEM1` can both be used to refer to the member `Item1`. + +An identifier consists of a letter or underscore followed by any number of letters, digits, or underscores. In order to reference an identifier with the same spelling as a keyword, the identifier must be prefixed with a single `@` character. Some examples of identifiers are `x`, `Hello`, `m_1`, `@true` and `@String`. + +> [!Note] +> The special keyword `it` represents the entire input element, and members can be accessed from this special identifier using dot notation, e.g. `it.Item1`. + +### Operators + +The expression language supports the following operators in order of precedence of the categories indicated in the table, from top to bottom. Operators in the same category have equal precedence. + +In the table below, `x`, `y`, and `z` refer to arbitrary expressions, `T` refers to one of the [accessible types](#types), and `m` refers to a member of an expression value (see the section on [identifiers](#identifiers)). + +| Category |
Expression
| Description | +| -------------- | -------------- | -------------------------------------- | +| Primary | `x.m` | Instance field or property access. Any public field or property can be accessed. | +| Primary | `x.m(...)` | Instance method invocation. Any public method may be invoked. Overload resolution follows C# rules. | +| Primary | `x[...]` | Array or indexer access. Any public indexer, including multi-dimensional indexers, can be accessed. | +| Primary | `T.m` | Static field or static property access. Any public field or property can be accessed. | +| Primary | `T.m(...)` | Static method invocation. Any public method may be invoked. Overload resolution follows C# rules. | +| Primary | `T(...)` | [Explicit conversion](#conversions) or constructor invocation. | +| Primary | `new(...)` | [Data object initializer](#data-object-initializers). This syntax can be used to perform dynamic projections. | +| Primary | `it` | Current instance access. See the note in the section on [identifiers](#identifiers). | +| Primary | `iif(x, y, z)` | Conditional expression. Alternate syntax for `x ? y : z`. | +| Unary | `-x` | Negation using two's complement. Supported types are `Int32`, `UInt32`, `Int64`, `Decimal`, `Single`, and `Double`. | +| Unary | `!x` | Logical negation. Operand must be of type `Boolean`. | +| Multiplicative | `x * y` | Multiplication. Only primitive numeric types are supported. | +| Multiplicative | `x / y` | Division. Only primitive numeric types are supported. | +| Multiplicative | `x % y` | Remainder. Only primitive numeric types are supported. | +| Additive | `x + y` | Addition or string concatenation. Performs string concatenation if either operand is of type `String`. Otherwise, performs addition on primitive numeric types only. | +| Additive | `x - y` | Subtraction. Only primitive numeric types are supported. | +| Additive | `x & y` | String concatenation. Operands must both be of type `String`. | +| Relational | `x == y` | Equal. Supported for reference types and any of the primitive types. Comparison with `null` is also supported. | +| Relational | `x != y` | Not equal. Supported for reference types and any of the primitive types. Comparison with `null` is also supported. | +| Relational | `x < y` | Less than. Supported for all primitive types except `Boolean`, `Object` and `Guid`. | +| Relational | `x > y` | Greater than. Supported for all primitive types except `Boolean`, `Object` and `Guid`. | +| Relational | `x <= y` | Less than or equal. Supported for all primitive types except `Boolean`, `Object` and `Guid`. | +| Relational | `x >= y` | Greater than or equal. Supported for all primitive types except `Boolean`, `Object` and `Guid`. | +| Logical AND | `x && y` | Logical AND. Operands must be of type `Boolean`. | +| Logical OR | `x || y` | Logical OR. Operands must be of type `Boolean`. | +| Conditional | `x ? y : z` | Evaluate `y` if `x` is `true`, otherwise evaluate `z`. | + +### Data Object Initializers + +The expression language supports creating dynamic data classes using data object initializers. A data object initializer simultaneously specifies a data class and creates a new instance of that class. The specific properties of the data class are inferred from the data object initializer. + +The syntax for a data object initializer is identical to a constructor, where each argument represents a property of the data class. For each argument the value must be specified together with an identifier for the property name, separated by the `as` keyword: + +``` +new( + Item1 as X, + Item2 as Y +) +``` + +The example above projects the two unnamed items of a tuple into a new data object with an `X` and a `Y` property. \ No newline at end of file From a0bd164eb5dcec3bef18d2a1bf6dfedb76d310ae Mon Sep 17 00:00:00 2001 From: glopesdev Date: Thu, 9 Jan 2025 15:20:33 +0000 Subject: [PATCH 6/7] Simplify annotations of expression examples --- ...ripting_Expressions_ExpressionCondition.md | 12 +++++----- ...ripting_Expressions_ExpressionTransform.md | 23 ++++++++----------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md index fe2fd8e4..cfcf54ed 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionCondition.md @@ -6,10 +6,10 @@ uid: Bonsai.Scripting.Expressions.ExpressionCondition ### Examples -The following examples demonstrate common [Condition](../articles/operators.md#condition) filters achievable with this operator. Elements that evaluate to `true` will pass the filter, while elements that evaluate to `false` will be dropped. +The following examples demonstrate common [Condition](../articles/operators.md#condition) filters achievable with this operator. Elements that evaluate to `true` will pass the filter, while elements that evaluate to `false` will be dropped from the output sequence. -| Category | Example | Description | -| -------------------- | --------------------------- | ----------- | -| Comparison Filtering | `it < 3` | Filters an element by performing an inline comparison. Inline comparisons can be set using [comparison](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/comparison-operators), [logical](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators), or [equality](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators) operators. | -| Predicate Filtering | `Double.IsPositive(it)` | Filters an element by calling a type predicate method. For more examples, refer to the C# type documentation - for instance, [Doubles](https://learn.microsoft.com/en-us/dotnet/api/system.double?view=net-7.0#methods). | -| NaN Filtering | `Double.IsNan(it) == false` | Filters an element by calling the `IsNan` predicate method. This is a special case of predicate filtering, notable because the output must be inverted to exclude `NaN` values. | \ No newline at end of file +| Category | Example | Description | +| -------------------- | ----------------------- | ----------- | +| Comparison Filtering | `it < 3` | Filter an element by performing an inline comparison. Inline comparisons can be set using [comparison](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/comparison-operators), [logical](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators), or [equality](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators) operators. | +| Predicate Filtering | `Double.IsPositive(it)` | Filter an element by calling a type predicate method. For more examples, refer to the type documentation, e.g. [Double](https://learn.microsoft.com/en-us/dotnet/api/system.double#methods). | +| NaN Filtering | `!Double.IsNaN(it)` | Filter an element by calling the `IsNaN` predicate method. This is a special case of predicate filtering where we invert the predicate method to exclude `NaN` values. | \ No newline at end of file diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md index 9d3f929b..103a7fae 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionTransform.md @@ -4,19 +4,16 @@ uid: Bonsai.Scripting.Expressions.ExpressionTransform [!include[](../articles/scripting-expressions-overview.md)] -### Examples +## Examples The following examples demonstrate common [Transforms](../articles/operators.md#transform) achievable with this operator. -| Category | Example | Description | -| ---------------------- | ------------------------------- | ----------- | -| Arithmetic Operations | `1.0 / (it + 2.0)` | Transforms an element using [arithmetic operators](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators). | -| Arithmetic Operations | `Math.Sqrt(it)` | Transforms an element using functions provided by the [Math](https://learn.microsoft.com/en-us/dotnet/api/system.math?view=net-7.0) class. | -| Attribute Renaming | `new(it.Item1 as X, it.Item2 as Y)` | Transforms an element's field name. Commonly used to rename column headers for the [`CsvWriter`](xref:Bonsai.IO.CsvWriter) node. | -| Conditional Expression | `it ? 1 : 0 ` | Transforms an element by returning the first value if `it` is `true`, and the second value otherwise, using the conditional operator [`?`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator). It can be placed directly after an node that outputs a Boolean value such as [`Equal`](xref:Bonsai.Expressions.EqualBuilder). It can also be used for type conversion. | -| Conditional Expression | `it < 3 ? 1 : 0 ` | Transforms an element by returning the first or second value after performing an inline comparison. Inline comparisons can be set using [comparison](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/comparison-operators), [logical](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators), or [equality](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators) operators. | -| Type Conversion | `Convert.ToDouble(it)` | Transforms an element's type using the [Convert](https://learn.microsoft.com/en-us/dotnet/api/system.convert?view=net-7.0) class. | -| Type Conversion | `TimeSpan.FromSeconds(it)` | Transforms an element's type by directly invoking an output type's method. Simplifies the required input formatting in some cases. | - -> [!Note] -> The expressions can be combined for additional flexibility. \ No newline at end of file +| Category |
Example
| Description | +| ---------------------- | ----------------------------- | -------------------- | +| Arithmetic Operations | `1.0 / (it + 2.0)` | Transform an element using [arithmetic operators](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators). | +| Arithmetic Operations | `Math.Sqrt(it)` | Transform an element using functions provided by the [Math](https://learn.microsoft.com/en-us/dotnet/api/system.math) class. | +| Attribute Renaming | `new(Item1 as X, Item2 as Y)` | Project the members of an element into a new data object. Commonly used to rename object attributes. | +| Conditional Expression | `it ? 1 : 0 ` | Convert a `Boolean` value into an integer or numerical type. | +| Type Conversion | `Double(it)` | Explicitly convert a primitive numeric type to a `Double`. | +| Type Conversion | `Convert.ToDouble(it)` | Convert an element of any primitive type (including `String` values) to a `Double` using the [Convert](https://learn.microsoft.com/en-us/dotnet/api/system.convert) class. | +| Type Conversion | `TimeSpan.FromSeconds(it)` | Convert a primitive value type into another type by directly invoking a static method in the target type. | \ No newline at end of file From 11a34e3545355e094c9f8ac74f2c39972ea9fd7a Mon Sep 17 00:00:00 2001 From: glopesdev Date: Thu, 9 Jan 2025 15:20:57 +0000 Subject: [PATCH 7/7] Add ExpressionSink examples --- ...nsai_Scripting_Expressions_ExpressionSink.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md b/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md index a81c63e5..0fb850ff 100644 --- a/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md +++ b/apidoc/Bonsai_Scripting_Expressions_ExpressionSink.md @@ -2,4 +2,19 @@ uid: Bonsai.Scripting.Expressions.ExpressionSink --- -[!include[](../articles/scripting-expressions-overview.md)] \ No newline at end of file +> [!Warning] +> In general the use of this operator should be avoided. Its main purpose is to trigger or evaluate side-effects in elements of the input sequence, which can break the immutability of values and create confusion. However, in specific applications it might be one of the few ways to interface with a specific API. + +[!include[](../articles/scripting-expressions-overview.md)] + +### Examples + +The following examples demonstrate some actions achievable with this operator. + +| Category | Example | Description | +| -------------------- | ----------------------- | ----------- | +| Method Invocation | `it.Update()` | Invoke the method `Update` on all the elements of the input sequence. | +| Property Assignment | `set_Delay(1)` | Assign a value to the `Delay` property. The expression language does not directly support assignment, but we can refer to the setter method by its canonical identifier `set_P` where `P` is the name of the property. | + +> [!Warning] +> Property assignment is only supported on reference types since for value types the expression will be evaluated on a copy of the value. This new value will not be included in the output sequence since a [Sink](../articles/operators.md#sink) operator does not modify the elements of the original sequence. \ No newline at end of file