How to use ABAP boolean in IF condition? - abap

I know abap has no real boolean type. Instead 'X' and ' ' is used. Up to this time I always used an if-statement that way:
IF myObj->is_sth( ) = abap_true.
ENDIF.
Now I did something like this:
IF myObj->is_sth( ).
ENDIF.
And I'm wondering that this seems to work. Return Type is boolean. I'm on Netweaver 7.4. Can I use this without problems? It's like my lovely C# writing :p.

This is called a predicative method call:
A predicative method call is a relational expression whose only
operand is a functional method call meth( ... ). The result of the
relational expression is true if the result of the functional method
call is not initial and false if the result of the functional method
call is initial. The result of the functional method call (the return
value of the called function method) can have any data type. A check
is made on the type-friendly initial value.
A predicative method call, like any relational expression, can be a
full logical expression or part of a logical expression. This means it
can be specified as a condition in control statements and other
statements, as an argument in Boolean functions or conditional
expressions, or in joins with Boolean operators.
This was introduced in 7.40 SP08. Be aware that this only works reliably if the initial value is false and false is the initial value. For instance, IS-H uses a character field where 0 is false and 1 is true - but since the initial value of a character field is a space, that's neither true nor false, so using any method that returns this value will always branch as if the method had returned true...

Related

What are the truthy and falsy values in Raku?

While it is always possible to use mixins or method overrides to modify the Bool coercions, by default what values are considered to be truthy and what values are considered to be falsy?
Note: this question was asked previously, but unfortunately it is so old its content is completely out of date and useless is modern Raku.
There are no truthy values, as each type decides for itself via a .Bool method that is called in boolean contexts. For built-in types, the following return False when their .Bool method is called.
0 (except Rat of x/0 where x≠0)
Empty list/collection types (List, Array, Hash, Map, Set, Bag, etc)
Empty string
Failure
Promise prior to being kept/broken.
StrDistance whose before/after is the same.
Junction, when you expect it to.
Type objects
Nil (technically type object)
Any undefined value (technically type objects)
Otherwise, any defined value by default returns True when its .Bool method is called. This includes the Str '0', NaN, and zero-length range (0^..^0) that in other languages might not be truthy.
This answer is intended as a quick reference. See this answer for a more detailed discussion.
TL;DR This answer is an exhaustive summary based on the relevant doc.1
The base case2 is True for a defined object (an instance) and False for an undefined one (a type object).
Numerically 0 values or 0/0 are False. (But a Rational with a non-zero numerator eg 1/0 is True and (0/0).Num (which evaluates to NaN) is True.)
An empty collection (List, Hash, Set, Buf, etc) is False.
An empty string (eg literal "") is False. (NB. "0", "0.0" etc. are True.)
A defined Failure is False.
A defined Promise is False until its status becomes Kept/Broken.
A defined StrDistance is False if the string transformation it represents had no effect on the string being transformed.
A defined Junction is True or False depending on the junction's type and the True/False values of its elements.
Footnotes
1 I wrote the first bullet item based on just knowing it to be true because it's fundamental to P6 and also confirming it by checking the compiler's code.2 The other bullet points summarize the content at the time of writing this answer of the .Bool doc page at which point it listed 20 types. If the latter page was incomplete then this answer is incomplete.
2 The base case can be seen by looking at the Rakudo implementation code, in particular the core's Mu.pm6. See my answer to a similarish SO for relevant code links.

Single-line method calls with untyped parameters

