Dynamically created class with invocant constraint - raku

Official docs says that class can be built dynamically like so:
constant A := Metamodel::ClassHOW.new_type( name => 'A' );
A.^add_method('x', my method x(A:D:) { say 42 });
A.^compose;
A.new.x(); # x will be only called on instances
But what if I am building a class and don't assign it to a constant but rather store it in a var (for instance when I need to create a bunch of classes in loop) like so:
my $x = Metamodel::ClassHOW.new_type( name => 'some custom string' );
$x.^add_method('x', my method ($y:) { say $y });
$x.^compose;
But in this case I can call method x both on class ($x.x) and on instance ($x.new.x) though I want it to only be called on instances.
I tried to define method like so:
$x.^add_method('x', my method ($y:D:) { say $y });
but that produces an error:
Invalid typename 'D' in parameter declaration.
Of course I can check defindness of the value inside the method but I want some compile-time guarantees (I want to believe that type checking is done in compile time).
I tried to play with signatures and parameters but couldn't find a way to create an invocant parameter but what is more important I am not sure how to assign signature which I have in a variable to some method.

Change:
my $x = ...
to:
my constant x = my $ = ...
In full:
my constant x = my $ = Metamodel::ClassHOW.new_type( name => 'some custom string' );
x.^add_method('x', my method (x:D $y:) { say $y });
x.^compose;
x = Metamodel::ClassHOW.new_type( name => 'another custom string' );
...
I want some compile-time guarantees (I want to believe that type checking is done in compile time).
By making the constant's RHS be a variable declaration, you blend static compile-time aspects with dynamic run-time ones.
(BTW, the my before constant is just me being pedantic. A plain constant like you've used is equivalent to our constant which is less strict than my constant.)
I note the error message for a non-instance is different:
Type check failed in binding to parameter '$y';
expected type some custom string cannot be itself
At a guess that's because the usual message comes from Mu or Any and your class isn't inheriting from either of them.
I am not sure how to assign signature which I have in a variable to some method.
I'll leave that part unanswered.

The best way I can think of to produce a method with types substituted into a signature with Raku today is to use a parametric role to help out, like this:
my role Helper[::T] {
method foo(T $inv:) {}
}
my &meth = Helper.^parameterize(Int).^pun.^lookup("foo");
say &meth.signature;
Which outputs (Int $inv: *%_). Substitute Int with the type you are building.

Related

Kotlin clarification about # symbol and return postfixes

I am confused about the meaning usage of the next syntax.
What does exactly do placing the postfixes "async" and "lazy" after a "return"?
return async
return lazy
What does the "#" symbol mean here?
return#async
return#lazy
return#withContext
About the "#" symbol, does it have a special naming in Kotlin? so I can better locate all the ways to use it in the documentation?
What is the difference between adding # and not using it? so:
"return async" vs "return#async"
What does exactly do placing the postfixes "async" and "lazy" after a "return"?
This is not special syntax in Kotlin with the specific words "async" or "lazy". So it is not really a "postfix for the return keyword". After a space, what follows the return is always the value that you want to return:
return 42 returns the value 42
return async returns the value of the expression async (which is probably a variable that has been declared earlier in the code)
return async { 42 } returns the value of the expression async { 42 }.
The meaning of the expression async { 42 } here is unrelated to the return in itself. You could see the same expression assigned to a variable for instance: val deferred = async { 42 }. async is simply a library function from the kotlinx.coroutines library (it's just my guess by the way, maybe the code you've seen declares variables/functions of this name, but it's hard to tell without more context). Have a look at the doc of the async function here if you're interested.
What does the "#" symbol mean here?
The return keyword by default returns from the closest enclosing function declared with the fun keyword. Lambdas don't count, because they are not declared with fun.
Therefore, return-ing from inside a lambda will by default (without #) return from an enclosing function rather than just the "local" lambda (as opposed to what happens in Java). This is why we call them non-local returns.
Using a qualified return with a label (return#label) allows to change this default behaviour and specify what you want to return from explicitly.
See the doc about return at labels, it contains many examples.
The specific examples you gave:
return#async
return#lazy
return#withContext
would need a bit more context to understand them. But I assume that you have seen them used inside lambdas that are a parameter of async/lazy/withContext function calls. What follows the # here is called an implicit label which tells the compiler that this return is supposed to return from this lambda instead of returning from the closest enclosing fun.
Other notes
Note that the # symbol here is not an annotation like you could see elsewhere like #JvmDefault or #OptIn(...), it is instead a label reference.
Note that both a label and a return value can be combined: return#myLabel 42 returns the value 42 from the function qualified by the label myLabel.

Collection<KProperty1<I,*>> How to get the property instance

I'm currently using Reflection to inspect an element at runtime using the class.memberProperties function. The type of properties is collection<KProperty1<I, *>> so I run through each of the KProperty objects to find the one that I want by checking if the name is equal to "nameIWant", though I would much rather be able to get the instance of the property from the KProperty by using the .get() method on the property, so that then I could do a check such as:
if (property.get(receiver) is ClassIWant) {
//Do something
}
My code looks like this:
val properties = request.payload::class.memberProperties
properties.forEach { property ->
run {
if (property.name.equals("nameIWant")) {
}
}
}
So far I've been trying to use the .get() method on the KProperty1 type but it takes an argument receiver of type Nothing. I'm not able to work out what I need to pass in order to call the .get() method and get the particular instance of the property. I've also checked the documentation here: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-property1/index.html but it hasn't really helped at all.
justPassingBy is right. but the more simple way is to use:
myObj.javaClass.kotlin.memberProperties.foreach { property ->
property.get(myObj)
}
If you want to get the value of the property, cast the class into invariant type.
instance::class.memberProperties.first() // returns KProperty1<out Instance, *>
(instance::class as KClass<Instance>).memberProperties.first() // returns KProperty1<Instance, *>
If your KClass<Instance> is KClass<*>, use Any as Instance.
Why did the KProperty.call take Nothing as receiver?
Because instance::class returns KClass<out Instance>, which propagates the covariant type argument down to the property, which it becomes KProperty<out Instance, *>, which narrows down the possible method receiver to any subtype of Instance, but because we do not know which, we can not safely supply any instance of Instance, as show by the rules of variance, which here limit the generic type argument to Nothing, which means it is impossible to call the method at all.
Why is ::class designed to be covariant?
To guarantee safety. This has been an issue of great debates as it seems somewhat illogical.
If you want to know the type of the value that the property can return, use
property.returnType
It returns a KType, wich is Kotlin's version of Java's Type, which is a more generic concept of a Class (which is one of the implementations of Type).
If you need to 'convert' the KType to a KClass, you need to do the same as if you needed to convert Type to a Class, which is get the raw type of the type. Raw type is type stripped of the any generic information, yes, an erased type. The way to do this is (seemingly) more complicated (involves handling each possible KType/Type implementation) and I recommend checking for answer to this problem separately.
You will be able to reuse Java implementation (that you will surely find on your own) using:
kType.javaType.covertJavaTypeToJavaClass().kotlin // returns KClass<*>
Corrections in your question. I recommend using the proper terms if you wish to receive proper answers:
* I in your question is type of the method receiver, not the value of the property
* collection is not a type, Collection is
* property is ClassIWantis ambiguous as property.type is type of the value in the property and property::class is simply the property implementation, is is also an instanceof check, but in reflection, you need to use KClass.isSubclassOf, or what is known in Java as type.isAssignableFrom (watch the call order), which then makes your condition to be ClassIWant.isSuperclassOf(property.type.getRawType())
* instance of the property properties have values, not instances. Only classes have instances. Instances are values and values are instances (of some class), but you must still say instance representing the value of the property
You can create a KType for your ClassIWant and then check the property's returnType. It will be something like this:
val properties = request.payload::class.memberProperties
val desiredType = ClassIWant::class.createType()
properties.forEach { property ->
if (property.name == "nameIWant" && property.returnType == desiredType) {
//todo
}
}
btw you can cast your property variable to correct type and use get
val properties = request.payload::class.memberProperties
properties.forEach { property ->
val value = (property as KProperty1<Payload, *>).get(request.payload)
if (property.name == "nameIWant" && value is ClassIWant) {
//todo
}
}
prop.getter.call(obj) as String?

How can I pass property getter as a function type to another function

How can I pass property getter to a function that accepts function type?
Here is an example of what I want achieve:
class Test {
val test: String
get() = "lol"
fun testFun(func: ()->String) {
// invoke it here
}
fun callTest() {
testFun(test::get)
// error: Type mismatch: inferred type is
// KFunction1<#ParameterName Int, Char> but () -> String was expected
}
}
Is there a way?
You can reference the getter by writing ::test (or this::test).
When you write test::get, you are actually referencing the get method on String. That method takes an index and returns the character at that index.
If the property was a var and you want a reference to its setter, you can write ::test::set.
For more info on property references, see here: https://kotlinlang.org/docs/reference/reflection.html#bound-function-and-property-references-since-11
As already mentioned, you can use this::test to refer to the getter. Alternatively, if you have kotlin-reflect, you can do this::test.getter.
When you pass the field as a function, it assumes you mean the getter. As a result, if you want the setter, you have two options:
this::test::set
or
this::test.setter
The latter, just like this::test.getter requires kotlin-reflect, or the program will crash (tested locally with Kotlin 1.2.50)
You can, however, get the getter in another way. But I recommend you just stick with this::test because it's shorter.
You can do:
this::something::get
With just something::get it refers to the method inside the String class, which returns a char at an index. For reference, the method declaration:
public override fun get(index: Int): Char
If you don't mind, just use { test } (e.g. testFun { test }). This will exactly translate to your () -> String. The next best alternative is probably ::test (or this::test) as was already mentioned.
The second has probably only minor (negligible?) impact on performance. I did not test it myself, nor did I found any source which tells something regarding it. The reason why I say this, is how the byte code underneath looks like. Just due to this question I asked myself about the difference of the two: Is the property reference (::test) equivalent to a function accessing the property ({ test }) when passed as argument e.g. `() -> String`?
It seems that you are doing something wrong on logical level.
If you are overriding get method of a variable, then you can access it's value through this get method. Thus, why bother with test::get (which is totally different method, by the way, all you are doing is trying to access char from string), when you can just access variable by it's name?

Indirect initialization of memory via UnsafeMutablePointer types

I encountered an unfamiliar pattern of initialization from Objective-C that I'm struggling to replicate in Swift.
Objective-C
In the example code, they defined a C struct such as this (abbreviated, original here):
struct AQPlayerState {
AudioFileID mAudioFile;
}
Here's an example that uses AQPlayerState:
AQPlayerState aqData; // 1
OSStattus result =
AudioFileOpenURL(
audioFileURL,
fsRdPerm,
0,
&aqData.mAudioFile // 2
);
The key takeaway from above is that aqData currently has uninitialized properties, and AudioFileOpenURL is initializing aqData.mAudioFile on it's behalf.
Swift
I'm trying to replicate this behaviour in Swift. Here's what I've tried so far:
Models:
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Foo {
var person: Person?
}
My idea was to replicate the Objective-C code by passing a reference of Foo.person into a function that would instantiate it on it's behalf.
Initialization Function:
func initializeWithBob(_ ptr: UnsafeMutablePointer<Person?>) {
ptr.pointee = Person(name: "Bob")
}
initializeWithBob takes a pointer to an address for a Person? type and initializes it with a Person(name: "Bob") object.
Here's my test code:
let foo = Foo()
let ptr = UnsafeMutablePointer<Person?>.allocate(capacity: 1)
ptr.initialize(to: foo.person)
defer {
ptr.deinitialize()
ptr.deallocate(capacity: 1)
}
initializeWithBob(ptr)
print(foo.person) // outputs nil
initializeWithBob failed to "install" an instance of type Person in my Foo instance. I presume some of my assumptions are wrong. Looking for help in correcting my assumptions and understanding of this situation.
Thanks in advance!
You can achieve what you are looking for via withUnsafeMutablePointer(to:_:) like so:
let foo = Foo()
withUnsafeMutablePointer(to: &foo.person) { (ptr) -> Void in
initializeWithBob(ptr)
}
print(foo.person!.name) // outputs Bob
However, I wouldn't recommend this approach. IMHO it makes more sense to wrap the APIs you are working with in a C function that you can make 'nice' to call from Swift. The problem with your current approach is that this type of Swift is hard to read for Swift developers and also hard to read for Audio Toolbox developers.
#kelvinlau Is this what you were thinking of trying to achieve?
func initializeWithBob(_ ptr: UnsafeMutablePointer<Foo>) {
ptr.pointee.person = Person(name: "Bob")
}
let foo = Foo()
let ptr = UnsafeMutablePointer<Foo>.allocate(capacity: 1)
ptr.initialize(to: foo)
initializeWithBob(ptr)
print(foo.person?.name ?? "nil")
ptr.deinitialize()
ptr.deallocate(capacity: 1)
print(foo.person?.name ?? "nil")
The code pattern you have in Objective-C is for out parameters, that is parameters which return a value, or in out parameters, that is parameters which both pass a value in and return one. Objective-C does not directly support these so pointers are used to produce the semantics.
Swift has in out parameters indicated by the keyword inout in the function declaration. Within the function an assignment to an inout parameters effectively assigns a value to the variable that was passed as the argument. At the function call site the variable must be prefixed by & to indicate it is the variable itself and not its value which is effectively being passed.
Keeping your Person and Foo as is your function becomes:
func initializeWithBob(_ ptr: inout Person?)
{
ptr = Person(name: "Bob")
}
and it may be used, for example, like:
var example = Foo()
initializeWithBob(&example.person)
Using inout in Swift is better than trying to build the same semantics using pointers.
HTH
Note: You can skip this unless you are curious
"Effectively" was used a few times above. Typically out parameters are implemented by the parameter passing method call-by-result, while in out use call-by-value-result. Using either of these methods the returned value is only assigned to the passed variable at the point the function returns.
Another parameter passing method is call-by-reference, which is similar to call-by-value-result except that each and every assignment to the parameter within the function is immediately made to passed variable. This means changes to the passed variable may be visible before the function returns.
Swift by design does not specify whether its inout uses call-by-value-result or call-by-reference. So rather than specify the exact semantics in the answer "effectively" is used.

Specifying a function with templates that takes and returns an arbitrary class

I'm interested in defining a function that given a class variable, generates and a new instance of the class object with a randomly selected member attribute mutated.
Context: Consider an instance, circle1, of some class, Circle, has attributes color and radius. These attributes are assigned values of red and 5, respectively. The function in question, mutate, must accept circle1 as an argument, but reject non-class arguments.
For other data types, templates provide an answer in this context. That is, templates may be used to specify generic instances of functions that can accept arguments of multiple types.
How can a generic function that accepts (and returns) an instance of any class be defined using templates?
In general, if you need to restrict what a template can take, you use template constraints. e.g.
import std.traits : isIntegral;
auto foo(T)(T t)
if(isIntegeral!T)
{
...
}
or
import std.functional : binaryFun;
auto foo(alias pred, T, U)(T t, U u)
if(is(typeof(binaryFun!pred(t, u.bar())) == bool)
{
...
}
As long the condition can be checked at compile time, you can test pretty much anything. And it can be used for function overloading as well (e.g. std.algorithm.searching.find has quite a few overloads all of which are differentiated by template constraint). The built-in __traits, the eponymous templates in std.traits, and is expressions provide quite a few tools for testing stuff at compile time and then using that information in template constraints or static if conditions.
If you specifically want to test whether something is a class, then use an is expression with == class. e.g.
auto foo(T)(T t)
if(is(T == class))
{
...
}
In general though, you'll probably want to use more specific conditions such as __traits(compiles, MyType result = t.foo(22)) or is(typeof(t.foo(22)) == MyType). So, you could have something like
auto mutate(T)(T t)
if(is(T == class) &&
__traits(compiles, t.color = red) &&
__traits(compiles, t.radius = 5))
{
...
}
If the condition is something that you want to reuse, then it can make sense to create an eponymous template - which is what's done in Phobos in places like std.range.primitives and std.range.traits. For instance, to test for an input range, std.range.primitives.isInputRange looks something like
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r = R.init; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}
Then code that requires an input range can use that. So, lots of functions in Phobos have stuff like
auto foo(R)(R range)
if(isInputRange!R)
{
...
}
A more concrete example would be this overload of find:
InputRange find(alias pred = "a == b", InputRange, Element)
(InputRange haystack, Element needle)
if(isInputRange!InputRange &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{
...
}
Ali Çehreli's book, Programming in D, has several relevant chapters, including:
http://ddili.org/ders/d.en/templates.html
http://ddili.org/ders/d.en/cond_comp.html
http://ddili.org/ders/d.en/is_expr.html
http://ddili.org/ders/d.en/templates_more.html