# \[SOLVED\] Conditional statement with a Lambda function variable

**URL:** <https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753>\
**Category:** Scripts & Rules\
**Tags:** rules\
**Created:** [August 11, 2019, 2:52pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753 "2019-08-11T14:52:24Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![funky28](https://community.openhab.org/user_avatar/community.openhab.org/funky28/32/36103_2.png) [@funky28](https://community.openhab.org/u/funky28)\
**Post date:** [August 11, 2019, 2:52pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/1 "2019-08-11T14:52:24Z")

</div>

Hi, I am trying to create/use Lambdas inside of my rules to avoid repeating code over and over, I am having issues with a simple “If” statement when using a Lambda defined variable that is a string. I did seach around the forum and with google but could not find an answer.

For the sake of simplicity, I am posting a simple example code that resembles what I want to do:

```csv
  val test_lambda = [ state s |
     if ( s = OFF ) { logInfo("test_rule","THE TEST WORKED, THE STATE IS {}.", item.label)}
     true ]
  test_lambda.apply (OFF)

```

But when executing, I get some errors.. first when loading/saving the file get this:

```csv
09:39:56.593 [INFO] [del.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'test.rules', using it anyway:                                                                          
Assignment to final parameter

```

And then when it executes I get:

```csv
09:41:30.002 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'test': Couldn't invoke 'assignValueTo' for feature param s

```

I experimented with using the “==” instead of “=” on the conditional statement, which cleared the loading/saving warning about the Validation issue, but when the rule executes i get:

```csv
09:48:30.066 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'test': Unknown variable or command '=='; line 12, column 22, length 8

```

I have tried using quotes around the Lambda variable definition and in the conditional statement as well.. but with no avail. I suspect the issue is around the fact that the variable is not recognized as a string and thus I get the error, I the past I had a similar issue with a Lambda variable that was a number (a temperature), and I had to define the variable “as Number” in order of the conditional statement to work… I am not sure if one can do the same for strings. I did try using the “toString” state but sill got errors.

Any help is greatly appreciated.

Thanks!

---

<div class="post-metadata">

**Author:** ![mstormi](https://community.openhab.org/user_avatar/community.openhab.org/mstormi/32/55857_2.png) [@mstormi](https://community.openhab.org/u/mstormi)\
**Post date:** [August 11, 2019, 3:03pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/2 "2019-08-11T15:03:42Z")

</div>

You are making the mistake to believe s is a parameter. It is not. The last variable ALWAYS needs to be declared because it defines the return value. So if you want to pass one parameter you need to have two variable declared in the `val ...` line. Just wrote almost the same answer [here](https://community.openhab.org/t/lambda-used-for-timer-does-not-accecpt-parameter/79748/2).

---

<div class="post-metadata">

**Author:** ![funky28](https://community.openhab.org/user_avatar/community.openhab.org/funky28/32/36103_2.png) [@funky28](https://community.openhab.org/u/funky28)\
**Post date:** [August 11, 2019, 4:52pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/3 "2019-08-11T16:52:03Z")

</div>

Thanks for the quick reply… so, I read your other post and incorporating your suggestion of having two variables declared i came up with:

```csv
    val test_lambda = [ state1 s1, state2 s2 |
        var Boolean ret = true
        if ( s1 = OFF ) {logInfo("test_rule","THE TEST WORKED, THE STATE IS {}.", item.label)}
        ret ]
    test_lambda.apply (OFF, OFF)

```

I did not get any validation errors, but the rule still does not run, here is what I get:

```csv
11:42:00.071 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'test': Couldn't invoke 'assignValueTo' for feature param s1

```

I even tried to pass s1 into another defined variable within the rule, but got the same error…

Can you help understand what am I doing wrong? i’ve read so many treads about how to properly use Lambda, but still not sure how to approach this scenario.

Unrelated question: What is the benefit of defining the variable “ret” as “true” and then calling it out in the end, vs the way I had it to begin with, which was just to type “true” at the end of the function?

Thanks for the help.

---

<div class="post-metadata">

**Author:** ![mstormi](https://community.openhab.org/user_avatar/community.openhab.org/mstormi/32/55857_2.png) [@mstormi](https://community.openhab.org/u/mstormi)\
**Post date:** [August 11, 2019, 5:40pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/4 "2019-08-11T17:40:09Z")

</div>

> [@funky28](#):
>
> Can you help understand what am I doing wrong?

Well seems like you’re a beginner with not much programming experience as there’s several things you’re lacking to understand.  
So my first and foremost advice is: start low. Read more examples before trying to implement it yourself. Check out @rlkoshak’s [design patterns](https://community.openhab.org/search?q=tags%3Adesignpattern).  
Lambdas you shouldn’t use as a beginner as they’re the most advanced construct in rules DSL and the one to have the most pitfalls.

In your code:

- you mustn’t use “state1”/“state2”, these need to be variable types (Number, Boolean, whatever)
- you mustn’t do s1 = OFF that’s an assignment, not a test
- you must declare the Function to have a specific number of parameters, see other thread

> [@funky28](#):
>
> What is the benefit of defining the variable “ret” as “true” and then calling it out in the end, vs the way I had it to begin with, which was just to type “true” at the end of the function?

No imminent advantage - you can just write “true”. But if depending on the input there’s a problem, one would want to be able to make that a dynamic answer.

---

<div class="post-metadata">

**Author:** ![chriscolden](https://community.openhab.org/user_avatar/community.openhab.org/chriscolden/32/71507_2.png) [@chriscolden](https://community.openhab.org/u/chriscolden)\
**Post date:** [August 11, 2019, 5:42pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/5 "2019-08-11T17:42:35Z")

</div>

Here is an example of how I define mine.

```csv
val Functions$Function2<String, String, Boolean> test_lambda = [ s1, s2 |
    LOGIC GOES HERE    
    true
]

```

Where Function2 is the number of parameters were passing in. The types go in the \< \> plus the additional return type of Boolean, function name in this case is test\_lambda.

Always return true, unless your logic can support other states or return variables. Mine usually dont, so I just return true.

Chris

---

<div class="post-metadata">

**Author:** ![funky28](https://community.openhab.org/user_avatar/community.openhab.org/funky28/32/36103_2.png) [@funky28](https://community.openhab.org/u/funky28)\
**Post date:** [August 11, 2019, 6:12pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/6 "2019-08-11T18:12:37Z")

</div>

Thanks for the help @mstormi, yes I am a beginner and i appreciate all of the help the openhab community offers.

@chriscolden, thanks for providing the example, it was not clear to me that I needed to define the number of parameters as well as the types, the example helped a lot and now I have a better understand and my logic works.

Hugo

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [August 11, 2019, 10:08pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/7 "2019-08-11T22:08:33Z")

</div>

> [@funky28](#):
>
> I am trying to create/use Lambdas inside of my rules to avoid repeating code over and over

There are far better approaches than using global lambdas in the Rules DSL. Global lambdas have a lot of problems which really make them only usable as a last resort. They should _never_ be the first thing you use to help make code better. See [Design Pattern: DRY, How Not to Repeat Yourself in Rules DSL](https://community.openhab.org/t/design-pattern-dry-how-not-to-repeat-yourself-in-rules-dsl/60105) for techniques which do work (using lambdas is among them).

> [@funky28](#):
>
> I am posting a simple example code that resembles what I want to do:

We need more context to understand this code. Is it in a Rule? Is the lambda definition within a Rule too? Where do you define `item`? Sometimes attempts to “simplify” a Rule before posting destroys the very detail we need to help.

There is no such type as `state`. Do you mean `State`? Rules DSL is case sensitive. And usually it is more appropriate to be more specific, such as `OnOffType` or `NumberType` rather than the very generic `State`. You are unlikely to be writing lambdas for that diverse of Item types.

You haven’t passed `item` into the lambda.

> [@funky28](#):
>
> I get some errors

As Markus pointed out, you are trying to assign OFF to `s` when what you mean to do is a comparison which requires `==`".

> [@funky28](#):
>
> but when the rule executes i get

That’s because it doesn’t know what to do with `s`. You’ve tried to make it of type `state` which doesn’t exist.

> [@funky28](#):
>
> I suspect the issue is around the fact that the variable is not recognized as a string and thus I get the error,

No, neither the variable `s` nor the `OFF` are Strings, they are `OnOffTypes`, which is the type of `State` carried by Switch Items.

> [@mstormi](#):
>
> The last variable ALWAYS needs to be declared because it defines the return value. So if you want to pass one parameter you need to have two variable declared in the `val`

That is actually an old syntax requirement. What OP did is perfectly acceptable since OH 2.3 (and before OH 2.0). It’s all the other stuff you identified that was causing problems. See [Reusable Functions: A simple lambda example with copious notes](https://community.openhab.org/t/reusable-functions-a-simple-lambda-example-with-copious-notes/15888) for details. The tl;dr is you don’t have to specify the Functions$Function1 with a return type or Procedures$Procedure (no return). The Rules DSL is smart enough to figure out the number and type of the arguments and if the last line returns void it will use Procedures$X and if it returns something it will use Functions$X and the appropriate type for the return value.

> [@funky28](#):
>
> variables declared i came up with:

That would work from a lambda declaration perspective but there are no `state1` and `state2` types.

Since you don’t care about the return value, eliminate the whole `true` stuff. Leave it out and the lambda won’t return anything which is perfectly OK.

> [@mstormi](#):
>
> Lambdas you shouldn’t use as a beginner as they’re the most advanced construct in rules DSL and the one to have the most pitfalls.

I agree. Even as an expert, global lambdas should only be used as a last resort. They are not thread safe so their use will cause more problems than they solve.

> [@mstormi](#):
>
> you must declare the Function to have a specific number of parameters, see other thread

This part is not required. It was for awhile but then I think the upstream Xtend/Xtext libraries fixed something and now we can do it the “nicer” way.

> [@chriscolden](#):
>
> Where Function2 is the number of parameters were passing in. The types go in the \< \> plus the additional return type of Boolean, function name in this case is test\_lambda.
> 
> Always return true, unless your logic can support other states or return variables. Mine usually dont, so I just return true.

```php
val test_lambda = [ String s1, String s2 |
    // LOGIC GOES HERE
]

```

would also work.

---

<div class="post-metadata">

**Author:** ![funky28](https://community.openhab.org/user_avatar/community.openhab.org/funky28/32/36103_2.png) [@funky28](https://community.openhab.org/u/funky28)\
**Post date:** [August 11, 2019, 10:44pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/8 "2019-08-11T22:44:53Z")

</div>

I guess part of my issue was my miss-understanding of the Lambda syntax, it was not clear to me that one could/needed to define the Type before the variable, in this case a `String ` or a `OnOffType `.. I thought it was a label for the parameter itself, hence I used `state `.

I know is always best to show the whole code so help can be more efficient and tailored.. I was just trying to get to the point… let’s call it beginner’s experience.

After the example posted with the old syntax, I quickly realized where my problem was and was able to fix it. I was able to define the type as OnOffType as you pointed out (Virtual Studio helped me with this one!).

I should have known better than to know i needed a == to make a test/comparison.. I just got frustrated at the lack of progress on my end. My oversight.

I have did read lots of threads and posting, and I was aware that Lambdas carried some level of extra difficulty and constrains, but at least i found it to be an elegant and clean solution… at least in my eyes.

So, for the sake of completeness, I have a Design Pattern rule file to specify different Activities through the day. I have a couple of electrical outlets with an air freshener that I wanted to turn on during Lunch and Dinner time and then turn it off at any other day activity . I have a different rule file with the DP for the Day\_Activity definitions and the rule below is a separate rule file on how I execute different commands as the Day Activity changes (I deleted some of the other code lines for other commands, as they are not relevant to the question).

```csv
rule "Thrigger Activites based on DayState changes"
when
    // Time cron "0/30 0/1 * 1/1 * ? *" or // Run every 30 seconds for debugging purposes 
    Item Day_Activity changed
then    
    // Variables / Values: -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    var rule_name = "MyRules.Daystate"
    // Functions: -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    val Functions$Function1 <OnOffType,Boolean> outlet_control = [ s1 |
        Sycamore_Outlet.allMembers.forEach(item | { 
            if( item.state != s1 && item.label.toString.contains("Left") ) {
                item.sendCommand(s1)
                if ( s1 == ON ) { logInfo(rule_name,"We are probably cooking!!! Turning ON the Air Wick on {}.", item.label)}
                if ( s1 == OFF ) { logInfo(rule_name,"Turning Off the Air Wick on {}.", item.label)}
            }
        }) true ]
    val Functions$Function1 <OnOffType,Boolean> heater_control = [ s1 | 
        Sycamore_Heater.allMembers.filter[i | i.state == ON].forEach(item | {
            item.sendCommand(OFF)
            logInfo(rule_name,"Forgot to turn off the {}. Turning it OFF ", item.label)
        }) true ]

    // Main Code: -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    switch Day_Activity.state {
        case "WAKEUP": {
          //
        }
        case "GETTING READY": {
            heater_control.apply (OFF)
        }
        case "AT WORK": {
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            outlet_control.apply (OFF)
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            heater_control.apply (OFF) 
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            Sycamore_Lights.allMembers.forEach(item | {
                if( item.state > 0 || item.state == ON) {
                    item.sendCommand(OFF)
                    logInfo(rule_name,"Forgot to turn off the {}. Turning it OFF ", item.label)
                }
            })
        }
        case "AT HOME": {
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            outlet_control.apply (OFF) 
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            heater_control.apply (OFF)
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        }
        case "LUNCH": {
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            outlet_control.apply (ON)
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        }
        case "DINNER": {
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            outlet_control.apply (ON) 
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
        }
        case "IN BED": {
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            outlet_control.apply (OFF)
            }
        }
        case "SLEEPING": {
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            Sycamore_Lights.allMembers.forEach(item | {
                if( item.state > 0 || item.state == ON) {
                    item.sendCommand(OFF)
                    logInfo(rule_name,"Forgot to turn off the {}. Turning it OFF ", item.label)
                }
            })
            // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            outlet_control.apply (OFF)
            }
        }
    }
end

```

In all, I was able to solve my problem, code the logic as I wanted and I have learned many new things today, and it will help me as I keep learning and using openhab in my house.

Thanks!

---

<div class="post-metadata">

**Author:** ![chriscolden](https://community.openhab.org/user_avatar/community.openhab.org/chriscolden/32/71507_2.png) [@chriscolden](https://community.openhab.org/u/chriscolden)\
**Post date:** [August 12, 2019, 7:58am UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/9 "2019-08-12T07:58:45Z")

</div>

> [@rlkoshak](#):
>
> This part is not required. It was for awhile but then I think the upstream Xtend/Xtext libraries fixed something and now we can do it the “nicer” way.

I wasn’t aware of this, thank you. I’ve mostly moved away from lambda now that I’ve migrated to gpstracker and changed the way I handled my mqtt to 433 gateway.

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [August 12, 2019, 6:20pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/10 "2019-08-12T18:20:39Z")

</div>

> [@funky28](#):
>
> I know is always best to show the whole code so help can be more efficient and tailored… I was just trying to get to the point… let’s call it beginner’s experience.

This runs a very high risk of creating the [XY Problem](http://xyproblem.info/). That’s another reason I don’t recommend it. As many of us have indicated, you are trying to solve a specific problem with lambdas but your entire use of lambdas is suspect.

> [@funky28](#):
>
> I have did read lots of threads and posting, and I was aware that Lambdas carried some level of extra difficulty and constrains, but at least i found it to be an elegant and clean solution… at least in my eyes.

Then you might be happier coding in JSR223 Rules. Global lambdas are dangerous, error prone, and a huge code smell and should only be used as a last resort. The perceived elegance is far out weighted by the suppressed error reporting, non-thread safeness, and other limitations.

> [@funky28](#):
>
> definitions and the rule below is a separate rule file on how I execute different commands as the Day Activity changes

Wait, these are not global lambdas? Well, that addresses some of the issues with lambdas because new ones are created with every execution of the Rule, but they are really not needed. A far better approach is [Design Pattern: How to Structure a Rule](https://community.openhab.org/t/design-pattern-how-to-structure-a-rule/45360) to avoid duplicated code.

```php
rule "Thrigger Activites based on DayState changes"
when
    // Time cron "0/30 0/1 * 1/1 * ? *" or // Run every 30 seconds for debugging purposes 
    Item Day_Activity changed
then    

    // 1: always run the Rule

    // 2: calculate what the rule needs to to
    var rule_name = "MyRules.Daystate"

    var heater_control = false
    var outlet_control = false
    var outlet_state = OFF
    var lights_control = false

    switch Day_Activity.state {
// case "WAKEUP": // nothing to do
        case "GETTING READY": heater_control = true // state is already defaulted to OFF
        case "AT WORK": {
            heater_control = true
            outlet_control = true // state is already defaulted to OFF
            light_control = true
        }
        case "AT HOME": {
            outlet_control = true // state is already defaulted to OFF
            heater_control = true
        }
        case "LUNCH",
        case "DINNER": {
            outlet_control = true
            outlet_state = ON
        }
        case "IN BED": outlet_control = true // state is already defaulted to OFF
        case "SLEEPING": {
            light_control = true
            outlet_control = true // state is already defaulted to OFF
        }
    }

    // 3: do it
    // heater
    if(heater_control){
        Sycamore_Heater.allMembers.filter[i | i.state == ON].forEach(item | {
            item.sendCommand(OFF)
            logInfo(rule_name,"Forgot to turn off the {}. Turning it OFF ", item.label)
        })
    }

    // outlet
    if(outlet_control){
        Sycamore_Outlet.allMembers.filter[item | item.state != outlet_state && item.label.toString.contains("Left")].forEach[ item |
            item.sendCommand(outlet_state)
            if ( outlet_state == ON ) { logInfo(rule_name,"We are probably cooking!!! Turning ON the Air Wick on {}.", item.label)}
            if ( outlet_state == OFF ) { logInfo(rule_name,"Turning Off the Air Wick on {}.", item.label)}
        ]
    }

    // lights
    if(light_control){
        Sycamore_Lights.allMembers.forEach(item | {
            if( item.state > 0 || item.state == ON) {
                item.sendCommand(OFF)
                logInfo(rule_name,"Forgot to turn off the {}. Turning it OFF ", item.label)
            }
        })
    }
end

```

The above is fewer lines of code (fewer usually means easier to understand and maintain), fewer levels of context (i.e fewer indentation levels which also means easier to understand and maintain), has no repeated code that modifies state (e.g. sendCommand or postUpdate) which is what I think you were trying to avoid, and it doesn’t introduce the complexity and overhead of using lambdas.

Also notice I streamlined the outlet control by using a filter instead of an if statement inside the forEach.

---

<div class="post-metadata">

**Author:** ![funky28](https://community.openhab.org/user_avatar/community.openhab.org/funky28/32/36103_2.png) [@funky28](https://community.openhab.org/u/funky28)\
**Post date:** [August 13, 2019, 3:34am UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/11 "2019-08-13T03:34:26Z")

</div>

Thanks for taking a stab at my rule, I definetly see the improvement and simplification when applying the 1-2-3 rule structure and I can tell it is easier to maintain and understand the code in the future. I like how some of the conditional statements were added to the Filter, which I tried before but encountered some syntax issues and just settled for a plain and old if-then statement.

I like the simplicity of how you made step #2: calculate what the rule needs to do, it is easy to follow and concise.

I will start using this concept and try to update some of my rules (and new ones) so more than likely I will have more questions to come in later posts.

Many thanks for the help!

---

<div class="post-metadata">

**Author:** ![auzick](https://community.openhab.org/user_avatar/community.openhab.org/auzick/32/44650_2.png) [@auzick](https://community.openhab.org/u/auzick)\
**Post date:** [March 16, 2020, 3:48pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/12 "2020-03-16T15:48:25Z")

</div>

> [@rlkoshak](#):
>
> That is actually an old syntax requirement. What OP did is perfectly acceptable since OH 2.3 (and before OH 2.0). It’s all the other stuff you identified that was causing problems. See [Reusable Functions: A simple lambda example with copious notes](https://community.openhab.org/t/reusable-functions-a-simple-lambda-example-with-copious-notes/15888) for details. The tl;dr is you don’t have to specify the Functions$Function1 with a return type or Procedures$Procedure (no return). The Rules DSL is smart enough to figure out the number and type of the arguments and if the last line returns void it will use Procedures$X and if it returns something it will use Functions$X and the appropriate type for the return value.

I came across this today while trying to fix a related problem, but it raises a question. Consider the following function that my rule uses to decide which “thermostat temperature item” that a rule should target depending on the name of the button clicked in a HabPanel:

```auto
// This function finds the temperature item that corresponds to the control pressed.
val Functions$Function1<GenericItem, NumberItem> GetThermostatTempItem = [buttonItem |
    if (buttonItem.name.toLowerCase.contains("upstairs"))
        return UpstairsThermostatTemperature
    else if (buttonItem.name.toLowerCase.contains("downstairs"))
        return DownstairsThermostatTemperature
    else
        return void
]

```

I’m returning `void` at the end, so that if for some reason I have a misnamed button, the script won’t target a “default” thermostat by accident. But according to what @rlkoshak wrote, I could not use the easier syntax because the last return is a `void`. Can you suggest a way around that?

FWIW, although these scripts were perfectly fine yesterday, today VS Code is throwing a validation error “`Type mismatch: cannot convert from (GenericItem)=>Object to Function1<GenericItem, NumberItem>`”. The detailed error also says “`a registered resource factory is needed`”. Not really understanding these errors, I thought I might give a go at the “easier” syntax if possible.

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [March 16, 2020, 4:31pm UTC](https://community.openhab.org/t/solved-conditional-statement-with-a-lambda-function-variable/79753/13 "2020-03-16T16:31:11Z")

</div>

> [@auzick](#):
>
> I’m returning `void` at the end, so that if for some reason I have a misnamed button, the script won’t target a “default” thermostat by accident. But according to what @rlkoshak wrote, I could not use the easier syntax because the last return is a `void` . Can you suggest a way around that?

I think you can return `null`. You can’t have a function or lambda that returns a value sometimes and void other times. A Functions must return something else and a Procedures can _only_ return void.

An even better approach would be to use a Map though.

```auto
import java.util.Map

val thermostatTempItem = newHashMap("upstairs" -> UpstairsThermostatTemperature,
                                                                    "downstairs" -> DownstairsThermostatTemperature)

...
    val thermostat = thermostatTempItem.get(buttonName)

```

As a general rule, lambdas should only be used as a last resort in Rules DSL. They have so many limitations that in almost all cases there is a better way to achieve the same thing.
