Return Default Value When No Match Found - openedge

I have a function GetQuantity that returns a decimal. In some cases I want to return nothing i.e. and empty string so that ' ' is displayed.
Actual Behavior:
GetQuantity(1) -> 1.0
GetQuantity(2) -> 2.0
GetQuantity(3) -> 3.3
Desired Behavior:
GetQuantity(1) -> 1.0
GetQuantity(2) -> 2.0
GetQuantity(3) -> ' '
In case 3 I can obviously return -1.0 or something but that is not what I need.
FUNCTION GetQuantity RETURNS DECIMAL(INPUT num AS INTEGER):
DEFINE VARIABLE quantity AS DECIMAL NO-UNDO FORMAT "->,>>>,>>9.9<<<<<<<<".
quantity = 3.3. //initialization is neccessary as IRL my value is initialized
IF num = 1 THEN DO:
RETURN 1.0.
END.
ELSE IF num = 2 THEN DO:
RETURN 2.0.
END.
RETURN quantity. //base case return ' '
END.
DISPLAY GetQuantity(3)

One way would be to return ? in case of the default and handle this in your output routine.
As ? is also the result of a failing calculation (div by 0) this might be dangerous.
The alternative would be to write a class with a Value property and a Default flag and an ToString() override.
BLOCK-LEVEL ON ERROR UNDO, THROW.
USING Progress.Lang.*.
CLASS Test.SampleValueHolder:
DEFINE PUBLIC PROPERTY Value AS DECIMAL NO-UNDO
GET.
PRIVATE SET.
DEFINE PUBLIC PROPERTY IsDefault AS LOGICAL NO-UNDO
GET.
PRIVATE SET.
CONSTRUCTOR PUBLIC SampleValueHolder (pdeValue AS DECIMAL,
plDefault AS LOGICAL):
ASSIGN THIS-OBJECT:Value = pdeValue
THIS-OBJECT:IsDefault = plDefault .
END CONSTRUCTOR.
METHOD PUBLIC OVERRIDE CHARACTER ToString ():
IF THIS-OBJECT:IsDefault THEN
RETURN "" .
ELSE
RETURN STRING (THIS-OBJECT:Value, "->,>>>,>>9.9<<<<<<<<") .
END METHOD.
END CLASS.
Now you can either RETURN NEW SampleValueHolder (1.0, FALSE) or RETURN NEW SampleValueHolder (?, TRUE) into a Variable of Type Test.SampleValueHolder.
And whenever you display STRING () of that value, you either get the formatted value or "" when it's the default.

An alternative solution to Mike's above would be to change getQuantity() to return a Character value instead of the decimal it currently does. Although of course this could cause a lot of work fixing all the calling points. I don't know the extent of its use.
Also, if you're in a position where the number of conditions is greater than you've shown, a CASE would be far easier to maintain than lots of IF statements. Something like this:
FUNCTION GetQuantity RETURNS CHARACTER(INPUT num AS INTEGER):
DEFINE VARIABLE quantity AS CHARACTER NO-UNDO INITIAL "3.3".
CASE num:
WHEN 1 THEN quantity = "1.0".
WHEN 2 THEN quantity = "2.0".
OTHERWISE quantity = "".
END CASE.
RETURN STRING(quantity).
END.
DISPLAY GetQuantity(3).

Related

xquery to check if the value is null then return null as string

