Lambda function to return default value for NULL and UNDEF items

Hi,

I usually use lambda functions of the following form in my calculations to make the code cleaner if items must be handled with a default value like 0 if they carry NULL:

val Functions$Function1 < GenericItem, Float > nvlFloat = [ theItem |
   var Float theValue = 0.0f
   if (theItem.state != NULL) theValue = theItem.getStateAs(DecimalType).floatValue
   theValue
] 
val Functions$Function1 < GenericItem, Integer > nvlInt = [ theItem |
   var int theValue = 0
   if (theItem.state != NULL) theValue = theItem.getStateAs(DecimalType).intValue
   theValue
] 

The usage of those functions look like this:

   if (
      (  (nvlInt.apply(I_Wetter_AktuellID) >= 800 && nvlInt.apply(I_Wetter_AktuellID) <= 802) 
      || (nvlInt.apply(I_Wetter_3Stunden_VorhersageID) >= 800 && nvlInt.apply(I_Wetter_3Stunden_VorhersageID) <= 802) 
      || (nvlInt.apply(I_Wetter_6Stunden_VorhersageID) >= 800 && nvlInt.apply(I_Wetter_6Stunden_VorhersageID) <= 802)
      ) {
         sunForecasted = true
   }

      if (nvlFloat.apply(I_EG_WZ_Ofenthermometer_Ofen) > 40.0 && nvlFloat.apply(I_EG_WZ_Ofenthermometer_Ofen) < 70.0 
         && nvlFloat.apply(I_KG_Heizraum_Solar_Speichertemperatur) < 50.0
         && nvlFloat.apply(G_Aussentemperatur) <= 10.0
         && nvlInt.apply(I_Wetter_3Stunden_VorhersageID) != 800 && nvlInt.apply(I_Wetter_3Stunden_VorhersageID) != 801
         && nvlInt.apply(I_Wetter_6Stunden_VorhersageID) != 800
         && nvlFloat.apply(I_KG_Heizraum_Solar_Kollektortemperatur) <= nvlFloat.apply(I_KG_Heizraum_Solar_Speichertemperatur) 
      ) {
         I_EG_WZ_Ofen_Nachlegeempfehlung.sendCommand(ON)
      } else {
         I_EG_WZ_Ofen_Nachlegeempfehlung.sendCommand(OFF)
      }

In the discussion Operator_multiply(float,float) on instance null Rich proposed a more generic lambda function that drops the need of differentiating the value type:

val nvl = [ GenericItem theItem |
    if(theItem.state == NULL || theItem.state == UNDEF) 0 else theItem.state as Number
]

However, I found that this gives me headaches if the item is of a QuantityType, and most often I only need the actual numeric value in my rules to calculate with.
My question would be: Is there a way to write this funtion such that it delivers only the number portion whether the item is a QuantityType or not?
rossko57 explained a lot on handling QuantityTypes in other threads (e.g. Working with Number:Temperature Items in rules), from which I took the following could work:

val nvl = [ GenericItem theItem |
    if(theItem.state == NULL || theItem.state == UNDEF) 0 else (theItem.state as QuantityType<Number>).toBigDecimal
]

However, this variant fails if the item is a pure Number item.
Is there a way to find out if the GenericItem is a Number item or a QuantityItem?

Thanks,
stedon81

Hi,

thanks to what I learned from Rich, I think I got the solution on my own.
The following function will do the trick:

val nvl = [ GenericItem theItem |
    if(theItem.state == NULL || theItem.state == UNDEF) 0 else theItem.getStateAs(DecimalType)
]

The clue is to not specify the lambda as type of Functions$Function1, so you are not forced to specify a return type. I really have to get used to program type-less with this rules DSL…

Hope this helps others who stumble over similar issues.

Regards,
stedon81

If it’s a problem, you should consider one of the other languages. If you have lots of lambdas like this, it’s a sign that that you are fighting the language and you’re going to have a miserable experience.