In many languages it's considered OK to have non-bool values in if statement conditions. Python has 16+ different values and scenarios when objects of different types are considered false, Java Script - 9, C++ - 3. Rust allows to define user conversion with
truthy::Truthy. This is obscure and error prone. That's why Argentum allows only one type as condition discriminator - optional; and only one value that considered false -
One of the main reasons for non-bool values as conditions is to adorn a conditional operator with certain computations in its condition, and make result accessible within the conditional branches via temporary local variable. For instance, in C++:
if (auto v = expression()) use(v);
For this to work,
v must be convertible to bool. However, it quickly became apparent that converting the same type to a bool type could be done in various ways and trythy/falsy rules aren't sufficient for all cases. Therefore, in C++17, a convenient variant appeared:
if (auto v = expression; predicate(v)) use(v);
How does it work?
- It evaluates
- it placed result is in the local variable
- Then it evaluates its
predicate, which converts it into a bool.
- Than basing on this bool, it choses the appropriate branch, and makes the value of
vaccessible within that branch. For example:
if (auto i = myMap.find(name); i != myMap.end()) use(*i);
Here is how this is achieved in Argentum without any additional syntax:
predicate(expression) ? use(_)
expressionyields a value of type
predicateanalyzes it and converts it into
?Twith a value inside.
?operator, checks the ?T and calls use with name "_" holding the value of type T.
isAppropriate(getUserName(userId)) ? log(_) : log("username is so @#$ity that I can't even say it");
- Argentum implements this functionality without introducing new language constructs.
- Argentum disallows implicit conversion of objects to bool, requiring each condition to specify which aspect of the object is being checked in each if-statement.