union type inference change between v1.7 and v1.8 - typescript1.8

In snippet below TypeScript compiler v1.7 identifies x as C1 under third typeguard clause
class C1 { item: string }
class C2 { item: string[] }
class C3 { item: string }
function Foo(x: C1 | C2 | C3): string {
if (x instanceof C1)
return x.item;
else if (x instanceof C2)
return x.item[0];
else if (x instanceof C3)
//in v1.7 compiler thinks x is C1
//in v1.8 compiler thinks x is C2
return x.item;
}
V1.8 thinks of x as C2 under third typeguard therefore making compilation to fail.
Is it intended or bug?

This is a bug in the compiler both in v1.7 and v1.8 even though the final result is different in them. The (x instanceof C3) type guard should make it C3 in that block period. I'll log a bug.
Bug report : https://github.com/Microsoft/TypeScript/issues/7271 🌹

Related

How to use `when` with 2 sealed classes and getting the inner value?

Consider this extreme simplified code (available on https://pl.kotl.in/bb2Irv8dD):
sealed class Person {
data class A(val i: Int) :
Person()
}
fun main() {
val a = Person.A(i = 0)
val b = Person.A(i = 1)
// Compiles
when (a) {
is Person.A -> print("I have access to {$a.i}")
}
// Does not compile :(
when (a to b) {
is Person.A to is Person.A -> print("I have access to {$a.i} and b {$b.i}")
}
}
Why does the (a to b) code not work? It works for 1 variable, I was hoping I can match on both classes and get both inner values.
The error is:
Incompatible types: Person.A and Pair<Person.A, Person.A> Expecting
'->' Expecting an element Incompatible types: Person.A and
Pair<Person.A, Person.A>
Aside from that syntax not being supported (you can only use is on one thing in a when branch), by using to you're literally creating an instance of the Pair class.
Pair uses generics for the types of its two variables, so this type information is lost at runtime due to type erasure.
So although, you can do this:
when (a to b) {
is Pair<Person.A, Person.A> -> print("I have access to {$a.i} and b {$b.i}")
}
it is only allowed when both a and b are local variables whose types are declared locally, so that the generic types of the Pair are known at compile time. But this makes it mostly useless, because if a and b are local variables with known type at compile time, then you could just replace the above with true or false.
To be able to do something like this in a general way, you must either create local variables to use:
val aIsTypeA = a is Person.A
val bIsTypeA = b is Person.A
when (aIsTypeA to bIsTypeA) {
true to true -> //...
//...
}
or use when without a subject and put the full condition on each branch:
when {
a is Person.A && b is Person.A -> //...
//...
}
The (a to b) returns a Pair<Person.A,Person.A> but what you are checking is Type Person.A to Type Person.A instead of the Type Pair<Person.A,Person.A>.
What you can do instead is:
when (a to b) {
is Pair<Person.A,Person.A> -> print("I have access to {$a.i} and b {$b.i}")
}

Kotlin toSortedMap() with custom Comparator not working properly

I need to group and sort an API result by 1st character of name. All names starting with a letter should come in order, followed by names starting with non-alphabet grouped into "#" and placed at end. Below is a simplified code:
data class Model(val title: String)
fun main() {
val mList = arrayListOf(Model("pqr"), Model("abc"), Model("3AM"), Model("%s5"))
val mComparator = Comparator<String> { o1, o2 ->
when {
o1 == "#" -> 1
o2 == "#" -> -1
else -> o1.compareTo(o2)
}
}
val mMap = mList.groupBy {
if (it.title[0].isLetter()) it.title[0].toString()
else "#"
}.toSortedMap(mComparator)
val outList = arrayListOf<List<Model>?>()
mMap.keys.forEach {
outList.add(mMap[it])
}
println(mMap)
println(mMap.keys)
println(mMap.values)
println(mMap["#"])
println(outList)
}
Here's output of above code:
{a=[Model(title=abc)], p=[Model(title=pqr)], #=[Model(title=3AM), Model(title=%s5)]}
[a, p, #]
[[Model(title=abc)], [Model(title=pqr)], [Model(title=3AM), Model(title=%s5)]]
null
[[Model(title=abc)], [Model(title=pqr)], null]
The problem is that mMap["#"] gives null although mMap, mMap.keys, mMap.values show "#" in keys and also the corresponding values.
Don't understand why mMap["#"] returns null rather than [Model(title=3AM), Model(title=%s5)]
Your comparator breaks the contract that a Comparator must satisfy. It must be reflexive, meaning it gives the exact opposite result if you swap the order of the two inputs. A corrected version of your comparator:
val mComparator = Comparator<String> { o1, o2 ->
when {
o1 == "#" && o2 != "#" -> 1
o2 == "#" && o1 != "#" -> -1
else -> o1.compareTo(o2)
}
}
TreeMap depends on a correct Comparator for its functionality. Apparently, its comparator is even involved when using treeMap.get such that in your case it returns the nonsensical result of null.
By the way, putting an "m" prefix before a variable name is Hungarian notation that means the prefix is a member variable. But these are not member variables. They are local variables. Kotlin doesn't even have member variables, but properties are analogous. So, you should not be using "m" prefixes here because it communicates incorrectly about the meaning of your code. Anyway, most developers avoid using Hungarian notation because it makes code harder to read. A lot of official Android examples use it because of the Android development team's internal code style, but that is not a recommendation that you use it in your own code.
val mComparator = Comparator<String> { o1, o2 ->
when {
(o1 == "#").xor(o2 == "#") -> if (o1 == "#") 1 else -1
else -> o1.compareTo(o2)
}
}

kotlin, which one is better, using "is" or "as?",

two functions test1 and test2, one uses "is" to check type, and one use "as?", seems test2 with "as?" has less code, but is it really better than the one uses "is" to do check?
Is there a comparison for using "is" vs. "as?", what is suggestion for general use of these two?
class Message(val int: Int, val msg:String)
class Test {
fun test1(objList: List<Any?>) {
for (i in objList.size - 1 downTo 0) {
val item = objList.get(i)
if (item is Message) {
println(item)
}
}
}
fun test2(objList: List<Any?>) {
for (i in objList.size - 1 downTo 0) {
(objList.get(i) as? Message)?.let {item ->
println(item)
}
}
}
}
So if you look at the JVM bytecode of both:
// JVM bytecode of test1
L5
LINENUMBER 8 L5
ALOAD 3
INSTANCEOF com/example/artifact/Message
IFEQ L6
// JVM bytecode of test2
L4
LINENUMBER 16 L4
ALOAD 0
ILOAD 1
INVOKEINTERFACE java/util/List.get (I)Ljava/lang/Object; (itf)
DUP
INSTANCEOF com/example/artifact/Message
IFNE L5
POP
ACONST_NULL
L5
CHECKCAST com/example/artifact/Message
DUP
IFNULL L6
ASTORE 3
You can clearly see that the test1 does check for the type only and it smart casts the result, while the test2 however first checks if the instance is of that type and then returns null or "casts" explicitly it to that type.
So, through this observation I'll suggest you to use the is operator as it is more optimized for these tasks. If you don't like using curly braces then you can omit them like python, or put the println on the same line as you're doing if conditions.
This is more optimized code if you'd like:
fun test1(objList: List<Any>) {
for (item in objList.asReversed()) {
if (item is Message) println(item)
}
}
fun test2(objList: List<Any>) {
for (item in objList.asReversed()) {
(item as? Message)?.let { println(it) }
}
}
The as? version may have one less line of code, but does it really have less code overall? You may have gotten rid of:
val item = objList.get(i)
But you replaced it with:
(objList.get(i) as? Message)?.let {item ->
In this case, I'd argue that the as? version requires ever so slightly more time to comprehend than the is version, which is more straightforward. I also doubt there's a significant difference in performance between the two approaches. In general, always prefer the more readable code over the more performant code unless you've profiled an actual performance problem in your application. Whether or not there's a performance problem is highly dependent on the context of your application. And remember, premature optimization is the root of all evil.
If you really want less code then consider using the following:
fun test(objList: List<Any>) = objList.asReversed().forEach {
if (it is Message) println(it)
}
This makes use of:
Single-expression functions
List.asReversed (returns a reversed view of the original list)
Iterable.forEach
it: implicit name of a single parameter (in lambda expressions)
is is type checking. as is type casting.
the different is
is return boolean, true or false
as return that type
you use is if you want the answer only yes or no
example
if (user is Login) you just want the answer yes or no right?
and then you do something else
you use as when you want to try to cast to that type
example
(user as? Admin).let{print(it.name.toString())}
this one you want to check if this user is Admin or not
if yes you want to use that user value to print something like name
so for condition Use is
for casting Use as
fun test(objList: List<Any>) = objList.asReversed().forEach {
when(it){ is Message -> println(it)}
}

Fluent Interface in ReasonML

Is there a way to get a module to return its own type using a functor submodule?
Example
module type A = {};
module type B = { let varB: int; };
module AMod : A = {};
module BMod : B = { let varB = 42; };
module Fn = (A: A, B: B) => A; /* Lets say this does some complex function that returns Type A */
module A2 = Fn(AMod, BMod);
What I want is a Fluent interface where a functor would be in A which returns its own type so it would look like
module type C = { module Fn: (B) => C };
module CMod : C = { Fn: (B) => C};
module C2 = CMod.Fn(BMod).Fn(BMod).Fn(BMod).Fn(BMod).Fn(BMod);
Is this possible in Reason or Ocaml?
Thanks
No, this is not possible. Your module type C would be recursive, which is not allowed. Such a form of recursion could very easily lead to undecidable type checking, given the expressive power of module types.
It seems like you are trying to shoehorn an object-oriented pattern onto modules, which won't usually work -- ML modules are very much a functional language in nature. What's wrong with the following?
module A2 = Fn(Fn(Fn(Fn(Fn(A, B), B), B), B), B)
If you are interested in shortening the general pattern, you can actually implement a module combinator (in plain Ocaml, since I don't know Reason syntax well enough):
module type FN = functor (X:A)(Y:B) -> A
let rec fn n =
if n = 0 then (module (functor (X:A)(Y:B) -> X) : FN)
else (module (functor (X:A)(Y:B) -> (val fn (n-1))(X)(Y)))
module A2 = (val fn 5)(AMod)(BMod)
You could also write combinators that take a list of different B modules, though I wonder how useful that is going to be in practice.

Is there any programming language that provides syntactic sugar for run-time input checking of arguments?

I would like to be able to write a function like this:
print_multiple_times (Int(> 3 && <= 40) foo; String(match "^.{5}$") bar) =
print(bar * foo)
That behaves like this:
print_multiple_times (Int foo; String bar) =
if not (foo > 3 && foo <= 40):
throw InputError('print_multiple_times, 'foo)
if not (bar match "^.{5}$"):
throw InputError('print_multiple_times, 'bar)
print(bar * foo)
Here's an example of Racket's contract system:
(define/contract (log10 x)
(-> (>/c 0) real?)
(/ (log x) (log 10)))
The contract in the code above is this line: (-> (>/c 0) real?). The arrow indicates a function contract, which has the argument contracts followed by a single contract for the result. The contract on the argument is (>/c 0), which checks that the argument is a real number greater than zero. The contract on the result is real?, which is Racket's built-in predicate for real numbers. A predicate can be used anywhere a contract is needed. Also, a regular expression acts as a contract that accepts strings that it matches. Racket has a rich library for producing different kinds of contracts.
Here are some good examples of using the function:
> (log10 10)
1.0
> (log10 250)
2.397940008672037
And here's an example of a contract violation:
> (log10 -5.0)
; log10: contract violation
; expected: a number strictly greater than 0
; given: -5.0
; in: the 1st argument of
; (-> (>/c 0) real?)
; contract from: (function log10)
; ....
See the chapter on contracts in the Racket Guide for more details.
IIRC, Racket's contract system was partly inspired by Eiffel, but I believe Racket's contracts are far more expressive, and Eiffel contracts are broken for subclassing.
In languages that provide implicit casting/type-conversion you can define types that perform the desired checks on their constructor, and boxing methods to automatically cast from literals.
(untested)
class Foo
{
public Foo(int i)
{
if (! (i > 3 && i <= 40)) {
throw ArgumentOutOfRangeException('i')
}
val = i;
}
public int val;
public static implicit operator int(Foo i)
{
return i.val;
}
public static implicit operator Foo(int i)
{
return new Foo(i);
}
public void print_multiple_times(Foo foo, string bar) {
// ...
}
}