Can I define an ABAP method where the RETURNING parameter and any IMPORTING parameters have a generic type but that can still be called in a single line as a functional method?
In other words I'd like to replace this:
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_external_value
IMPORTING
output = lv_internal_value.
With:
lv_internal_value= zcl_conversion=>alpha_input( lv_external_value ).
Unfortunately the fact that Class Methods can't have an untyped returning parameter is preventing me from declaring the functional method's return value as type ANY or CLIKE. The accepted standard of creating generic method parameters seems to be to define them as TYPE REF TO DATA and dereference/assign them. But as far as I know that prevents me from calling the method in a single statement as I have to first assign the importing parameter and then dereference the returning parameter, resulting in the same or more lines of code than a simple FM call.
Is there a way around this?
Unfortunately, there is no other way to dereference data than to use the dereference operator, either in the form ->* for the full value segment, or in the form ->comp, if the data object is structured and has a component named comp (and, even worse, there are a lot of places in ABAP code where you would like to use a value from a derefenced data object but can't do it for internal reasons / syntax restrictions).
However, you could simply keep the data reference object retrieved by your method in a variable of the calling code and work with that variable (instead of using a field symbol or a variable for the derefenced value segment itself). Either generically, as a ref to data variable, or typed, using the CAST operator (new ABAP syntax).
Most things that can be done with a field-symbol, can also be done directly with a data reference as well.
Example: Working with a variable result of the expected return type:
data(result) = cast t000( cl=>m( ) ).
write result->mandt.
See here the full example:
report zz_new_syntax.
class cl definition.
public section.
class-methods m returning value(s) type ref to data.
endclass.
start-of-selection.
data(result) = cast t000( cl=>m( ) ).
write: / result->mandt. " Writes '123'.
class cl implementation.
method m.
s = new t000( mandt = '123' ).
endmethod.
endclass.
On ABAP NW Stack 7.4 you could just use parameters type STRING and then use the new CONV Operator to convert your actual input in string. Little ugly but should work.
lv_internal_value = CONV #(zcl_conversion=>alpha_input( CONV #(lv_external_value) )).

Why is the syntax for a worksheet IF() function with optional parameters different from UDF?

Never really deeply thought about this but why does an =IF() function require you to pass commas even though the last 2 parameters are Optional?
=IF(logical_test, [value_if_true], [value_if_false])
Why can't we just call it
=IF(TRUE)
to get TRUE (default return value when logical_test evaluated to TRUE)
we have to call it providing the two commas in between even when leaving the parameters missing/empty...
=IF(TRUE, ,)
In a UDF when using Optional Parameters we will not need to pass the commas (much simpler version of the original IF, error handling not implemented as not needed here)
Public Function MYIF(logical_test, Optional value_if_true$ = "TRUE", Optional value_if_false$ = "FALSE")
MYIF = IIf(Evaluate(logical_test), value_if_true, value_if_false)
End Function
and when calling from a spreadsheet we can omit the commas
=MYIF(TRUE)
Anyone, besides Spolsky ;), is aware of the reason why do we need to provide commas when using the native =IF()?
I am in Excel 2010 but just have noticed that 2007 requires 2 parameters.. Still, in 2010 the function definition shows 1st as required, last 2 optional. Any explanation?
Update:
I am aware of the =1=1 and =AND(TRUE,FALSE) syntax, I am not looking for an alternative to a short-hand version of the =IF(). Instead what I am asking is
why do the commas need to be provided with the original =IF() since the last 2 parameters are Optional Parameters?
"Optional argument" can apparently have two distinct meanings for Excel functions:
the optional argument may be omitted;
the value of the optional argument may be omitted.
Sometimes both are allowed, sometimes only #2 is allowed.
Look at the documentation for IF:
IF(logical_test, [value_if_true], [value_if_false])
[...]
value_if_false Optional. [...]
If logical_test evaluates to FALSE and the value_if_false argument is omitted [...], the IF function returns the logical value FALSE.
If logical_test evaluates to FALSE and the value of the value_if_false argument is omitted [...], the IF function returns the value 0 (zero).
Okay, both are allowed. So =IF(FALSE,) (argument omitted) returns FALSE, while =IF(FALSE,,) (argument there but value omitted) returns 0.
But for the value_if_true argument, only option #2 is allowed according to the documentation. There is no provision for omitting this argument entirely; only omitting its value is supported. So =IF(TRUE,) and =IF(TRUE,,) (argument there but value omitted) both return 0, while =IF(TRUE) (argument omitted entirely) is unsupported and therefore does not compile.
The above describes the documented and supported behaviour. Of course this doesn't answer the deeper question of "why" it is like that. My answer to that is, I don't know. I'm sure the makers of Excel had a good reason, or at least thought they did.
As for UDFs, they are written in VBA and their Optional parameters are governed by VBA's rules, which are different. There is no such thing as omitting "the value of" a parameter in VBA functions.

Exclamation operator?

I'm learning D and have seen a lot of code like this:
ushort x = to!ushort(args[1]);
I assume this casts args[1] to ushort, but what's the difference between this and cast(ushort)?
EDIT: And what other uses does the exclamation mark operator have?
In D,
to!ushort(args[1])
is shorthand for the template instantiation
to!(ushort)(args[1])
and is similar to
to<ushort>(args[1])
in languages like C++/Java/C#.
The exclamation point is to note the fact that it's not a regular argument, but a template argument.
The notation does not use angle brackets because those are ridiculously difficult to parse correctly for a compiler (they make the grammar very context-sensitive), which makes it that much more difficult to implement a correct compiler. See here for more info.
The only other use I know about is just the unary 'not' operation (e.g. false == !true)... I can't think of any other uses at the moment.
Regarding the cast:
cast(ushort) is an unchecked cast, so it won't throw an exception if the value is out of range.
to!ushort() is a checked cast, so it throws an exception if the value is out of range.
The exclamation mark here is not an operator, it is just a token part of the explicit template instantiation syntax (described in detail here).
std.conv.to (docs) is a function template for converting between arbitrary types. It is implemented entirely in the library and has no special support in the language. It has a broader and different scope compared to the cast operator.
The to template takes two type parameters; a "to" type and a "from" type, in that order. In your example, the template is explicitly instantiated with the single type argument ushort for the "to" parameter, and a second type argument string (assuming args comes from the first parameter to main) is automatically inferred from the regular function argument passed to the function (args[1]) as the "from" parameter.
The resulting function takes a string parameter and returns a ushort parsed from that string, or throws an exception if it failed. The cast operator will not attempt this kind of high-level conversion.
Note that if there is more than one explicit template parameter, or that parameter has more than one token in it (ushort is a single keyword token), you must wrap the template parameter list in parentheses:
ushort result;
result = to!(typeof(result))(args[1]);
In this example, typeof, (, result and ) are four separate tokens and the parentheses are thus required.
To answer your last question, the ! token is also used for the unary not operator, unrelated to template instantiations:
bool yes = true;
bool no = !yes; // 'no' is false
You already got two excellent answers by jA_cOp and Merhdad. I just want answer directly to the OP question (what's the difference between this and cast(ushort)?) - The difference is that cast(ushort)args[1] will not work (you cannot cast from a string to an uint just like that), while the to!(type)(param) template knows what to do with the string and how to convert it to the primitive type.

Is the 'Is' VB.NET keyword the same as Object.ReferenceEquals?

Is the Is VB.NET keyword the same as Object.ReferenceEquals?
Yes, it is, unless combined with a TypeOf check.
Quote from MSDN:
The Is operator determines if two
object references refer to the same
object. However, it does not perform
value comparisons. If object1 and
object2 both refer to the exact same
object instance, result is True; if
they do not, result is False.
Is can also be used with the TypeOf
keyword to make a TypeOf...Is
expression, which tests whether an
object variable is compatible with a
data type.
BTW, also note the IsNot operator (which gives the boolean inverse of the matching Is expression):
IsNot is the opposite of the Is
operator. The advantage of IsNot is
that you can avoid awkward syntax with
Not and Is, which can be difficult to
read.