UBBFriend: Email This Page to Someone!
  uCalc Message Forums
  Code Exchange
  Enhanced IIF function

Post New Topic  Post A Reply
profile | register | preferences | faq | search

next newest topic | next oldest topic
Author Topic:   Enhanced IIF function
Daniel Corbier
Administrator
posted 12-03-2001 12:09 AM     Click Here to See the Profile for Daniel Corbier     Edit/Delete Message Reply w/Quote
Some have inquired about the built-in IIF function.
If you have the following: IIF(Expression, TruePart, FalsePart),
then in the current version of the parser (v 2.0), both TruePart and
FalsePart are evaluated, even if only one of the two results is
returned. This works the same way as in Visual Basic. However,
this has been an issue for a number of UCalc users.

For instance, let's say you have: IIF(x=5, 2/x, x+6). If "x=5"
is true then you get 2/5, and all is fine. If it's false, you get
the value of x+6 as the result. However, if x happens to equal 0,
then even if the 2/x argument does not contribute towards the result,
it is still evaluated. In this case the unneeded argument gets in
the way, and causes a division by 0 error, instead of returning
the result from the relevant argument.

At first glance, it would appear as though you could work around
this using a simple callback function that would only evaluate
the first argument. However, because of a limitation in
the design of the current version, even using a callback, if done
in a straight-forward manner, both arguments would still end up
being evaluated anyway. This limitation has been removed in the
beta for the next version, and an updated IIF function is also
provided in the beta. However, if you need a work-around before
the next official version is released (there is no estimated
release date yet), then use the following IIF replacement:


In the Visual Basic Form_Load area add this code:

code:

ucPreParse "IIF", AddressOf PreParseIIF
ucDefineFunction "EvalIf(Expr, CalcIndex)", AddressOf EvalIf
ucDefineFunction "IsTrue(CalcIndex)", AddressOf ucIsTrue
ucDefineFunction "IsFalse(CalcIndex)", AddressOf ucIsFalse

In a separate module paste in this code:

code:

Const CalcDepth = 512
Dim CalcIndex As Long
Dim TrueOrFalse(CalcDepth) As Long
Dim TrueBranch$(CalcDepth)
Dim FalseBranch$(CalcDepth)


Function PreParseIIF() As Long
CalcIndex = CalcIndex + 1
TrueBranch$(CalcIndex) = ucParamStr(2)
FalseBranch$(CalcIndex) = ucParamStr(3)


ucParamStr(1) = "EvalIf(" + ucParamStr(1) + "," + Format$(CalcIndex) + ")"
ucParamStr(2) = "IsTrue(" + Format$(CalcIndex) + ")"
ucParamStr(3) = "IsFalse(" + Format$(CalcIndex) + ")"
End Function


Function EvalIf() As Double
If ucParam(1) <> 0 Then TrueOrFalse(ucParam(2)) = True _
Else TrueOrFalse(ucParam(2)) = False
EvalIf = ucParam(1)
End Function


Function ucIsTrue() As Double
If TrueOrFalse(ucParam(1)) = True Then ucIsTrue = iEval(TrueBranch$(ucParam(1)))
If ucError Then ucSetError = ucError
End Function


Function ucIsFalse() As Double
If TrueOrFalse(ucParam(1)) = False Then ucIsFalse = iEval(FalseBranch$(ucParam(1)))
If ucError Then ucSetError = ucError
End Function


Function iEval(Expression$) As Double
Dim ExpressionPtr As Long


ExpressionPtr = ucParse(Expression$)
iEval = ucEvaluate(ExpressionPtr)
ucReleaseExpr
End Function

' --- End of code


IMPORTANT: Do not use the built-in ucEval function inside
the callback routine in this context. Instead, in this
code a new function named iEval was created. It explicitely
calls ucParse, ucEvaluate, and ucReleaseExpr, in that
order, whereas the built-in ucEval calls ucReleaseExpr
before ucEvaluate, making ucEval inadequate in inside
callback routines.


NOTE: This is not a perfect solution. The CalcIndex variable is
incremented each time an expression with IIF is parsed. CalcIndex
is what allows IIF statements to be nested. However, once it reaches
the maximum value of CalcDepth, then there's a problem. If you will
not be using nested IIF functions, you can remove CalcIndex. Otherwise
you may create wrapper functions for ucParse, and ucReleaseExpr and
have the ucParse wrapper store the value of CalcIndex before calling
the DLL's ucParse, and have the ucReleaseExpr function restore CalcIndex
to its previous state using a temporary variable.

This is a temporary solution until the next version is released. Callback
functions were not intended to make recursive calls to the parser in this
way, so there may be an unforeseen context where it might not work as expected.
You will need to experiment with this code to see if it works well for you.

IP: Logged

All times are Eastern Time (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | uCalc

Copyright © 2000-2007 by Daniel Corbier

Powered by: Ultimate Bulletin Board, Version 5.42a
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 1999.