FHIR Chat · Single value from function changes to a list · cql

Stream: cql

Topic: Single value from function changes to a list


view this post on Zulip Michael Riley (Jun 03 2021 at 18:15):

I've been writing a script to capture an index date of a covid immunization with the FHIR library on cql. But I'm having an issue with typing of returns from functions. I'm working from this initial script definition

library "TestExampleOfFunction" version '0.0.1'
using FHIR version '4.0.0'
include "FHIRHelpers" version '4.0.0' called FHIRHelpers
codesystem "ICD-10-CM": 'http://hl7.org/fhir/sid/icd-10-cm'
codesystem "CVX": 'http://hl7.org/fhir/sid/cvx'
codesystem "RxNorm": 'http://www.nlm.nih.gov/research/umls/rxnorm'
codesystem "NDC": 'http://hl7.org/fhir/sid/ndc'
codesystem "CPT": 'http://www.ama-assn.org/go/cpt'

*Covid Vaccine Drug Exposure definition ommited for space*

context Patient

define "CovidImmunization": [Immunization: "Covid Vaccine Drug Exposure".codes]

define "MostRecentCovidI": MostRecentImmunizationDT("CovidImmunization")

define function MostRecentImmunizationDT(ImmunizationList List<FHIR.Immunization>):
  from ImmunizationList I
  let result: Last(ImmunizationList I sort by (occurrence as FHIR.dateTime).value asc)
    return (result.occurrence as FHIR.dateTime).value

define "testRange":
  Interval[ "MostRecentCovidI" + 1 day, "MostRecentCovidI" + 42 days]

Now when I run this definition, I get a weird typing on "MostRecentCovidI" on the testRange definition

Error [53:13] Could not resolve call to operator Add with signature (list<System.DateTime>,System.Quantity).

So it seems like the 'result' variable comes back as a tuple of a list with a quantity, which seems very odd, I was expecting a FHIR.dateTime.value which would be a system.DateTime in cql.

So I try and reduce the result scope variable in the function definition itself and add another Last clause in the definition like so.

define function MostRecentImmunizationDT(ImmunizationList List<FHIR.Immunization>):
  from ImmunizationList I
  let result: Last(ImmunizationList I sort by (occurrence as FHIR.dateTime).value asc)
    return Last((result.occurrence as FHIR.dateTime).value)

This generates an error saying that the return value is already a System.DateTime, and the Last function cannot work on it.

Error [50:12] Could not resolve call to operator Last with signature (System.DateTime).

So the return is already defined as a System.DateTime, but the only way I'm able to move forward on my script is to change my top level definition to

define "MostRecentCovidI": Last(MostRecentImmunizationDT("CovidImmunization"))

Which makes no sense, the return type should have been a System.DateTime not a list. What's going on here? Is the return clause not firing correctly? Is this a poor way to craft functions? And what's a better way to check runtime types of defines?

view this post on Zulip JP (Jun 03 2021 at 19:32):

This code is a bit redundant in the sense that you're effectively generating the cross-product of ImmunizationList with itself

define function MostRecentImmunizationDT(ImmunizationList List<FHIR.Immunization>):
  from ImmunizationList I
  let result: Last(ImmunizationList I sort by (occurrence as FHIR.dateTime).value asc)
    return (result.occurrence as FHIR.dateTime).value

I think what you're looking for is:

define function MostRecentImmunizationDT(ImmunizationList List<FHIR.Immunization>):
Last(ImmunizationList I
  return (I.occurrence as FHIR.dateTime).value
  sort asc)

That creates a List of dateTime ordered earliest to latest, then gets the last one.

view this post on Zulip JP (Jun 03 2021 at 19:34):

As far as this error is concerned, the latter parameter that's showing as a Quantity is due to first parameter being a List and causing some type inference to blow up. There might be a way to improve the messaging in the future in the translator.

Error [53:13] Could not resolve call to operator Add with signature (list<System.DateTime>,System.Quantity).

view this post on Zulip Michael Riley (Jun 04 2021 at 14:57):

Thank you for the help here. I will be more careful with the from clause, I thought I still needed the multi-query from clause to define the retrieval, as i wanted my return clause to be very clear in the function. but clearly you can just run the filters, and access down the List via an INTERNAL return clause.


Last updated: Apr 12 2022 at 19:14 UTC