Stream: implementers
Topic: FHIRPath Specification Questions
Michael Calderero (Jun 14 2017 at 12:31):
Hi,
I have some questions regarding the FHIRPath specification, but don't know whether the version I'm looking at is the most recent one or there's something newer.
I am looking at these:
https://github.com/FHIR/fluentpath/blob/master/spec/index.adoc
http://hl7.org/fhirpath/
Are these the latest versions?
Grahame Grieve (Jun 14 2017 at 12:37):
the current formal version is here:
Grahame Grieve (Jun 14 2017 at 12:37):
Michael Calderero (Jun 14 2017 at 15:12):
Thanks for that. I have the following questions:
1. In section 6.5 Boolean logic (i.e. http://hl7.org/fhirpath/#boolean-logic), it says:
"For all boolean operators, the collections passed as operands are first evaluated as booleans (as described in Boolean Evaluation of Collections). The operators..."
It seems to refer to a section named "Boolean Evaluation of Collections". However, I don't see such a named section in the specification. The closest I could find was http://hl7.org/fhirpath/#singleton-evaluation-of-collections. Is this the correct reference?
2. In http://hl7.org/fhir/STU3/definitions.xml.zip, in search-parameters.xml, some of the search parameters use the is() or as() functions. An example is http://hl7.org/fhir/SearchParameter/Condition-abatement-boolean.
I cannot find any definition of these functions in the FHIRPath spec. I do find the equivalent 'is' or 'as' keywords under http://hl7.org/fhirpath/#types. Are the functions equal to their keyword counterparts?
Bryn Rhodes (Jun 14 2017 at 15:15):
1. Yes, that's been corrected in the next version, but isn't published yet.
Bryn Rhodes (Jun 14 2017 at 15:16):
2. Yes, that's also been corrected, and yes, they are equivalent. They're done as part of the syntax so we can distinguish that the identifier is a "type" identifier, rather than a "variable" identifier.
Michael Calderero (Jun 14 2017 at 15:20):
Thanks. Is the unpublished version viewable? Like in GForge or something?
Bryn Rhodes (Jun 14 2017 at 15:21):
The source is in Github, and now that I'm looking at it I see that that issue is still outstanding, I thought it had been corrected.
Bryn Rhodes (Jun 14 2017 at 15:21):
https://github.com/FHIR/fluentpath/blob/master/spec/index.adoc
Bryn Rhodes (Jun 14 2017 at 15:21):
I'll fix it.
Bryn Rhodes (Jun 14 2017 at 15:27):
There's actually a tracker on it too: http://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=12583&start=0
Michael Calderero (Jun 14 2017 at 15:34):
I had forgotten about that issue I posted on GForge. My bad.
But for my question #2, it seems that https://github.com/FHIR/fluentpath/blob/master/spec/index.adoc is not yet updated. Do you want me to put in a GForge ticket for this?
Bryn Rhodes (Jun 14 2017 at 15:35):
No, in looking at that ticket, it was auto-deferred, so we can just put it back to open and apply the change.
Bryn Rhodes (Jun 14 2017 at 15:39):
For question #2, the github is correct, is and as are keywords.
Bryn Rhodes (Jun 14 2017 at 15:41):
But yes, I see that they are used as functions in the FHIRPath for the search parameters in the spec.
Bryn Rhodes (Jun 14 2017 at 15:42):
So yes, log a ticket for that so we can sort it.
Bryn Rhodes (Jun 14 2017 at 15:43):
Actually, looks like Ewout just did.
Ivan Dubrov (Feb 22 2018 at 20:04):
So, what is the correct semantics for the "Boolean Evaluation of Collections" (I wasn't able to find it anywhere).
Is it that single boolean value evaluates to that value, empty collection evaluates to empty and anything else is "true"?
Bryn Rhodes (Feb 22 2018 at 20:42):
Singleton evaluation of collections
Bryn Rhodes (Feb 22 2018 at 20:44):
Boolean evaluation of collections is a special case of singleton evaluation. In general, it's an error to attempt to evaluate a collection with more than one thing in it as a singleton.
Ivan Dubrov (Feb 22 2018 at 20:56):
Would non-boolean produce an error or evaluate to 'true'?
Reason I'm asking is that I see the following FHIRPath in standard definitions: "(code or value.empty()) and (system.empty() or system = 'urn:iso:std:iso:4217')", which implies that non-empty code should evaluate to true.
Ivan Dubrov (Feb 22 2018 at 20:58):
(it's in Money definition)
Lloyd McKenzie (Feb 22 2018 at 21:04):
@Bryn Rhodes
Bryn Rhodes (Feb 22 2018 at 22:17):
Hmmm.... seems like it shouldn't evaluate to me, should be (code.exists() or value.empty()) and (system.empty() or system = 'urn:iso:std:iso:4217')
Grahame Grieve (Feb 22 2018 at 22:26):
indeed that should be corrected
Bryn Rhodes (Feb 22 2018 at 22:50):
Lloyd McKenzie (Feb 22 2018 at 23:19):
Marked as an auto-approved typo
Ivan Dubrov (Feb 26 2018 at 19:12):
Here is one more inconsistency between the spec and its application.
For example, spec doesn't define ".in()" function (), but rather an "in" operator. However, both spec and real definitions use "in" as a function.
Same for the "as" operator.
So, in those two cases, should those be both supported as a "function" and as an "operator" or only as an operator?
Ivan Dubrov (Feb 26 2018 at 19:19):
There is also a lot of other things, like missing .exists()
, as in example above, comparing single item versus a collection (like in value.empty() or code!=component.code
for Observation), assuming short-cutting "or" operator (like in min.empty() or max.empty() or (max = '*') or (min <= max.toInteger())
, toInteger will fail if max = '*'
).
(plus some of the data in examples doesn't pass validation, like bmi-questionnaire.json missing "linkId" elements here and there).
Should I report all these cases one by one or maybe I can just list all of them as a bulk item?
Bryn Rhodes (Feb 26 2018 at 19:21):
I don't see a reference to .in() in the spec, in is defined as an operator in the spec and the grammar.
Bryn Rhodes (Feb 26 2018 at 19:22):
For is
and as
, they are defined in the spec and the grammar as operators, but I do see examples that use them as functions. I'd suggest a tracker for that on FHIRPath.
Bryn Rhodes (Feb 26 2018 at 19:22):
For the use of .in()
in the spec, I'd say that would be a tracker against FHIR, citing the invariant that uses it.
Bryn Rhodes (Feb 26 2018 at 19:22):
Separate trackers for the items in FHIRPath are preferable, it's easier to track the specific resolutions for the issues.
Ivan Dubrov (Feb 26 2018 at 19:29):
You are right about ".in()", it was just one of the constraints.
I'll open separate tickets.
Bryn Rhodes (Feb 26 2018 at 20:09):
Thank you!
Ivan Dubrov (Feb 26 2018 at 21:42):
Created few:
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=15648
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=15649
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=15650
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=15651
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=15652
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=15653
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=15654
Ewout Kramer (Feb 27 2018 at 09:44):
There is also a lot of other things, like missing
.exists()
, as in example above, comparing single item versus a collection (like in `value.empty() or (...)Should I report all these cases one by one or maybe I can just list all of them as a bulk item?
Hi Ivan, these inconsistencies are because of a change of the boolean interpretation of empty arrays & introduction of three-valued logic in STU3. We tried to manually hunt these mistakes down & fix them, but obviously we've missed a few. Thanks for pointing them out!
Ewout Kramer (Feb 27 2018 at 09:45):
@Bryn Rhodes @Grahame Grieve: I think we need to continue our discussion around sum() or aggregate/fold (and possible lambda notation) for the FhirPath normative?
Grahame Grieve (Feb 27 2018 at 10:00):
we do. though I don't know about the lambda bit?
Ewout Kramer (Feb 27 2018 at 10:08):
The major question is:
- Option A: We add just sum(), which works on a collection of numbers and sums the numbers
- Option B: We generalize and introduce explicit lambda notation like so:
Patient.name.first.aggregate(\total arg -> $total & $arg)
(just borrowing from Haskell here) - which would allow you to sum/aggregate anything in any way, since you're not bound to just sums - Option C: Another magic variable
$total
(much like $this), which only appears inaggregate
:Patient.name.first.aggregate($total & $this)
Ewout Kramer (Feb 27 2018 at 10:22):
I think the third option is closest to our current design - where() etc introduce a magic $this, aggregate() could introduce $total.
Interestingly, repeat()
could then be rewritten using aggregate()
:
Questionnaire.repeat(group | question).question
becomes
Questionnaire.aggregate($total | (group | question)).question
Bryn Rhodes (Feb 27 2018 at 17:08):
Option A is the most well understood, but least flexible. It's the least likely to be considered a substantive change.
Bryn Rhodes (Feb 27 2018 at 17:09):
Option B is, I think, the least understood, but most flexible, and I think would be considered substantive, it's a pretty big change in terms of functionality, even if not in terms of the actual grammar and specification.
Bryn Rhodes (Feb 27 2018 at 17:11):
Option C is my favorite, it's not as flexible as lambdas, but it's also a very focused change so much less likely to be considered substantive. I actually really like it, it supports everything we need and more, nice proposal @Ewout Kramer
Grahame Grieve (Feb 27 2018 at 18:05):
I understand this: Patient.name.first.aggregate($total & $this) - but I find it not useful because of the need for a separator in most cases - an 'all but the first' action.
Grahame Grieve (Feb 27 2018 at 18:05):
but I don't understand this: Questionnaire.aggregate($total | (group | question)).question - what is aggregate aggregating on? Is this a mistake, or something I don't understand?
Bryn Rhodes (Feb 27 2018 at 19:38):
Patient.name.first().aggregate($total & $total.iif(exists(), ', ') & $this)
Bryn Rhodes (Feb 27 2018 at 19:38):
For the second one, it's aggregating the list, so union is the aggregate function.
Grahame Grieve (Feb 27 2018 at 20:04):
how is it different to (Questionnaire.group | Questionnaire.question) ? Surely you have to have a list as focus in order to actually aggregate something?
nicola (RIO/SS) (Feb 27 2018 at 20:17):
Are you going create Turing complete language with perl syntax?
Grahame Grieve (Feb 27 2018 at 20:18):
no but that sounds like fun. It'll only take you a few minutes to do that...
Ewout Kramer (Feb 28 2018 at 16:16):
but I don't understand this: Questionnaire.aggregate($total | (group | question)).question - what is aggregate aggregating on? Is this a mistake, or something I don't understand?
No, I was a bit too enthousiastic ;-) We can't get rid of the repeat() unfortunately.
Ewout Kramer (Feb 28 2018 at 16:17):
Are you going create Turing complete language with perl syntax?
Thinking about addinc let rec
....
Brian Postlethwaite (Feb 28 2018 at 22:37):
With the aggregate functions, need to be very careful that they don't operate on a list that has had duplicates removed, will skew values and make sums incorrect.
Last updated: Apr 12 2022 at 19:14 UTC