Kotlin class equality fails - reflection

The following snippet shows the result of testing equality of Kotlin KClass references obtained from different sources. Their string representations are the same. But their java classes are different. Expected that c, c0 and c1 are equal. But for some reason they aren't.
Is there some nuance or it's a bug? If it's not a bug what is the reliable way to test equality of KClasses?
fun main(args: Array<String>) {
val c = Int::class
fun test(v0: Any, v1: Any) {
val c0 = v0.javaClass.kotlin
val c1 = v1.javaClass.kotlin
println("c= $c; c0= $c0; c1= $c1") // c= class kotlin.Int; c0= class kotlin.Int; c1= class kotlin.Int
println("c= ${c.java}; c0= ${c0.java}; c1= ${c1.java}") // c= int; c0= class java.lang.Integer; c1= class java.lang.Integer
println("c = c0? ${c == c0}; c0 = c1? ${c1 == c0}") // c = c0? false; c0 = c1? true
}
test(11, 22)
}
EDIT:
The workaround is to use KClass.javaObjectType method.
The docs says:
Returns a Java Class instance corresponding to the given KClass instance. In case of primitive types it returns corresponding wrapper classes.
I.e. c.javaObjectType == c1.javaObjectType is true
But it doesn't justifies why KClasses having same string representation are different. At least it's confusing. And it's good idea to note about that in docs.

In your case equality fails because KClasses are considered equal when they correspond to the same Java's type, not the same Kotlin type. This is false for int and java.lang.Integer.
The workaround is to use KClass's javaObjectType property, which will return Java class (not primitive type) even for Kotlin type compiled into Java's primitive:
fun sameClass(c1: KClass<*>, c2: KClass<*>) = c1.javaObjectType == c2.javaObjectType
sameClass(Int::class, (1 as Any?)!!.javaClass.kotlin) //true
I agree that this semantics is rather confusing, I filed an issue about it.
Also, KClass doesn't reflect nullability of Kotlin types, and in case if you need to work with declared Kotlin types precisely, you will need to use KType, which does.
UPD: the issue has been marked as fixed, and the equality is explained in KClass.equals KDoc since 1.0.2.

Related

porting python class to Julialang

I am seeing that Julia explicitly does NOT do classes... and I should instead embrace mutable structs.. am I going down the correct path here?? I diffed my trivial example against an official flux library but cannot gather how do I reference self like a python object.. is the cleanest way to simply pass the type as a parameter in the function??
Python
# Dense Layer
class Layer_Dense
def __init__(self, n_inputs, n_neurons):
self.weights = 0.01 * np.random.randn(n_inputs, n_neurons)
self.biases = np.zeros((1, n_neurons))
def forward(self, inputs):
pass
My JuliaLang version so far
mutable struct LayerDense
num_inputs::Int64
num_neurons::Int64
weights
biases
end
function forward(layer::LayerDense, inputs)
layer.weights = 0.01 * randn(layer.num_inputs, layer.num_neurons)
layer.biases = zeros((1, layer.num_neurons))
end
The flux libraries version of a dense layer... which looks very different to me.. and I do not know what they're doing or why.. like where is the forward pass call, is it here in flux just named after the layer Dense???
source : https://github.com/FluxML/Flux.jl/blob/b78a27b01c9629099adb059a98657b995760b617/src/layers/basic.jl#L71-L111
struct Dense{F, M<:AbstractMatrix, B}
weight::M
bias::B
σ::F
function Dense(W::M, bias = true, σ::F = identity) where {M<:AbstractMatrix, F}
b = create_bias(W, bias, size(W,1))
new{F,M,typeof(b)}(W, b, σ)
end
end
function Dense(in::Integer, out::Integer, σ = identity;
initW = nothing, initb = nothing,
init = glorot_uniform, bias=true)
W = if initW !== nothing
Base.depwarn("keyword initW is deprecated, please use init (which similarly accepts a funtion like randn)", :Dense)
initW(out, in)
else
init(out, in)
end
b = if bias === true && initb !== nothing
Base.depwarn("keyword initb is deprecated, please simply supply the bias vector, bias=initb(out)", :Dense)
initb(out)
else
bias
end
return Dense(W, b, σ)
end
This is an equivalent of your Python code in Julia:
mutable struct Layer_Dense
weights::Matrix{Float64}
biases::Matrix{Float64}
Layer_Dense(n_inputs::Integer, n_neurons::Integer) =
new(0.01 * randn(n_inputs, n_neurons),
zeros((1, n_neurons)))
end
forward(ld::Layer_Dense, inputs) = nothing
What is important here:
here I create an inner constructor only, as outer constructor is not needed; as opposed in the Flux.jl code you have linked the Dense type defines both inner and outer constructors
in python forward function does not do anything, so I copied it in Julia (your Julia code worked a bit differently); note that instead of self one should pass an instance of the object to the function as the first argument (and add ::Layer_Dense type signature so that Julia knows how to correctly dispatch it)
similarly in Python you store only weights and biases in the class, I have reflected this in the Julia code; note, however, that for performance reasons it is better to provide an explicit type of these two fields of Layer_Dense struct
like where is the forward pass call
In the code you have shared only constructors of Dense object are defined. However, in the lines below here and here the Dense type is defined to be a functor.
Functors are explained here (in general) and in here (more specifically for your use case)

