Lambda into another lambda

If I try to execute a lambda into another lambda, when I do the Apply, it throw an IllegalStateException.
I try creating the lambda into the lambda and also to pass the lambda as a parameter into the first lamda, always the same error.
Any idea how to do it?

Could not invoke method: org.eclipse.xtext.xbase.lib.Procedures$Procedure3.apply(P1,P2,P3) on instance: Proxy for org.eclipse.xtext.xbase.lib.Functions$Function3: org.eclipse.xtext.xbase.impl.XClosureImplCustom@ce6f71 (explicitSyntax: true)

I know it is possible as I’ve done it, usually by passing the lambda as a parameter. Post your code so we can see if there is a syntax error or something like that.

I have a lambda “SendNotification” passed as parameter, the call to this lambda are in comment now because it doesn’t work.

// notification to push bullet, email and optionnally to imperihome 
var org.eclipse.xtext.xbase.lib.Procedures$Procedure3<String, String, boolean> sendNotification = [
	String title,
	String subject,
	boolean isVocal |

logDebug("sendNotification", title)

// send to pushbullet
executeCommandLine("curl@@-k@@-H@@Access-Token: xxx@@-XPOST@@https://api.pushbullet.com/v2/pushes@@-H@@Content-Type: application/json@@--data-binary@@{\"type\": \"note\", \"title\": \"" + title + "\", \"body\": \"" + subject + "\"}@@")

// send email
sendMail("xxxxx@gmail.com", title, subject)

// send text to speech to imperihome
if(isVocal){
	imperiHabSay(subject) 
	}
]



 var org.eclipse.xtext.xbase.lib.Functions$Function5 runningMachineAlert = [
	org.openhab.core.library.items.NumberItem machineItem,
	java.util.Map<String, org.openhab.model.script.actions.Timer> checkRunningMachineTimers,
	java.util.Map<String, int> checkRunningMachineIsSleepings,
	java.util.Map<String, org.eclipse.xtext.xbase.lib.Procedures$Procedure1<Object>> runningMachineFuncs,
	org.eclipse.xtext.xbase.lib.Procedures$Procedure3<String, String, boolean> sendNotification |
	
	
	if(runningMachineFuncs.get(machineItem.name) == null){
		var org.eclipse.xtext.xbase.lib.Procedures$Procedure1<Object> machineFuncGlobal = [ Object machineFunc |
			var org.eclipse.xtext.xbase.lib.Procedures$Procedure1 updateState = [
				String message | 
				if(machineItem.name == "Conso_WashingMachine"){
					postUpdate(WashingState, message)
				} else {
					if(machineItem.name == "Conso_Backup"){
						postUpdate(DryerState, message)
					}
				}
			]
						
			if(machineItem.state < 10){
				logDebug("Machine Alert", "Washing machine is consumming low...")
				if(checkRunningMachineIsSleepings.get(machineItem.name) < 60){
					// check 60 so it 10 min to receive 2 updates from server
					//updateState.apply("Consomme peu...")
					if(machineItem.name == "Conso_WashingMachine"){
						postUpdate(WashingState, "Consomme peu...")
					} else {
						if(machineItem.name == "Conso_Backup"){
							postUpdate(DryerState, "Consomme peu...")
						}
					}
					logDebug("Machine Alert", "Check low consumption is " + checkRunningMachineIsSleepings.get(machineItem.name))
					checkRunningMachineIsSleepings.put(machineItem.name, checkRunningMachineIsSleepings.get(machineItem.name) + 1)
					checkRunningMachineTimers.put(machineItem.name, createTimerWithArgument(now.plusSeconds(10), machineFunc, machineFunc as org.eclipse.xtext.xbase.lib.Procedures$Procedure1<Object>))
				}
				else {
					logDebug("Washing Machine Alert", "Washing machine is finished")
					checkRunningMachineIsSleepings.put(machineItem.name, 0);
					
					if(checkRunningMachineTimers.get(machineItem.name) !=null){
						checkRunningMachineTimers.get(machineItem.name).cancel();
						checkRunningMachineTimers.remove(machineItem.name);
					}
					//updateState.apply("Fini, vider la machine")
					if(machineItem.name == "Conso_WashingMachine"){
						postUpdate(WashingState, "Fini, vider la machine")
					} else {
						if(machineItem.name == "Conso_Backup"){
							postUpdate(DryerState, "Fini, vider la machine")
						}
					}
					
					if(machineItem.name == "Conso_WashingMachine"){
						// send to pushbullet
						executeCommandLine("curl@@-k@@-H@@Access-Token: cz8nT4eoI4Eb4MWlSslsjcpK7yav4ySu@@-XPOST@@https://api.pushbullet.com/v2/pushes@@-H@@Content-Type: application/json@@--data-binary@@{\"type\": \"note\", \"title\": \"" + "Openhab" + "\", \"body\": \"" + "La machine à laver à fini" + "\"}@@")
						imperiHabSay("La machine à laver à fini") 
						//sendNotification.apply("La machine a laver a fini", "", true)
					} else {
						if(machineItem.name == "Conso_Backup"){
							// send to pushbullet
							executeCommandLine("curl@@-k@@-H@@Access-Token: cz8nT4eoI4Eb4MWlSslsjcpK7yav4ySu@@-XPOST@@https://api.pushbullet.com/v2/pushes@@-H@@Content-Type: application/json@@--data-binary@@{\"type\": \"note\", \"title\": \"" + "Openhab" + "\", \"body\": \"" + "Le sèche linge à fini" + "\"}@@")
							imperiHabSay("Le sèche linge à fini") 
							//sendNotification.apply("Le seche linge a fini", "", true)
						} else {
							//sendNotification.apply("Une machine a fini de tourner", "", true)
						}
					}
				}
			}
			else {
				logDebug("Machine Alert", "Machine is running...")
				//updateState.apply("Tourne")
				if(machineItem.name == "Conso_WashingMachine"){
					postUpdate(WashingState, "Tourne")
				} else {
					if(machineItem.name == "Conso_Backup"){
						postUpdate(DryerState, "Tourne")
					}
				}
				
				checkRunningMachineIsSleepings.put(machineItem.name, 0)
				checkRunningMachineTimers.put(machineItem.name, createTimerWithArgument(now.plusSeconds(10), machineFunc, machineFunc as org.eclipse.xtext.xbase.lib.Procedures$Procedure1<Object>))
			}  
        ]
		
		runningMachineFuncs.put(machineItem.name, machineFuncGlobal)
	}
	
	if(machineItem.state > 10 && checkRunningMachineTimers.get(machineItem.name) == null){
		logDebug("Machine Alert", "Machine starting detected")
		imperiHabSay("La machine à laver ou le sèche linge à commencé") 
		// machine is consumming and timer is not started so machine is just starting
		checkRunningMachineIsSleepings.put(machineItem.name, 0)
		var timerMachine = createTimerWithArgument(now.plusSeconds(10),runningMachineFuncs.get(machineItem.name), runningMachineFuncs.get(machineItem.name))
		checkRunningMachineTimers.put(machineItem.name, timerMachine)
		//postUpdate(WashingState, "Tourne") 
	} 
]

Right off the bat I notice you are using Procedures$Procedure3. I’ve not see that syntax used in openHAB rules before (and apparently missed that from your original posting). Keep in mind that openHAB rules are a DSL based on Xbase so while it shares a whole lot in common with Xtend, there are notable differences. Perhaps the rules DSL doesn’t support Procedures.

Try converting sendNotification to a Functions$Function3 and see if that makes any difference.

1 Like

Ok, with Function it works, but is there any documentation with what is supported from the Xtend language?
Other question, if I pass a Function1 to createTimerWithArgument with the openhab designer, it says that it must be a Procedure1, normal?
Thanks.

Unfortunately none that I’ve been able to find. I’ve mainly learned what does and doesn’t work through the examples, experimentation, and deduction.

I’ve never tried to pass a Function or Procedure to createTimerWithArgument. I’ve always see it with the lambda defined right there (e.g. [ arg | code]) and I’ve only personally used createTimer. I honestly don’t know the difference between a Function and a Procedure inside the language so I don’t really have any idea nor do I really know what createTimerWithArgument gives you.

I’ve see createTimerWithArgument in examples but it is not documented in the wiki.