Skip to content

Commit aa20b5d

Browse files
maskri17copybara-github
authored andcommitted
Updating the README.md with CelComprehensionsExtensions docs
PiperOrigin-RevId: 802209374
1 parent a138ce3 commit aa20b5d

1 file changed

Lines changed: 130 additions & 0 deletions

File tree

  • extensions/src/main/java/dev/cel/extensions

extensions/src/main/java/dev/cel/extensions/README.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,3 +912,133 @@ regex.extractAll('id:123, id:456', 'assa') == []
912912
913913
regex.extractAll('testuser@testdomain', '(.*)@([^.]*)') \\ Runtime Error multiple capture group
914914
```
915+
## TwoVarComprehensions
916+
917+
TwoVarComprehensions introduces support for two-variable comprehensions.
918+
919+
The two-variable form of comprehensions looks similar to the one-variable
920+
counterparts. Where possible, the same macro names were used and additional
921+
macro signatures added. The notable distinction for two-variable comprehensions
922+
is the introduction of `transformList`, `transformMap`, and `transformMapEntry`
923+
support for list and map types rather than the more traditional `map` and
924+
`filter` macros.
925+
926+
### All
927+
928+
Comprehension which tests whether all elements in the list or map satisfy a
929+
given predicate. The `all` macro evaluates in a manner consistent with logical
930+
AND and will short-circuit when encountering a `false` value.
931+
932+
<list>.all(indexVar, valueVar, <predicate>) -> bool
933+
<map>.all(keyVar, valueVar, <predicate>) -> bool
934+
935+
Examples:
936+
937+
[1, 2, 3].all(i, j, i < j) // returns true
938+
{'hello': 'world', 'taco': 'taco'}.all(k, v, k != v) // returns false
939+
940+
// Combines two-variable comprehension with single variable
941+
{'h': ['hello', 'hi'], 'j': ['joke', 'jog']}
942+
.all(k, vals, vals.all(v, v.startsWith(k))) // returns true
943+
944+
### Exists
945+
946+
Comprehension which tests whether any element in a list or map exists which
947+
satisfies a given predicate. The `exists` macro evaluates in a manner consistent
948+
with logical OR and will short-circuit when encountering a `true` value.
949+
950+
<list>.exists(indexVar, valueVar, <predicate>) -> bool
951+
<map>.exists(keyVar, valueVar, <predicate>) -> bool
952+
953+
Examples:
954+
955+
{'greeting': 'hello', 'farewell': 'goodbye'}
956+
.exists(k, v, k.startsWith('good') || v.endsWith('bye')) // returns true
957+
[1, 2, 4, 8, 16].exists(i, v, v == 1024 && i == 10) // returns false
958+
959+
### Exists_One
960+
961+
Comprehension which tests whether exactly one element in a list or map exists
962+
which satisfies a given predicate expression. The `exists_one` macro
963+
comprehension does not short-circuit in keeping with the one-variable semantics.
964+
965+
<list>.existsOne(indexVar, valueVar, <predicate>)
966+
<map>.existsOne(keyVar, valueVar, <predicate>)
967+
968+
Examples:
969+
970+
[1, 2, 1, 3, 1, 4].existsOne(i, v, i == 1 || v == 1) // returns false
971+
[1, 1, 2, 2, 3, 3].existsOne(i, v, i == 2 && v == 2) // returns true
972+
{'i': 0, 'j': 1, 'k': 2}.existsOne(i, v, i == 'l' || v == 1) // returns true
973+
974+
### TransformList
975+
976+
Comprehension which converts a map or a list into a list value. The output
977+
expression of the comprehension determines the contents of the output list.
978+
Elements in the list may optionally be filtered according to a predicate
979+
expression, where elements that satisfy the predicate are transformed.
980+
981+
<list>.transformList(indexVar, valueVar, <transform>)
982+
<list>.transformList(indexVar, valueVar, <filter>, <transform>)
983+
<map>.transformList(keyVar, valueVar, <transform>)
984+
<map>.transformList(keyVar, valueVar, <filter>, <transform>)
985+
986+
Examples:
987+
988+
[1, 2, 3].transformList(indexVar, valueVar,
989+
(indexVar * valueVar) + valueVar) // returns [1, 4, 9]
990+
[1, 2, 3].transformList(indexVar, valueVar, indexVar % 2 == 0
991+
(indexVar * valueVar) + valueVar) // returns [1, 9]
992+
{'greeting': 'hello', 'farewell': 'goodbye'}
993+
.transformList(k, _, k) // returns ['greeting', 'farewell']
994+
{'greeting': 'hello', 'farewell': 'goodbye'}
995+
.transformList(_, v, v) // returns ['hello', 'goodbye']
996+
997+
### TransformMap
998+
999+
Comprehension which converts a map or a list into a map value. The output
1000+
expression of the comprehension determines the value of the output map entry;
1001+
however, the key remains fixed. Elements in the map may optionally be filtered
1002+
according to a predicate expression, where elements that satisfy the predicate
1003+
are transformed.
1004+
1005+
<list>.transformMap(indexVar, valueVar, <transform>)
1006+
<list>.transformMap(indexVar, valueVar, <filter>, <transform>)
1007+
<map>.transformMap(keyVar, valueVar, <transform>)
1008+
<map>.transformMap(keyVar, valueVar, <filter>, <transform>)
1009+
1010+
Examples:
1011+
1012+
[1, 2, 3].transformMap(indexVar, valueVar,
1013+
(indexVar * valueVar) + valueVar) // returns {0: 1, 1: 4, 2: 9}
1014+
[1, 2, 3].transformMap(indexVar, valueVar, indexVar % 2 == 0
1015+
(indexVar * valueVar) + valueVar) // returns {0: 1, 2: 9}
1016+
{'greeting': 'hi'}.transformMap(k, v, v + '!') // returns {'greeting': 'hi!'}
1017+
1018+
### TransformMapEntry
1019+
1020+
Comprehension which converts a map or a list into a map value; however, this
1021+
transform expects the entry expression be a map literal. If the transform
1022+
produces an entry which duplicates a key in the target map, the comprehension
1023+
will error. Note, that key equality is determined using CEL equality which
1024+
asserts that numeric values which are equal, even if they don't have the same
1025+
type will cause a key collision.
1026+
1027+
Elements in the map may optionally be filtered according to a predicate
1028+
expression, where elements that satisfy the predicate are transformed.
1029+
1030+
<list>.transformMapEntry(indexVar, valueVar, <transform>)
1031+
<list>.transformMapEntry(indexVar, valueVar, <filter>, <transform>)
1032+
<map>.transformMapEntry(keyVar, valueVar, <transform>)
1033+
<map>.transformMapEntry(keyVar, valueVar, <filter>, <transform>)
1034+
1035+
Examples:
1036+
1037+
{'greeting': 'hello'}.transformMapEntry(keyVar, valueVar,
1038+
{valueVar: keyVar}) // returns {'hello': 'greeting'}
1039+
// reverse lookup, require all values in list be unique
1040+
[1, 2, 3].transformMapEntry(indexVar, valueVar,
1041+
{valueVar: indexVar}) // returns {1:0, 2:1, 3:2}
1042+
1043+
{'greeting': 'aloha', 'farewell': 'aloha'}
1044+
.transformMapEntry(k, v, {v: k}) // error, duplicate key

0 commit comments

Comments
 (0)