Java8 time comparison in Kotlin - kotlin

I stumbled across some strange behaviour when comparing Java8 time objects.
The below does not appear to be valid code.
val t1 = LocalTime.now()
val t2 = LocalTime.now()
val foo: Int = t1 > t2
Yet hovering over the undersquiggled code shows that the overridden function return type is correct:
Any ideas?

According to the documentation, when using the natively overloaded operators (comparison operators specifically) - Kotlin doesn't just call compareTo but rather performs a compareTo against 0 (thus ending up as a bool).
https://kotlinlang.org/docs/operator-overloading.html#comparison-operators
Comparison operators
Expression
Translated to
a > b
a.compareTo(b) > 0
a < b
a.compareTo(b) < 0
a >= b
a.compareTo(b) >= 0
a <= b
a.compareTo(b) <= 0
All comparisons are translated into calls to compareTo, that is required to return Int.
The documentation snippet you attached is admittedly a bit confusing.

Related

Doing BNF for a simplified SQL “where” clause

I have the following SQL statement with a rudimentary BNF applied:
SELECT
from_expression [, from_expression] ...
FROM
from_source
WHERE
condition
from_source:
table_name
from_expression:
literal # 'abc', 1,
column # Table.Field1, Table.Profit
function # ABS(...)
operator invocation # NOT field1, 2+3, Genres[0], Genres[1:2], Address.name
condition:
???
For now the WHERE condition is the same as the from_expression but evaluated as a boolean. What would be the proper way to show that?
The grammar doesn't care about semantics.
Syntactically, an expression is an expression, nothing more. If you later do some kind of semantic analysis, that is when you'll need to deal with the difference. You might do that in the reduction actions for condition and from_expression but it would be cleaner to just build an AST while parsing and do the semantic analysis later on the tree.
One option would be as follow, with examples in-line:
expression:
literal # 'abc', 1,
column # Table.Field1, Table.Profit
function call # ABS(...)
operator invocation # NOT field1, 2+3, Genres[0], Genres[1:2], Address.name
condition:
expression { = | != | < | <= | > | >= | IN } expression # Revenue > 0
expression IS [NOT] NULL # Revenue IS NOT NULL
condition { AND | OR } condition # Revenue > 0 AND Profit < 100
This is a comment that doesn't fit in the comments section.
I was hesitant to provide the link to the LiveSQL implementation, since it's specifically for Java language, it's open source, but we have never added any documentation whatsoever. Read at your own risk.
The main class is LiveSQL.java: in line 113 you can see the main variant of the select clause. It has many variants, but this is the one that allows the developer to include as many result set columns (expressions) as needed:
public SelectColumnsPhase<Map<String, Object>> select(
final ResultSetColumn... resultSetColumns) {
return new SelectColumnsPhase<Map<String, Object>>(this.sqlDialect,
this.sqlSession, this.liveSQLMapper, false,
resultSetColumns);
}
Of course, the SELECT clause has many other variants, that you can find in the same class if you explore it a bit. I think I was pretty exhaustive when I researched all variants. It should be [mostly] complete, except for non-standard SQL dialect variations that I didn't consider.
If you follow the QueryBuilder up the WHERE phase you can see how the predicate is assembled in the method where(final Predicate predicate) (line 101) of the SelectFrom.java class, as in:
public SelectWherePhase<R> where(final Predicate predicate) {
return new SelectWherePhase<R>(this.select, predicate);
}
As you can see the WHERE clause does not accept any type of expression. First of all, it only accepts a single expression, not a list. Second this expression must be a Predicate (boolean expression). Of course, this predicate can be as complex as you want, mixing all kinds of expressions and boolean logic. You can peek at the Predicate.java class to explore all the expressions that can be built.
Condition
Let's take as an example the Predicate class described above. If p and q are boolean expressions and a, b, c are of [mostly] any type you can express the condition as:
condition:
<predicate>
predicate:
p and q,
p or q,
not p,
( p ),
a == b,
a <> b,
a > b,
a < b,
a >= b,
a <= b,
a between b and c,
a not between b and c,
a in (b, c, ... )
a not in (b, c, ... )
Of course there are more operators but this gives you the gist of it.

