If you are coming from the realm of C# 3.0 then lamda expressions should be pretty familiar to you as it's basic syntactic sugar for creating a function with a conditional return. Since functions in AutoIt are first class objects, the following code should make some sense. It passes an array of integers to a function called IsTrueForAll() that checks whether the function object matches the return condition of that function (you passed). So for example a function called IsGreaterThanOrEqualTo10() checks if all values are greater than or equal to 10 (TRUE). Similarly, IsLessThan10() checks if all values are less than 10 (FALSE). This example should be nothing new to those of you who use v3.3.10.0+ and have an understanding of Call(). #include <MsgBoxConstants.au3>
Local $aArray[] = [10, 100, 99, 67]
If IsTrueForAll($aArray, IsGreaterThanOrEqualTo10) Then
MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')
Else
MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')
EndIf
If IsTrueForAll($aArray, IsLessThan10) Then
MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')
Else
MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')
EndIf
Func IsTrueForAll($aArray, $hFunc) ; Loop through the array and check the function passed with a single param matches the condition.
For $i = 0 To UBound($aArray) - 1
If Not $hFunc($aArray[$i]) Then
Return False
EndIf
Next
Return True
EndFunc ;==>IsTrueForAll
Func IsGreaterThanOrEqualTo10($x)
Return $x >= 10
EndFunc ;==>IsGreaterThanOrEqualTo10
Func IsLessThan10($x)
Return $x < 10
EndFunc ;==>IsLessThan10
But, we could easily just forget about writing the functions (less typing is always nice) and let the compiler or pre-processor do all the work for us. It would simply use the lambda expression and create the function for us with whatever we specified. Like so... #include <MsgBoxConstants.au3>
Local $aArray[] = [10, 100, 99, 67]
If IsTrueForAll($aArray, $x => $x >= 10) Then ; $x is the parameter, => tells us it's a lambda expression and then the condition we are checking.
MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')
Else
MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')
EndIf
If IsTrueForAll($aArray, $x => $x < 10) Then ; $x is the parameter, => tells us it's a lambda expression and then the condition we are checking.
MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')
Else
MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')
EndIf
Func IsTrueForAll($aArray, $hFunc) ; Loop through the array and check the function passed with a single param matches the condition.
For $i = 0 To UBound($aArray) - 1
If Not $hFunc($aArray[$i]) Then
Return False
EndIf
Next
Return True
EndFunc ;==>IsTrueForAll...which would create the following code with anonymous functions (they're anonymous as we don't care about them in our main script)... #include <MsgBoxConstants.au3>
Local $aArray[] = [10, 100, 99, 67]
If IsTrueForAll($aArray, D3F7B1B92177415CA70C7FFC35C2649C) Then
MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')
Else
MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')
EndIf
If IsTrueForAll($aArray, DA06B548ABF4045AA32F805E6651004) Then
MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')
Else
MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')
EndIf
Func IsTrueForAll($aArray, $hFunc)
For $i = 0 To UBound($aArray) - 1
If Not $hFunc($aArray[$i]) Then
Return False
EndIf
Next
Return True
EndFunc ;==>IsTrueForAll
Func D3F7B1B92177415CA70C7FFC35C2649C($x)
Return $x >= 10
EndFunc ;==>D3F7B1B92177415CA70C7FFC35C2649C
Func DA06B548ABF4045AA32F805E6651004($x)
Return $x < 10
EndFunc ;==>DA06B548ABF4045AA32F805E6651004
Example of parsing a lambda expression and replacing in the chosen script: #include <WinAPICom.au3>
; Script read from a file.
Local $sScript = "#include <MsgBoxConstants.au3>" & @CRLF
$sScript &= "" & @CRLF
$sScript &= "Local $aArray[] = [10, 100, 99, 67]" & @CRLF
$sScript &= "If IsTrueForAll($aArray, $x => $x >= 10) Then" & @CRLF ; Lambda expression.
$sScript &= " MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')" & @CRLF
$sScript &= "Else" & @CRLF
$sScript &= " MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')" & @CRLF
$sScript &= "EndIf" & @CRLF
$sScript &= "" & @CRLF
$sScript &= "If IsTrueForAll($aArray, $x => $x < 10) Then" & @CRLF ; Lambda expression.
$sScript &= " MsgBox($MB_SYSTEMMODAL, '', 'Condition was True.')" & @CRLF
$sScript &= "Else" & @CRLF
$sScript &= " MsgBox($MB_SYSTEMMODAL, '', 'Condition was False')" & @CRLF
$sScript &= "EndIf" & @CRLF
$sScript &= "" & @CRLF
$sScript &= "Func IsTrueForAll($aArray, $hFunc) ; Loop through the array and check the function passed with a single param matches the condition." & @CRLF
$sScript &= " For $i = 0 To UBound($aArray) - 1" & @CRLF
$sScript &= " If Not $hFunc($aArray[$i]) Then" & @CRLF
$sScript &= " Return False" & @CRLF
$sScript &= " EndIf" & @CRLF
$sScript &= " Next" & @CRLF
$sScript &= " Return True" & @CRLF
$sScript &= "EndFunc ;==>IsTrueForAll" & @CRLF
ReplaceLambdaInScript($sScript, '$x => $x >= 10') ; Parse the lambda expression and replace it in the above script.
ReplaceLambdaInScript($sScript, '$x => $x < 10') ; Parse the lambda expression and replace it in the above script.
ConsoleWrite($sScript & @CRLF) ; This is the new script with the lamda expression convert to an anonymous method!
ClipPut($sScript)
Func CreateLambdaMethod($sExpression) ; Currently no error checking of whether parameters match.
Local $bIsReturn = False, _ ; Is the return condition.
$sFunction = StringRegExpReplace(_WinAPI_CreateGUID(), '[}{-]', ''), $sParam = '', $sReturn = ''
$sFunction = StringRegExpReplace($sFunction, '^\d+', '') ; Remove digits at the beginning of the function name.
For $i = 1 To StringLen($sExpression)
$sChr = StringMid($sExpression, $i, 1)
If $bIsReturn Then
$sReturn &= $sChr
ElseIf $sChr & StringMid($sExpression, $i + 1, 1) == '=>' Then ; Check for =>
$i += 1
$bIsReturn = True
ElseIf Not $bIsReturn Then
$sParam &= $sChr
EndIf
Next
If Not $bIsReturn Then Return "" ; Something went wrong as the => was not found.
$sParam = '(' & StringRegExpReplace($sParam, '^\h*|\h*$', '') & ')'
$sReturn = @TAB & 'Return ' & $sReturn
Return 'Func ' & $sFunction & $sParam & @CRLF & $sReturn & @CRLF & 'EndFunc ;==>' & $sFunction & @CRLF
EndFunc ;==>CreateLambdaMethod
Func ReplaceLambdaInScript(ByRef $sScript, $sLambda)
Local $sFunction = CreateLambdaMethod($sLambda)
Local $sFunctionName = StringRegExp($sFunction, 'Func (\w*)\(', 3)
If @error Then Return False
$sFunctionName = $sFunctionName[0]
$sScript = StringReplace($sScript, $sLambda, $sFunctionName, 1)
$sScript &= @CRLF & $sFunction
Return True
EndFunc ;==>ReplaceLambdaInScriptIt was a simple idea I had this morning whilst having breakfast.