ACSL Logic Struct Declarations Not Working as in Reference Manual

I would like to have a way to describe logic/spec level structs that include abstract lists. Example 2.2.7 on page 27 of the ACSL Reference Manual suggests that there is a
way to do this and it is as follows:
//# type point = struct { real x; real y; };
//# type triangle = point[3];
//# logic point origin = { .x = 0.0 , .y = 0.0 };
/*# logic triangle t_iso = { [0] = origin,
# [1] = { .y = 2.0 , .x = 0.0 }
# [2] = { .x = 2.0 , .y = 0.0 }};
#*/
/*# logic point centroid(triangle t) = {
# .x = mean3(t[0].x,t[1].x,t[2].x);
# .y = mean3(t[0].y,t[1].y,t[2].y);
# };
#*/
//# type polygon = point[];
/*# logic perimeter(polygon p) =
# \sum(0,\length(p)-1,\lambda integer i;d(p[i],p[(i+1) % \length(p)])) ;
#*/
If I copy/paste this exact code into a text editor and try to run this code with the wp plugin with:
frama-c -wp -wp-rte -wp-prover alt-ergo shapes.c
I get an error:
[kernel:annot-error] shapes.c:1: Warning: unexpected token '{'
If I give up on trying to write logic/spec level declarations of struct types, but would still like to write logic/spec level expressions that instantiate structs defined in C as follows:
struct somestruct {
int x;
int y;
};
/*#
logic struct somestruct foo = { .x = 3, .y = 4 };
*/
I still get an error:
[kernel:annot-error] aggregate_err.c:7: Warning:
unsupported aggregated field construct. Ignoring global annotation
and not having a way to write particular values of structs as expressions in specifications leads to some fairly ugly specifications, so I am hoping that I am doing something wrong.
If I dig into the source of frama-C 20.0 to try to find the part of the parser-generator code for /*# type declarations, it looks like the syntax in Ex 2.2.7 is not really implemented. It looks like the syntax for type level declarations is line 799 of
frama-c-20.0-Calcium/src/kernel_internals/parsing/logic_parser.mly
(called type_spec)
And the parse rule for type level declarations of structs is:
| STRUCT exit_rt_type identifier_or_typename { LTstruct $3 }
which looks like it would support
//# type foo = struct c_struct;
but not something like what Ex 2.2.7 has as in:
//# type point = struct { real x; real y; };
Is there something else I should be doing to have better support for structs in ACSL/Frama-C? Thanks!
Not all ACSL constructions are supported by the current Frama-C implementation. With each Frama-C release comes an ACSL implementation manual, which describes the constructions that are not yet implemented. For Frama-C 20.0 Calcium, this can be found here. In this document, unsupported constructions appear in red in the relevant BNF rule. Note however that other parts of the manual are left untouched. Notably, the fact that an example is included in the implementation manual does not imply that it is expected to be successfully parsed by the current Frama-C version. In your case, these are the rules of figure 2.17 on page 57, which show that indeed records are not implemented.
As you have already discovered by yourselves, it is indeed possible to define a C struct (possibly ghost) and an ACSL type out of it. Of course, since the struct lives in the C world, its fields must have C types (ACSL types in ghost declarations is unsupported as well).
Similarly, you can simulate the absence of direct record definition by an update (the \with construction) of all the fields of an arbitrary record, as in the following example:
//# ghost struct c_s { float x; float y; };
//# type point = struct c_s;
//# axiomatic Arbitrary_point { logic point empty; }
//# logic point my_point = {{ empty \with .x = (float)1. } \with .y = (float)2.};

How to use method reference in Java 8 for Map merge?

I have following 2 forms of calling a collect operation, both return same result, but I still cannot depend fully on method references and need a lambda.
<R> R collect(Supplier<R> supplier,
BiConsumer<R,? super T> accumulator,
BiConsumer<R,R> combiner)
For this consider the following stream consisting on 100 random numbers
List<Double> dataList = new Random().doubles().limit(100).boxed()
.collect(Collectors.toList());
1) Following example uses pure lambdas
Map<Boolean, Integer> partition = dataList.stream()
.collect(() -> new ConcurrentHashMap<Boolean, Integer>(),
(map, x) ->
{
map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, (map, map2) ->
{
map2.putAll(map);
});
2) Following tries to use method references but 2nd argument still requires a lambda
Map<Boolean, Integer> partition2 = dataList.stream()
.collect(ConcurrentHashMap<Boolean, Integer>::new,
(map, x) ->
{
map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, Map::putAll);
How can I rewrite 2nd argument of collect method in java 8 to use method reference instead of a lambda for this example?
System.out.println(partition.toString());
System.out.println(partition2.toString());
{false=55, true=45}
{false=55, true=45}
A method reference is a handy tool if you have an existing method doing exactly the intended thing. If you need adaptations or additional operations, there is no special syntax for method references to support that, except, when you consider lambda expressions to be that syntax.
Of course, you can create a new method in your class doing the desired thing and create a method reference to it and that’s the right way to go when the complexity of the code raises, as then, it will get a meaningful name and become testable. But for simple code snippets, you can use lambda expressions, which are just a simpler syntax for the same result. Technically, there is no difference, except that the compiler generated method holding the lambda expression body will be marked as “synthetic”.
In your example, you can’t even use Map::putAll as merge function, as that would overwrite all existing mappings of the first map instead of merging the values.
A correct implementation would look like
Map<Boolean, Integer> partition2 = dataList.stream()
.collect(HashMap::new,
(map, x) -> map.merge(x < 0.5, 1, Integer::sum),
(m1, m2) -> m2.forEach((k, v) -> m1.merge(k, v, Integer::sum)));
but you don’t need to implement it by yourself. There are appropriate built-in collectors already offered in the Collectors class:
Map<Boolean, Long> partition2 = dataList.stream()
.collect(Collectors.partitioningBy(x -> x < 0.5, Collectors.counting()));

instance::class.java vs. instance.javaClass

Given Kotlin 1.1. For an instance of some class, instance::class.java and instance.javaClass seem to be nearly equivalent:
val i = 0
println(i::class.java) // int
println(i.javaClass) // int
println(i::class.java === i.javaClass) // true
There is a subtle difference, however:
val c1: Class<out Int> = i::class.java
val c2: Class<Int> = i.javaClass
instance.javaClass is negligibly shorter, but instance::class.java is more consistent with the corresponding usage on a type. While you can use .javaClass on some types, the result may not be what you would expect:
println(i::class.java === Int::class.java) // true
println(i.javaClass === Int.javaClass) // false
println(Int::class.java === Int.javaClass) // false
println(Int.javaClass) // class kotlin.jvm.internal.IntCompanionObject
So, I would argue that it is better to never use .javaClass for more consistency. Are there any arguments against that?
The difference in these two constructs is that, for an expression foo of static (declared or inferred) type Foo:
foo.javaClass is typed as Class<Foo>
foo::class.java is typed as Class<out Foo>
In fact, the latter is more precise, because the actual value that foo evaluates to can be an instance of not Foo itself but one of its subtypes (and it's exactly what's denoted by the covariant out Foo).
As #marstran correctly noted in the comment on the question, .javaClass once was considered to be deprecated (see the Kotlin 1.1 RC announcement) because it can break type safety (see below), but it was afterwards left as-is because it was widely used and replacing it with the alternative of ::class.java would require adding explicit unchecked casts in the code.
Also, see the comments under this answer: (link)
Please note that Int.javaClass does not denote the type of Int but instead is the Java class of the Int's companion object. Whereas Int::class.java is an unbound class reference and denotes the type. To get it with .javaClass, you need to call it on an Int instance, e.g. 1.javaClass.
Here's how exactly .javaClass can break type safety. This code compiles but breaks at runtime:
open class Foo
class Bar : Foo() {
val baz: Int = 0
}
fun main(args: Array<String>) {
val someFoo: Foo = Bar()
val anotherFoo: Foo = Foo()
val someFooProperty: KProperty1<in Foo, *> = // 'in Foo' is bad
someFoo.javaClass.kotlin.memberProperties.first()
val someValue = someFooProperty.get(anotherFoo)
}
This example uses kotlin-reflect.
That's because someFooProperty represents a property of Bar, not Foo, but since it was obtained from someFoo.javaClass (Class<Foo> then converted to KClass<Foo>) the compiler allows us to use it with the in Foo projection.

How do you get the Discriminated Union Type from a Case instance?

Given these two Discriminated Unions I'd like to get the DeclaringType from a case instance.
type SingleCaseUnion =
| One
type MultiCaseUnion =
| Two
| Three
An example for each case would be as follows:
getDiscriminatedUnionType One = typeof<SingleCaseUnion> // true
getDiscriminatedUnionType Three = typeof<MultiCaseUnion> // true
My first attempt was to get the case type and get it's base class, this works because in F# a subtype is created for each case.
MultiCaseUnion.Two.GetType().BaseType = typeof<MultiCaseUnion> // true
However, for a single case union this doesn't work because no nested types are created.
SingleCaseUnion.One.GetType().BaseType = typeof<SingleCaseUnion> // false
My second attempt, which aimed to get a more robust solution was to use the FSharp Reflection helpers.
FSharpType.GetUnionCases(unionValue.GetType()).First().DeclaringType
This does work for all cases but it has to generate UnionCaseInfo instances for each case which seems somewhat unnecessary.
Is there Something built in that I may have missed? Something like:
FSharpValue.GetUnionFromCase(SingleCaseUnion.One)
How about
open FSharp.Reflection
type FSharpType =
static member GetUnionType t =
let ownType = t.GetType()
assert FSharpType.IsUnion(ownType)
let baseType = ownType.BaseType
if baseType = typeof<System.Object> then ownType else baseType
Test:
(FSharpType.GetUnionType MultiCaseUnion.Three).Name //MultiCaseUnion
(FSharpType.GetUnionType SingleCaseUnion.One).Name //SingleCaseUnion

Resources