null safety without elvis operator kotlin

a ?: b is just shorthand for if (a != null) a else b.
I understand that ?: eliminates the danger of null references from code. However I encountered fragment, which I failed to re-write myself. Here it is:
`
val words = mutableMapOf<String, Int>()
input = scan.next()
wordCounts[input] = (wordCounts[input] ?: 0) + 1
What I tried is:
words[input] = if (words[input] != null) (words[input]+1) else 0
However Intelij displays error here
After I replaced it with its sugesttion I have further errors:
words[input] = if (words[input] != null) (words[input]?.plus(1)) else 0
How can I fix that if statement remain?
val n = words[input]
words[input] = if (n != null) n + 1 else 0
words might change value to become null after your if statement, so you should capture the variable first and then do the assignment.
a ?: b is just shorthand for if (a != null) a else b
That's almost true.  But there's one subtle difference: the elvis version only evaluates a once, while the other evaluates it twice — carrying the possibility that it could give a different result each time.
In this case, a is words[input].  What if another thread changes the contents of words in between the two evaluations, removing the value for key input so that words[input] returns null the second time?  (Even if you know that no other thread could possibly be accessing it, if the compiler can't prove that, it has to assume that the second time could give a null result.)
So the solution is to evaluate it only once.
You can do that with a temporary variable, as per another answer.  But Kotlin's scoping functions give you a slightly simpler option:
words[input].let{ if (it != null) it + 1 else 1 }
This works because let() is an extension method defined on Any?, so (unlike ‘real’ methods) it's safe to call on a null.
However, this just illustrates why the elvis operator is useful, and how it simplifies some code!  You don't explain why you want to rewrite your code to avoid it; that could be a useful learning exercise, but in practice you'd just use the elvis operator instead.

Merging add and sub functions in SafeMath.sol

I want to merge the addition and subtraction function with their associated revert guard functions using OR (||) operators, but I am missing the syntax. Could anyone advise?
The functions are initially two in different blocks. I am attempting to make addition and subtraction functions into one and call them using one name in the contract. My assumption is that the OR operator could allow me do that.
I expected the new merged function to work just fine.
But I am getting the error message telling me that there is an overflow.
I want to merge the addition and subtraction function with their associated revert guard functions using OR (||) operators, but I am missing the syntax. Could anyone advise?
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
bool whichOp; // to test which operator to use
whichOp = c = a + b || c = a - b;
whichOp = require(c >= a, "SafeMath: addition overflow") || require(b <= a, "SafeMath: subtraction overflow");
return c;
}
I expected the new merged function to work just fine.
But I am getting the error message telling me that there is an overflow.

How to parse big string U-SQL Regex

I have got a big CSVs that contain big strings. I wanna parse them in U-SQL.
#t1 =
SELECT
Regex.Match("ID=881cf2f5f474579a:T=1489536183:S=ALNI_MZsMMpA4voGE4kQMYxooceW2AOr0Q", "ID=(?<ID>\\w+):T=(?<T>\\w+):S=(?<S>[\\w\\d_]*)") AS p
FROM
(VALUES(1)) AS fe(n);
#t2 =
SELECT
p.Groups["ID"].Value AS gads_id,
p.Groups["T"].Value AS gads_t,
p.Groups["S"].Value AS gads_s
FROM
#t1;
OUTPUT #t
TO "/inhabit/test.csv"
USING Outputters.Csv();
Severity Code Description Project File Line Suppression State
Error E_CSC_USER_INVALIDCOLUMNTYPE:
'System.Text.RegularExpressions.Match' cannot be used as column type.
I know how to do it in a SQL way with EXPLODE/CROSS APPLY/GROUP BY. But may be it is possible to do without these dances?
One more update
#t1 =
SELECT
Regex.Match("ID=881cf2f5f474579a:T=1489536183:S=ALNI_MZsMMpA4voGE4kQMYxooceW2AOr0Q", "ID=(?<ID>\\w+):T=(?<T>\\w+):S=(?<S>[\\w\\d_]*)").Groups["ID"].Value AS id,
Regex.Match("ID=881cf2f5f474579a:T=1489536183:S=ALNI_MZsMMpA4voGE4kQMYxooceW2AOr0Q", "ID=(?<ID>\\w+):T=(?<T>\\w+):S=(?<S>[\\w\\d_]*)").Groups["T"].Value AS t,
Regex.Match("ID=881cf2f5f474579a:T=1489536183:S=ALNI_MZsMMpA4voGE4kQMYxooceW2AOr0Q", "ID=(?<ID>\\w+):T=(?<T>\\w+):S=(?<S>[\\w\\d_]*)").Groups["S"].Value AS s
FROM
(VALUES(1)) AS fe(n);
OUTPUT #t1
TO "/inhabit/test.csv"
USING Outputters.Csv();
This wariant works fine. But there is a question. Will the regex evauated 3 times per row? Does exists any chance to hint U-SQL engine - the function Regex.Match is deterministic.
You should probably be using something more efficient than Regex.Match. But to answer your original question:
System.Text.RegularExpressions.Match is not part of the built-in U-SQL types.
Thus you would need to convert it into a built-in type, such as string or SqlArray<string> or wrap it into a udt that provides an IFormatter to make it a user-defined type.
Looks like it is better to use something like this to parse the simple strings. Regexes are slow for the task and if i will use simple string expressions (instead of CLR calls) they probably will be translated into c++ code at codegen phase... and .net interop will be eliminated (i'm not sure).
#t1 =
SELECT
pv.cust_gads != null ? new SQL.ARRAY<string>(pv.cust_gads.Split(':')) : null AS p
FROM
dwh.raw_page_view_data AS pv
WHERE
pv.year == "2017" AND
pv.month == "04";
#t3 =
SELECT
p != null && p.Count == 3 ? p[0].Split('=')[1] : null AS id,
p != null && p.Count == 3 ? p[1].Split('=')[1] : null AS t,
p != null && p.Count == 3 ? p[2].Split('=')[1] : null AS s
FROM
#t1 AS t1;
OUTPUT #t3
TO "/tmp/test.csv"
USING Outputters.Csv();

SQL check for NULLs in WHERE clause (ternary operator?)

What would the SQL equivalent to this C# statement be?
bool isInPast = (x != null ? x < DateTime.Now() : true)
I need to construct a WHERE clause that checks that x < NOW() only if x IS NOT NULL. x is a datetime that needs to be null sometimes, and not null other times, and I only want the WHERE clause to consider non-null values, and consider null values to be true.
Right now the clause is:
dbo.assignments.[end] < { fn NOW() }
Which works for the non-NULL cases, but NULL values always seem to make the expression evaluate to false. I tried:
dbo.assignments.[end] IS NOT NULL AND dbo.assignments.[end] < { fn NOW() }
And that seems to have no effect.
For use in a WHERE clause, you have to test separately
where dbo.assignments.[end] is null or dbo.assignments.[end] < GetDate()
or you can turn the nulls into a date (that will always be true)
where isnull(dbo.assignments.[end],0) < GetDate()
or you can do the negative test against the bit flag derived from the below
where case when dbo.assignments.[end] < GetDate() then 0 else 1 end = 1
The below is explanation and how you would derive isInPast for a SELECT clause.
bool isInPast = (x != null ? x < DateTime.Now() : true)
A bool can only have one of two results, true or false.
Looking closely at your criteria, the ONLY condition for false is when
x != null && x < now
Given that fact, it becomes an easy translation, given that in SQL, x < now can only be evaluated when x!=null, so only one condition is needed
isInPast = case when dbo.assignments.[end] < { fn NOW() } then 0 else 1 end
(1 being true and 0 being false)
Not sure what { fn NOW() } represents, but if want SQL Server to provide the current time, use either GETDATE() or if you are working with UTC data, use GETUTCDATE()
isInPast = case when dbo.assignments.[end] < GetDate() then 0 else 1 end
The one you are looking for is probably the CASE statement
You need something like
WHERE X IS NULL
OR X < NOW()
Have two separate queries, one when x is null one when is not. Trying to mix the two distinct conditions is the sure shot guaranteed way to get a bad plan. Remember that the generated plan must work for all values of x, so any optimization based on it (a range scan on an index) is no longer possible.