I am new to XQuery. Please guide me to solve the issue below I want to return the null value as a string, if the below expression does not give any value.
Currently, the output doesn't show the 'name' field itself. I want to have a name with null. for eg-
if (IsNull(expression),null,expression)
$output.dataAccessResponse[1]/*:row/*:name/text()
You could use the fn:exists() function to test whether or not there is a text() node.
exists($output.dataAccessResponse[1]/:row/:name/text())
You could also use the fn:boolean() function to test the effective boolean value of the node.
boolean($output.dataAccessResponse[1]/:row/:name/text())
If you wanted to test whether or not there was a significant value i.e. something other than whitespace, you can fn:normalize-space() in a predicate, to ensure that only text() nodes that have meaningful text are selected, and then test fn:exists().
exists($output.dataAccessResponse[1]/:row/:name/text()[normalize-space()])
XQuery doesn't have null, so if you are asking what to return to indicate null, then you would want to return an empty sequence () instead of null.
So, you could execute something like this:
let $name := $output.dataAccessResponse[1]/:row/:name/text()
return
if (fn:exists($name))
then $name
else ()
But at that point, it's really the same as just attempting to select the text() with that XPath and it will either return the text() node or an empty sequence:
$output.dataAccessResponse[1]/:row/:name/text()

To set operator value Dynamically instead of static value in VB.net

I am doing some calculation using comparison operator in my code (> or <) . Currently I have '>' static written.For Ex.
If Counter_1 > MaxAllow Then
' ......ASP.net code.
Now I want to make it dynamic.So,instead of '>' static value I have one variable which contains operation (> or <) dynamically from database.
Now How can I use this variable so that I can do calculation of variable (> or <)
For Ex .
If Counter_1 [variable] MaxAllow.
Here variable may be > or <.
Note : I am using ASP.Net 2.0 with Language VB.
Immediate help in this concern will be appreciated.
I don't believe you can do exactly what you want.
You could do it with a function like this:
Public Function GreaterThanLessThan(value1 As Integer, value2 As Integer, aOperator As Char) As Boolean
If aOperator <> ">"c AndAlso aOperator <> "<"c Then
'If we get here then the operator character wasn't > or <
Throw New Exception("Invalid operator")
Return False
Else
Return If(aOperator = ">"c, (value1 > value2), (value1 < value2))
End If
End Function
Usage:
If GreaterThanLessThan(Counter_1, Maxllow, ">"c) Then
End If
This code would probably benefit from being an extenstion Method (with a shorter name):
<Extension()>
Public Function GtLt(value1 As Integer, value2 As Integer, aOperator As Char) As Boolean
...etc
So that you could then do this:
If Counter_1.GtLt(MaxAllow,">"c) Then

Ada String Concatenation

I have a function that returns a string for a particular item, and I need to call that function numerous times and combine those strings into one. The combined string is bounded. I've made sure to fill it when space characters when it initializes but I keep getting "length check failed" errors. Is there something basic I'm doing wrong here?
FOR I IN 1..Collection.Size LOOP
Combined_String := combined_string & Tostring(Collection.Book(I));
END LOOP;
Unbounded_String is probably the easiest way to go:
with Ada.Strings.Unbounded;
use Ada.Strings.unbounded;
...
Temp_Unbounded_String : Unbounded_String; -- Is empty by default.
...
for I in 1 .. Collection.Size loop
Append(Temp_Unbounded_String, ToString(Collection.Book(I));
end loop;
If you then need to have the result placed in your fixed length standard string:
declare
Temp_String : constant String := To_String(Temp_Unbounded_String);
begin
-- Beware! If the length of the Temp_String is greater than that of the
-- fixed-length string, a Constraint_Error will be raised. Some verification
-- of source and target string lengths must be performed!
Combined_String(Temp_String'Range) := Temp_String;
end;
Alternatively, you can use the Ada.Strings.Fixed Move() procedure to bring the Unbounded_String into the target fixed-length string:
Ada.Strings.Fixed.Move(To_String(Temp_Unbounded_String), Combined_String);
In this case, if the source string is "too long", by default a Length_Error exception is raised. There are other parameters to Move() that can modify the behavior in that situation, see the provided link on Move for more detail.
In order to assign Combined_String, you must assign the full correct length at once. You can't "build up" a string and assign it that way in Ada.
Without seeing the rest of your code, I think Ada.Strings.Unbounded is probably what you should be using.
I know this is an ancient question, but now that Ada 2012 is out I thought I'd share an idiom I've been finding myself using...
declare
function Concatenate(i: Collection'index)
is
(tostring(Collection(i) &
if (i = Collection'last) then
("")
else
(Concatenate(i+1))
);
s: string := Concatenate(Collection'first);
begin
Put_Line(s);
end;
Typed off the top of my head, so it'll be full of typos; and if you want it to work on empty collections you'll need to tweak the logic (should be obvious).
Ada 2012's expression functions are awesome!
Ada works best when you can use perfectly-sized arrays and strings. This works wonderfully for 99% of string uses, but causes problems any time you need to progressively build a string from something else.
Given that, I'd really like to know why you need that combined string.
If you really need it like that, there are two good ways I know of to do it. The first is to use "unbounded" (dynamically-sized) strings from Ada.Strings.Unbounded, as Dave and Marc C suggested.
The other is to use a bit of functional programming (in this case, recursion) to create your fixed string. Eg:
function Combined_String (String_Collection : in String_Collection_Type) return String is
begin
if String_Collection'length = 1 then
return String_Collection(String_Collection'first);
end if;
return String_Collection(String_Collection'first) &
Combined_String (String_Collection'first + 1 .. String_Collection'last);
end Combined_String;
I don't know what type you used for Collection, so I'm making some guesses. In particular, I'm assuming its an unconstrained array of fixed strings. If it's not, you will need to replace some of the above code with whatever your container uses to return its bounds, access elements, and perform slicing.
From AdaPower.com:
function Next_Line(File : in Ada.Text_IO.File_Type :=
Ada.Text_Io.Standard_Input) return String is
Answer : String(1..256);
Last : Natural;
begin
Ada.Text_IO.Get_Line(File => File,
Item => Answer,
Last => Last);
if Last = Answer'Last then
return Answer & Next_Line(File);
else
return Answer(1..Last);
end if;
end Next_Line;
As you can see, this method builds a string (using Get_Line) of unlimited* length from the file it's reading from. So what you'll need to do, in order to keep what you have is something on the order of:
function Combined_String (String_Collection : in String_Collection_Type)
Return String is
begin
if String_Collection'length = 1 then
Return String_Collection(String_Collection'First).All;
end if;
Recursion:
Declare
Data : String:= String_Collection(String_Collection'First).All;
SubType Constraint is Positive Range
Positive'Succ(String_Collection'First)..String_Collection'Last;
Begin
Return Data & Combined_String( String_Collection(Constraint'Range) );
End Recursion;
end Combined_String;
Assuming that String_Collection is defined as:
Type String_Collection is Array (Positive Range <>) of Access String;
*Actually limited by Integer'Range, IIRC

ASP.NET (VB) Extension Method not working as expected

I have the following Extension Method
Imports System.Runtime.CompilerServices
Namespace Extensions
Public Module IntegerExtensions
<Extension()>
Public Function ToCommaDeliminatedNumber(ByVal int As Integer) As String
Dim _input As String = int.ToString
Select Case int
Case Is > 99999 : Return _input.Remove(_input.Length - 3) & "k"
Case Is > 9999 : Return Math.Round(Double.Parse(int / 1000), 1).ToString & "k"
Case Is > 999 : Return String.Format("{0:N0}", int)
Case Else : Return _input
End Select
End Function
End Module
End Namespace
And in one of my classes I'm using
user.Reputation.ToCommaDeliminatedNumber
I am importing the Extensions Namespace into the Class, but the error I'm getting is...
'ToCommaDeliminatedNumber' is not a member of 'Integer?'.
Can anybody tell me what I might be missing here? I do have other Extension Methods for Strings and Dates that work exactly as expected... I'm just at a loss on this one.
Judging from your error message it looks like user.Reputation is actually a Nullable(Of Integer), based on the trailing question mark ('Integer?'). Is that correct?
Your extension method is extending Integer, not Integer? (i.e., Nullable(Of Integer)), hence the error. So either provide an overload that handles Integer? or call Value on the nullable type:
user.Reputation.Value.ToCommaDeliminatedNumber()
You will need to check that it is not null (Nothing) otherwise an exception will be thrown. An overloaded method might look like this:
<Extension()>
Public Function ToCommaDeliminatedNumber(ByVal int As Integer?) As String
Return int.GetValueOrDefault().ToCommaDeliminatedNumber()
End Function
In the case that it's null the default value of 0 would be displayed.

Simplest way to check if a string converted to a number is actually a number in actionscript

Not sure if this makes sense, but I need to check if a server value returned is actually a number. Right now I get ALL number values returned as strings
ie '7' instead of 7.
What's the simplest way to check if string values can actually be converted to numbers?
The easiest way to do this is to actually convert the string to a Number and test to see if it's NaN. If you look at the Flex API reference, the top-level Number() function says it will return NaN if the string passed to the method cannot be converted to a Number.
Fortunately, Flex (sort of) does this for you, with the isNaN() function. All you need to do is:
var testFlag:Boolean = isNaN( someStringThatMightBeANumber );
If testFlag is false, the string can be converted to a number, otherwise it can't be converted.
Edit
The above will not work if compiling in strict mode. Instead, you will need to first convert to Number and then check for NaN, as follows:
var testFlag:Boolean = isNaN( Number( someStringThatMightBeANumber ) );
Haven't tested this, but this should work:
if( isNaN(theString) ) {
trace("it is a string");
} else {
trace("it is a number");
}
If you are using AS3 and/or strict mode (as pointed out by back2dos), you will need to convert to number first in order for it to compile:
if( isNaN(Number(theString)) ) {
trace("it is a string");
} else {
trace("it is a number");
}
Most of the answers on this question have a major flaw in them. If you take Number(null) or Number(undefined) or Number(""), all will return 0 and will evaluate to "is a number". Try something like this instead:
function isANumber( val:* ):Boolean {
return !(val === null || val === "" || isNaN(val));
}
RegExp path :
function stringIsAValidNumber(s: String) : Boolean {
return Boolean(s.match(/^[0-9]+.?[0-9]+$/));
}
Here is another way to check if value can be converted to a number:
var ob:Object = {a:'2',b:3,c:'string'};
for( var v:* in ob){
var nr:Number = ob[v];
trace(ob[v]+" "+(nr === Number(nr)))
}
this will trace following:
2 true
3 true
string false
You can notice that in actionscript :
trace(int('7')); // will return 7
and
trace(int('a')); // will return 0
So except for zeros, you can actually now if a string is a number or not
this will try to convert your String to a Number, which essentially is a 64 bit floating point number:
var val:Number = Number(sourceString);
if sourceString is not a valid String representation of a Number, val will be NaN (not a number) ... you have check against that value with isNaN ... because val == NaN will return false for a reason that can't quite understand ... you can use int(val) == val to check, whether it is an integral value ...
greetz
back2dos
Put this into any function where you want only numbers to stayjoy_edit1 is a TextInput Object (spark)
//is a number check
if( isNaN(Number(joy_edit1.text)) ) {
joy_edit1.text = "";
return void;
}
function isANumber(__str:String):Boolean
{
return !isNaN(Number(__str));
}
You should use the native solution of Adobe:
parseInt and parseFloat methods.
Also read the isNaN description:
Returns true if the value is NaN(not a number). The isNaN() function
is useful for checking whether a mathematical expression evaluates
successfully to a number. The most common use of isNaN() is to check
the value returned from the parseInt() and parseFloat() functions. The
NaN value is a special member of the Number data type that represents
a value that is "not a number."
Here is a simple implementation:
function isANumber(value:String):Boolean {
return !isNaN(parseFloat(value));
}
typeof('7') == 'string'
typeof(7) == 'number'
Does that help?

Resources