What are the truthy and falsy values in Raku? - 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.

Related

Unexpected result when comparing CharSequence.reversed() return value

Have noticed a strange behavior when comparing a result of CharSequence.reversed() method.
val s = "a"
val subSequence = s.subSequence(0, 1)
println("$subSequence == ${subSequence.reversed()}: ${subSequence == subSequence.reversed()}")
Results in:
a == a: false
Moreover subSequence.reversed() == subSequence.reversed() is also false.
Can someone explain this unexpected behavior?
CharSequence is actually an interface which classes like String and StringBuilder implements. The reason why the result of subSequence(0, 1) isn't equal to subSequence.reversed() is because of the actual types they return.
The subSequence(0, 1) call returns a String, while reversed() returns a StringBuilder. The equals-method will therefore return false because the types are different.
It will work as you would expect if you call toString() on the result of reversed():
val reversed = subSequence.reversed().toString()
println("$subSequence == $reversed: ${subSequence == reversed}") // Prints a == a: true
Converting back to a String fixes the issue because then the correct (expected) eqauals is applied:
val s = "a"
val subSequence = s.subSequence(0, 1)
println(subSequence.reversed() == subSequence.reversed()) //false
println(subSequence.reversed().toString() == subSequence.reversed().toString()) //true
Note that you are probably confused by what is shown by toString and how equality (equals) behaves.
What you see is the output of toString(). Any type can decide how it's object's string representation might look like by overriding that method. This however has no influence on how objects of that type are compared against each other. That is where equals (in some cases also compare) comes in.
Others wrote something about that the underlying type of the objects to compare isn't equal (one side StringBuilder and the other String). The actual problem however is that of the equals-method. It could be (usually it isn't done so for various reasons), that equals for a certain type supports equality of different types of objects (such a behaviour (would) should be mentioned in the interface at least). If nothing is specified one can assume that the default equality from Object.equals holds.
In this case however the CharSequence-javadoc already states the following about equality (emphasis mine):
This interface does not refine the general contracts of the equals and hashCode methods. The result of testing two objects that implement CharSequence for equality is therefore, in general, undefined. Each object may be implemented by a different class, and thereis no guarantee that each class will be capable of testing its instancesfor equality with those of the other. It is therefore inappropriate to usearbitrary CharSequence instances as elements in a set or as keys ina map.
So summarizing: forget that you got a String or StringBuilder from subSequence and reversed. The method contract specifies CharSequence and as such you must handle it as CharSequence. There is no guarantee that those functions will still return a String or StringBuilder in future.

How to use ABAP boolean in IF condition?

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...

Warn if using an object as a boolean expression in conditionals

Is there a clang flag to warn when you use e.g. an object in an if statement instead of a boolean expression?
I googled for this but couldn't find anything. This would help prevent mistakes like this, especially when using editor generated Core Data classes:
NSNumber *n = #(YES)
if (n) { // should be n.boolValue instead of n
...
}
I found an "Implicit Boolean Conversions" option in Xcode but that doesn't seem to be it (I double checked).
No, there is no short-hander for this and there cannot be.
A.
if comes from classical C. In classical C there is no boolean type. (They extended C in 99, but did not touch if.) Basically everything !=0 is true, everything ==0 is false.
B.
n is no object. It is an object reference. You need expressions like you have to check, whether the object reference points to nil. With your suggestion there would be no difference between "no object" and "an object containing NO".

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.

Difference between using GetterUtils and ParamUtils

For instance, when to use
GetterUtil.getBoolean()
and when
ParamUtil.getBoolean()?
Are both same, or is it expected to be used differently according to a parameter, a variable, etc? Can you give some examples for both?
Both are util methods to avoid Null-Pointer Exceptions.
GetterUtil internally returns the default type and does the casting too. So in case where someone has passed a null value, it will return default value of the type.
Example:
Assume you have a String value "true", and you are expecting it will always be of type boolean. So you use GetterUtil.getBoolean("true") which will internally do the casting to boolen and return the value as boolean-true. Incase someone passes rubbish characters like "tr", it will be converted to boolean-false.
As mentioned ParamUtil does the same treatment with request parameters. ParamUtil internally uses the GetterUtil to have the above behaviour. It first retrieves the parameter (which always would be a string) and then passes it to GetterUtil.getType() method and in turn returns the proper type.
GetterUtil and ParmUtil both are different classes.
GetterUtil is to get the default values for basic Java data types.
ParamUtil is to retrive the values(of primitive data types) from the HttpReqeust.
Check the source code here for these two classes here
For GetterUtil
http://docs.liferay.com/portal/6.0/javadocs/src-html/com/liferay/portal/kernel/util/GetterUtil.html
For ParamUtil
http://docs.liferay.com/portal/5.1/javadocs/portal-kernel/com/liferay/portal/kernel/util/ParamUtil.java.html