According to the ELM spec,
https://cql.hl7.org/04-logicalspecification.html#tolist
The operator is effectively shorthand for "if operand is null then { } else { operand }".
However:
https://github.com/cqframework/clinical_quality_language/blob/d10c4ef801a8e160510b2a868c044dea5bdb85c1/Src/java/engine/src/main/java/org/opencds/cqf/cql/engine/elm/execution/ToListEvaluator.java
When operand is already a list, the ruler simply returns the operand. That logic is on line 12.
This is important as the cql-to-elm translator assumes this behavior. Consider this CQL:
private codesystem "Test": 'https://example.org/fhir/codesystem/test-cs'
private code "Code 1": '1' from "Test"
private code "Code 2": '2' from "Test"
private code "Code 3": '3' from "Test"
define "Test Codes": { "Code 1", "Code 2", "Code 3" }
define "Retrieve with list of codes": [Observation : "Test Codes"]
The translator is generating this ELM for the codes property of the Retrieve:
"expression" : {
"type" : "Retrieve",
"codes" : {
"type" : "ToList",
"operand" : {
"type" : "ExpressionRef",
"resultTypeSpecifier" : {
"type" : "ListTypeSpecifier",
"elementType" : {
"type" : "NamedTypeSpecifier",
"name" : "{urn:hl7-org:elm-types:r1}Code"
}
},
"locator" : "24:54-24:65",
"name" : "Test Codes"
}
},
Because the ruler ignores the ToList for expressions that are already lists, it codes would end up being expressed as a List<Code>.
If you were to follow the letter of the ELM spec, codes ends up expressed as a List<List<Code>>.
This confounds engines that expect the terminology element of the retrieve statement to be a List<Code> (or a value set, which is implicitly convertible to a List<Code>).
According to the ELM spec,
https://cql.hl7.org/04-logicalspecification.html#tolist
However:
https://github.com/cqframework/clinical_quality_language/blob/d10c4ef801a8e160510b2a868c044dea5bdb85c1/Src/java/engine/src/main/java/org/opencds/cqf/cql/engine/elm/execution/ToListEvaluator.java
When operand is already a list, the ruler simply returns the operand. That logic is on line 12.
This is important as the cql-to-elm translator assumes this behavior. Consider this CQL:
The translator is generating this ELM for the codes property of the Retrieve:
Because the ruler ignores the ToList for expressions that are already lists, it codes would end up being expressed as a
List<Code>.If you were to follow the letter of the ELM spec, codes ends up expressed as a
List<List<Code>>.This confounds engines that expect the terminology element of the retrieve statement to be a
List<Code> (or a value set, which is implicitly convertible to aList<Code>).