calling super() from an actionscript constructor with varargs - actionscript-3

If a constructor takes its parameters as a vararg (...) it seems to be impossible to create a subclass that will just pass on that vararg to the superclass.
There is a related question with fix for this same situation for normal functions: Wrapping a Vararg Method in ActionScipt but I cannot get that to work with a super call.
base class:
public class Bla
{
public function Bla(...rest)
{
trace(rest[0]); // trace the first parameter
}
}
subclass:
public class Blie extends Bla
{
public function Blie(...rest)
{
// this is not working, it will
// pass an array containing all
// parameters as the first parameters
super(rest);
}
}
if I now call
var b1 = new Bla('d', 'e');
var b2 = new Blie('a', 'b', 'c');
I get the output
d
a,b,c
And I want it to print out:
d
a
Aside from actually moving the handling of the parameters to the subclass or shifting it off to a separate initializer method, does anyone know how to get the super call right?

There's unfortunately no way to call the super constructor with ... args. If you remove the super() call, it will be called by the compiler (with no arguments). arguments is also not accessible from constructors.
If you can change the method signatures, you modify the arguments to accept an Array rather than ... args. Otherwise, as you mentioned, you could move it into an initializer method.

You may use a statement like this:
override public function doSomething(arg1:Object, ...args):void {
switch(args.length) {
case 0: super.doSomething(arg1); return;
case 1: super.doSomething(arg1, args[0]); return;
case 2: super.doSomething(arg1, args[0], args[1]); return;
}
}

Related

Run a 'constructor' or function, after class fields initialized, in a sane way?

I'd like to use ES6 public class fields:
class Superclass {
constructor() {
// would like to write modular code that applies to all
// subclasses here, or similarly somewhere in Superclass
this.example++; // does NOT WORK (not intialized)
//e.g. doStuffWith(this.fieldTemplates)
}
}
class Subclass extends Superclass {
example = 0
static fieldTemplates = [
Foo,
function() {this.example++},
etc
]
}
Problem:
ES6 public fields are NOT initialized before the constructors, only before the current constructor. For example, when calling super(), any child field will not yet have been defined, like this.example will not yet exist. Static fields will have already been defined. So for example if one were to execute the code function(){this.example++} with .bind as appropriate, called from the superclass constructor, it would fail.
Workaround:
One workaround would be to put all initialization logic after all ES6 public classes have been properly initialized. For example:
class Subclass extends Superclass {
example = 0
lateConstructor = (function(){
this.example++; // works fine
}).bind(this)()
}
What's the solution?
However, this would involve rewriting every single class. I would like something like this by just defining it in the Superclass.constructor, something magic like Object.defineProperty(this, 'lateConstructor', {some magic}) (Object.defineProperty is allegedly internally how es6 static fields are defined, but I see no such explanation how to achieve this programatically in say the mozilla docs; after using Object.getOwnPropertyDescriptor to inspect my above immediately-.binded-and-evaluated cludge I'm inclined to believe there is no way to define a property descriptor as a thunk; the definition is probably executed after returning from super(), that is probably immediately evaluated and assigned to the class like let exampleValue = eval(...); Object.defineProperty(..{value:exampleValue})). Alternatively I could do something horrible like do setTimeout(this.lateConstructor,0) in the Superclass.constructor but that would break many things and not compose well.
I could perhaps try to just use a hierarchy of Objects everywhere instead, but is there some way to implement some global logic for all subclasses in the parent class? Besides making everything lazy with getters? Thanks for any insight.
References:
Run additional action after constructor -- (problems: this requires wrapping all subclasses)
Can I create a thunk to run after the constructor?
No, that is not possible.
How to run code after class fields are initialized, in a sane way?
Put the code in the constructor of the class that defines those fields.
Is there some way to implement some global logic for all subclasses in the parent class?
Yes: define a method. The subclass can call it from its constructor.
Just thought of a workaround (that is hierarchically composable). To answer my own question, in a somewhat unfulfilling way (people should feel free to post better solutions):
// The following illustrates a way to ensure all public class fields have been defined and initialized
// prior to running 'constructor' code. This is achieved by never calling new directly, but instead just
// running Someclass.make(...). All constructor code is instead written in an init(...) function.
class Superclass {
init(opts) { // 'constructor'
this.toRun(); // custom constructor logic example
}
static make() { // the magic that makes everything work
var R = new this();
R.init(...arguments);
return R;
}
}
class Subclass extends Superclass {
subclassValue = 0 // custom public class field example
init(toAdd, opts) { // 'constructor'
// custom constructor logic example
this.subclassValue += toAdd; // may use THIS before super.init
super.init(opts);
// may do stuff afterwards
}
toRun() { // custom public class method example
console.log('.subclassValue = ', this.subclassValue);
}
}
Demo:
> var obj = Subclass.make(1, {});
.subclassValue = 1
> console.log(obj);
Subclass {
subclassValue: 1
__proto__: Superclass
}

Pass Variables As Reference AS3

I have a function which has arguments that will modify multiple variables that are global. And I want the arguments to be reference arguments, so they can modify multiple global variables with the same lines of code that are modifying the arguments.
example(psuedocode):
function random(a:number, b:number, c:number):void{
a = RNG(20);
b = RNG(25);
c = RNG(30);
}
there will be two different variables passed in through a, b and c, these are global, but a, b and c are not. The goal is to not have to have identical lines of code for both separate sets of variables to set the RNG numbers.
Edit: So I suppose more explanation is in order I will probably just try to research making a wrapper or other object to add all the variables to, but I just didn't know what type of object to make and how to make it. I admit I was just being a little bit lazy in a little bit too complex creative way.
I have two sets of global variables that I want to pass into this function and set them equal to the same range of RNG as the corresponding ones in each set. The way I'm trying to do this without repeating "a = RNG(20);" twice for each one is by passing the global variables into the function as arguments, but the arguments are the variables that are having the RNG set to them. The only way this can work is if the variables are passed to the function as reference so that setting the RNG to the arguments will change the global variables.
There are two types of data in AS3:
Plain data: Boolean, String, Number, int, uint — always passed as values.
Objects: Object, Array and literally everything else — always passed as a pointer/reference rather than through copy/clone.
There's no trick, like in C/C++ there is, to pass some plain variable as a pointer to let a method modify the original and only value.
That said, there are two ways around.
Solution №1: you can pass variables indirectly, in pairs like container → variable name.
function doIt(A:Object, a:String):void
{
A[a] = RNG(20);
}
Solution №2: devise a custom wrapper class to cross the border between plain and object data.
Implementation:
package
{
public class Oint
{
public var data:int;
// Class constructor.
public function Oint(value:int = 0)
{
data = value;
}
// There's always nice to have a interface methods,
// rather than member or getter/setter, because
// you can actually link to read/write methods.
public function read():int
{
return data;
}
public function write(value:int):void
{
data = value;
}
// With this you can use Oint variables in math expressions.
public function valueOf():Object
{
return data;
}
// With this you can trace Oint variables and see their values.
public function toString():String
{
return data.toString();
}
}
}
Usage:
function random(a:Oint, b:Oint, c:Oint):void
{
a.data = RNG(20);
b.data = RNG(25);
c.data = RNG(30);
}

when to use an inline function in Kotlin?

I know that an inline function will maybe improve performance & cause the generated code to grow, but I'm not sure when it is correct to use one.
lock(l) { foo() }
Instead of creating a function object for the parameter and generating a call, the compiler could emit the following code. (Source)
l.lock()
try {
foo()
}
finally {
l.unlock()
}
but I found that there is no function object created by kotlin for a non-inline function. why?
/**non-inline function**/
fun lock(lock: Lock, block: () -> Unit) {
lock.lock();
try {
block();
} finally {
lock.unlock();
}
}
Let's say you create a higher order function that takes a lambda of type () -> Unit (no parameters, no return value), and executes it like so:
fun nonInlined(block: () -> Unit) {
println("before")
block()
println("after")
}
In Java parlance, this will translate to something like this (simplified!):
public void nonInlined(Function block) {
System.out.println("before");
block.invoke();
System.out.println("after");
}
And when you call it from Kotlin...
nonInlined {
println("do something here")
}
Under the hood, an instance of Function will be created here, that wraps the code inside the lambda (again, this is simplified):
nonInlined(new Function() {
#Override
public void invoke() {
System.out.println("do something here");
}
});
So basically, calling this function and passing a lambda to it will always create an instance of a Function object.
On the other hand, if you use the inline keyword:
inline fun inlined(block: () -> Unit) {
println("before")
block()
println("after")
}
When you call it like this:
inlined {
println("do something here")
}
No Function instance will be created, instead, the code around the invocation of block inside the inlined function will be copied to the call site, so you'll get something like this in the bytecode:
System.out.println("before");
System.out.println("do something here");
System.out.println("after");
In this case, no new instances are created.
Let me add: When not to use inline:
If you have a simple function that doesn't accept other functions as an argument, it does not make sense to inline them. IntelliJ will warn you:
Expected performance impact of inlining '...' is insignificant.
Inlining works best for functions with parameters of functional types
Even if you have a function "with parameters of functional types", you may encounter the compiler telling you that inlining does not work. Consider this example:
inline fun calculateNoInline(param: Int, operation: IntMapper): Int {
val o = operation //compiler does not like this
return o(param)
}
This code won't compile, yielding the error:
Illegal usage of inline-parameter 'operation' in '...'. Add 'noinline' modifier to the parameter declaration.
The reason is that the compiler is unable to inline this code, particularly the operation parameter. If operation is not wrapped in an object (which would be the result of applying inline), how can it be assigned to a variable at all? In this case, the compiler suggests making the argument noinline. Having an inline function with a single noinline function does not make any sense, don't do that. However, if there are multiple parameters of functional types, consider inlining some of them if required.
So here are some suggested rules:
You can inline when all functional type parameters are called directly or passed to other inline function
You should inline when ↑ is the case.
You cannot inline when function parameter is being assigned to a variable inside the function
You should consider inlining if at least one of your functional type parameters can be inlined, use noinline for the others.
You should not inline huge functions, think about generated byte code. It will be copied to all places the function is called from.
Another use case is reified type parameters, which require you to use inline. Read here.
Use inline for preventing object creation
Lambdas are converted to classes
In Kotlin/JVM, function types (lambdas) are converted to anonymous/regular classes that extend the interface Function. Consider the following function:
fun doSomethingElse(lambda: () -> Unit) {
println("Doing something else")
lambda()
}
The function above, after compilation will look like following:
public static final void doSomethingElse(Function0 lambda) {
System.out.println("Doing something else");
lambda.invoke();
}
The function type () -> Unit is converted to the interface Function0.
Now let's see what happens when we call this function from some other function:
fun doSomething() {
println("Before lambda")
doSomethingElse {
println("Inside lambda")
}
println("After lambda")
}
Problem: objects
The compiler replaces the lambda with an anonymous object of Function type:
public static final void doSomething() {
System.out.println("Before lambda");
doSomethingElse(new Function() {
public final void invoke() {
System.out.println("Inside lambda");
}
});
System.out.println("After lambda");
}
The problem here is that, if you call this function in a loop thousands of times, thousands of objects will be created and garbage collected. This affects performance.
Solution: inline
By adding the inline keyword before the function, we can tell the compiler to copy that function's code at call-site, without creating the objects:
inline fun doSomethingElse(lambda: () -> Unit) {
println("Doing something else")
lambda()
}
This results in the copying of the code of the inline function as well as the code of the lambda() at the call-site:
public static final void doSomething() {
System.out.println("Before lambda");
System.out.println("Doing something else");
System.out.println("Inside lambda");
System.out.println("After lambda");
}
This doubles the speed of the execution, if you compare with/without inline keyword with a million repetitions in a for loop. So, the functions that take other functions as arguments are faster when they are inlined.
Use inline for preventing variable capturing
When you use the local variables inside the lambda, it is called variable capturing(closure):
fun doSomething() {
val greetings = "Hello" // Local variable
doSomethingElse {
println("$greetings from lambda") // Variable capture
}
}
If our doSomethingElse() function here is not inline, the captured variables are passed to the lambda via the constructor while creating the anonymous object that we saw earlier:
public static final void doSomething() {
String greetings = "Hello";
doSomethingElse(new Function(greetings) {
public final void invoke() {
System.out.println(this.$greetings + " from lambda");
}
});
}
If you have many local variables used inside the lambda or calling the lambda in a loop, passing every local variable through the constructor causes the extra memory overhead. Using the inline function in this case helps a lot, since the variable is directly used at the call-site.
So, as you can see from the two examples above, the big chunk of performance benefit of inline functions is achieved when the functions take other functions as arguments. This is when the inline functions are most beneficial and worth using. There is no need to inline other general functions because the JIT compiler already makes them inline under the hood, whenever it feels necessary.
Use inline for better control flow
Since non-inline function type is converted to a class, we can't write the return statement inside the lambda:
fun doSomething() {
doSomethingElse {
return // Error: return is not allowed here
}
}
This is known as non-local return because it's not local to the calling function doSomething(). The reason for not allowing the non-local return is that the return statement exists in another class (in the anonymous class shown previously). Making the doSomethingElse() function inline solves this problem and we are allowed to use non-local returns because then the return statement is copied inside the calling function.
Use inline for reified type parameters
While using generics in Kotlin, we can work with the value of type T. But we can't work with the type directly, we get the error Cannot use 'T' as reified type parameter. Use a class instead:
fun <T> doSomething(someValue: T) {
println("Doing something with value: $someValue") // OK
println("Doing something with type: ${T::class.simpleName}") // Error
}
This is because the type argument that we pass to the function is erased at runtime. So, we cannot possibly know exactly which type we are dealing with.
Using an inline function along with the reified type parameter solves this problem:
inline fun <reified T> doSomething(someValue: T) {
println("Doing something with value: $someValue") // OK
println("Doing something with type: ${T::class.simpleName}") // OK
}
Inlining causes the actual type argument to be copied in place of T. So, for example, the T::class.simpleName becomes String::class.simpleName, when you call the function like doSomething("Some String"). The reified keyword can only be used with inline functions.
Avoid inline when calls are repetitive
Let's say we have the following function that is called repetitively at different abstraction levels:
inline fun doSomething() {
println("Doing something")
}
First abstraction level
inline fun doSomethingAgain() {
doSomething()
doSomething()
}
Results in:
public static final void doSomethingAgain() {
System.out.println("Doing something");
System.out.println("Doing something");
}
At first abstraction level, the code grows at: 21 = 2 lines.
Second abstraction level
inline fun doSomethingAgainAndAgain() {
doSomethingAgain()
doSomethingAgain()
}
Results in:
public static final void doSomethingAgainAndAgain() {
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
}
At second abstraction level, the code grows at: 22 = 4 lines.
Third abstraction level
inline fun doSomethingAgainAndAgainAndAgain() {
doSomethingAgainAndAgain()
doSomethingAgainAndAgain()
}
Results in:
public static final void doSomethingAgainAndAgainAndAgain() {
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
System.out.println("Doing something");
}
At third abstraction level, the code grows at: 23 = 8 lines.
Similarly, at the fourth abstraction level, the code grows at 24 = 16 lines and so on.
The number 2 is the number of times the function is called at each abstraction level. As you can see the code grows exponentially not only at the last level but also at every level, so that's 16 + 8 + 4 + 2 lines. I have shown only 2 calls and 3 abstraction levels here to keep it concise but imagine how much code will be generated for more calls and more abstraction levels. This increases the size of your app. This is another reason why you shouldn't inline each and every function in your app.
Avoid inline in recursive cycles
Avoid using the inline function for recursive cycles of function calls as shown in the following code:
// Don't use inline for such recursive cycles
inline fun doFirstThing() { doSecondThing() }
inline fun doSecondThing() { doThirdThing() }
inline fun doThirdThing() { doFirstThing() }
This will result in a never ending cycle of the functions copying the code. The compiler gives you an error: The 'yourFunction()' invocation is a part of inline cycle.
Can't use inline when hiding implementation
The public inline functions cannot access private functions, so they cannot be used for implementation hiding:
inline fun doSomething() {
doItPrivately() // Error
}
private fun doItPrivately() { }
In the inline function shown above, accessing the private function doItPrivately() gives an error: Public-API inline function cannot access non-public API fun.
Checking the generated code
Now, about the second part of your question:
but I found that there is no function object created by kotlin for a
non-inline function. why?
The Function object is indeed created. To see the created Function object, you need to actually call your lock() function inside the main() function as follows:
fun main() {
lock { println("Inside the block()") }
}
Generated class
The generated Function class doesn't reflect in the decompiled Java code. You need to directly look into the bytecode. Look for the line starting with:
final class your/package/YourFilenameKt$main$1 extends Lambda implements Function0 { }
This is the class that is generated by the compiler for the function type that is passed to the lock() function. The main$1 is the name of the class that is created for your block() function. Sometimes the class is anonymous as shown in the example in the first section.
Generated object
In the bytecode, look for the line starting with:
GETSTATIC your/package/YourFilenameKt$main$1.INSTANCE
INSTANCE is the object that is created for the class mentioned above. The created object is a singleton, hence the name INSTANCE.
That's it! Hope that provides useful insight into inline functions.
Higher-order functions are very helpful and they can really improve the reusability of code. However, one of the biggest concerns about using them is efficiency. Lambda expressions are compiled to classes (often anonymous classes), and object creation in Java is a heavy operation. We can still use higher-order functions in an effective way, while keeping all the benefits, by making functions inline.
here comes the inline function into picture
When a function is marked as inline, during code compilation the compiler will replace all the function calls with the actual body of the function. Also, lambda expressions provided as arguments are replaced with their actual body. They will not be treated as functions, but as actual code.
In short:- Inline-->rather than being called ,they are replaced by the function's body code at compile time...
In Kotlin, using a function as a parameter of another function (so called higher-order functions) feels more natural than in Java.
Using lambdas has some disadvantages, though. Since they’re anonymous classes (and therefore, objects), they need memory (and might even add to the overall method count of your app).
To avoid this, we can inline our methods.
fun notInlined(getString: () -> String?) = println(getString())
inline fun inlined(getString: () -> String?) = println(getString())
From the above example:- These two functions do exactly the same thing - printing the result of the getString function. One is inlined and one is not.
If you’d check the decompiled java code, you would see that the methods are completely identical. That’s because the inline keyword is an instruction to the compiler to copy the code into the call-site.
However, if we are passing any function type to another function like below:
//Compile time error… Illegal usage of inline function type ftOne...
inline fun Int.doSomething(y: Int, ftOne: Int.(Int) -> Int, ftTwo: (Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/
}
To solve that, we can rewrite our function as below:
inline fun Int.doSomething(y: Int, noinline ftOne: Int.(Int) -> Int, ftTwo: (Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/}
Suppose we have a higher order function like below:
inline fun Int.doSomething(y: Int, noinline ftOne: Int.(Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/}
Here, the compiler will tell us to not use the inline keyword when there is only one lambda parameter and we are passing it to another function. So, we can rewrite above function as below:
fun Int.doSomething(y: Int, ftOne: Int.(Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/
}
Note:-we had to remove the keyword noinline as well because it can be used only for inline functions!
Suppose we have function like this -->
fun intercept() {
// ...
val start = SystemClock.elapsedRealtime()
val result = doSomethingWeWantToMeasure()
val duration = SystemClock.elapsedRealtime() - start
log(duration)
// ...}
This works fine but the meat of the function’s logic is polluted with measurement code making it harder for your colleagues to work what’s going on. :)
Here’s how an inline function can help this code:
fun intercept() {
// ...
val result = measure { doSomethingWeWantToMeasure() }
// ...
}
}
inline fun <T> measure(action: () -> T) {
val start = SystemClock.elapsedRealtime()
val result = action()
val duration = SystemClock.elapsedRealtime() - start
log(duration)
return result
}
Now I can concentrate on reading what the intercept() function’s main intention is without skipping over lines of measurement code. We also benefit from the option of reusing that code in other places where we want to
inline allows you to call a function with a lambda argument within a closure ({ ... }) rather than passing the lambda like measure(myLamda)
When is this useful?
The inline keyword is useful for functions that accept other functions, or lambdas, as arguments.
Without the inline keyword on a function, that function's lambda argument gets converted at compile time to an instance of a Function interface with a single method called invoke(), and the code in the lambda is executed by calling invoke() on that Function instance inside the function body.
With the inline keyword on a function, that compile time conversion never happens. Instead, the body of the inline function gets inserted at its call site and its code is executed without the overhead of creating a function instance.
Hmmm? Example in android -->
Let's say we have a function in an activity router class to start an activity and apply some extras
fun startActivity(context: Context,
activity: Class<*>,
applyExtras: (intent: Intent) -> Unit) {
val intent = Intent(context, activity)
applyExtras(intent)
context.startActivity(intent)
}
This function creates an intent, applies some extras by calling the applyExtras function argument, and starts the activity.
If we look at the compiled bytecode and decompile it to Java, this looks something like:
void startActivity(Context context,
Class activity,
Function1 applyExtras) {
Intent intent = new Intent(context, activity);
applyExtras.invoke(intent);
context.startActivity(intent);
}
Let's say we call this from a click listener in an activity:
override fun onClick(v: View) {
router.startActivity(this, SomeActivity::class.java) { intent ->
intent.putExtra("key1", "value1")
intent.putExtra("key2", 5)
}
}
The decompiled bytecode for this click listener would then look like something like this:
#Override void onClick(View v) {
router.startActivity(this, SomeActivity.class, new Function1() {
#Override void invoke(Intent intent) {
intent.putExtra("key1", "value1");
intent.putExtra("key2", 5);
}
}
}
A new instance of Function1 gets created every time the click listener is triggered. This works fine, but it's not ideal!
Now let's just add inline to our activity router method:
inline fun startActivity(context: Context,
activity: Class<*>,
applyExtras: (intent: Intent) -> Unit) {
val intent = Intent(context, activity)
applyExtras(intent)
context.startActivity(intent)
}
Without changing our click listener code at all, we're now able to avoid the creation of that Function1 instance. The Java equivalent of the click listener code would now look something like:
#Override void onClick(View v) {
Intent intent = new Intent(context, SomeActivity.class);
intent.putExtra("key1", "value1");
intent.putExtra("key2", 5);
context.startActivity(intent);
}
Thats it.. :)
To "inline" a function basically means to copy a function's body and paste it at the function's call site. This happens at compile time.
The most important case when we use the inline modifier is when we define util-like functions with parameter functions. Collection or string processing (like filter, map or joinToString) or just standalone functions are a perfect example.
This is why the inline modifier is mostly an important optimization for library developers. They should know how it works and what are its improvements and costs. We should use the inline modifier in our projects when we define our own util functions with function type parameters.
If we don’t have function type parameter, reified type parameter, and we don’t need non-local return, then we most likely shouldn’t use the inline modifier. This is why we will have a warning on Android Studio or IDEA IntelliJ.
Also, there is a code size problem. Inlining a large function could dramatically increase the size of the bytecode because it's copied to every call site. In such cases, you can refactor the function and extract code to regular functions.
One simple case where you might want one is when you create a util function that takes in a suspend block. Consider this.
fun timer(block: () -> Unit) {
// stuff
block()
//stuff
}
fun logic() { }
suspend fun asyncLogic() { }
fun main() {
timer { logic() }
// This is an error
timer { asyncLogic() }
}
In this case, our timer won't accept suspend functions. To solve it, you might be tempted to make it suspend as well
suspend fun timer(block: suspend () -> Unit) {
// stuff
block()
// stuff
}
But then it can only be used from coroutines/suspend functions itself. Then you'll end up making an async version and a non-async version of these utils. The problem goes away if you make it inline.
inline fun timer(block: () -> Unit) {
// stuff
block()
// stuff
}
fun main() {
// timer can be used from anywhere now
timer { logic() }
launch {
timer { asyncLogic() }
}
}
Here is a kotlin playground with the error state. Make the timer inline to solve it.
fun higherOrder(lambda:():Unit){
//invoking lambda
lambda()
}
//Normal function calling higher-order without inline
fun callingHigerOrder() {
higherOrder()
//Here an object will be created for the lambda inside the higher-order function
}
//Normal function calling higher-order with inline
fun callingHigerOrder() {
higherOrder()
//Here there will be no object created and the contents of the lambda will be called directly into this calling function.
}
use inline if you want to avoid object creation at the calling side.
So when using inline, as we understood lambda will be the part of calling function incase if there is a return call inside the lambda block then whole calling function will get returned this is called non-local return.
To avoid non-local return use cross-inline before lambda block in the higher-order function.

How do I determine the number of arguments a function takes in Haxe?

How can I determine the number of arguments a function takes in Haxe?
I've looked at the Reflect and Type APIs without success. In AS3 and JavaScript, you can do Function#length. Similar reflective abilities are available for most, if not all, of the other Haxe targets. Combined with Haxe's detailed type system, there must be a way to determine a function's number of argument that I'm overlooking.
I ended up going the macro route and here's what I came up with.
import haxe.macro.Context;
import haxe.macro.Type;
import haxe.macro.Expr;
class Main {
static function main() {
function test1(a, b, c) {}
function test2() {}
trace(numberOfArgs(test1)); // 3
trace(numberOfArgs(test2)); // 0
trace(numberOfArgs(function test3(a, b) {})); // 2
trace(numberOfArgs('test')); // null
}
macro static function numberOfArgs(f:Expr):ExprOf<Null<Int>> {
var fType:Type = Context.typeof(f);
if (Reflect.hasField(fType, 'args')) {
var fArgs:Array<Dynamic> = Reflect.field(fType, 'args');
return macro $v{fArgs[0].length};
} else {
return macro null;
}
}
}
If these functions are members of a class that you can get run time type information for, then you could add the #:rtti annotation to the class and look up those fields in the RTTI structure. See: http://haxe.org/manual/cr-rtti-structure.html
In particular CFunction takes a list of arguments and the length of that would be what you want, and that will be in the RTTI. Something like:
#:rtti
class Main {
public static function main():Void {
var rtti = haxe.rtti.Rtti.getRtti(Main);
trace(rtti); // Search in rtti->fields for foo
}
public function foo(a:Int, b:Int, c:Float, d:String):Void {
}
}
The best solution depends on your use-case though. It could also be possible to write a macro to get just the number of parameters at compile time.

Constructor being called for no reason

I got this class, let's call it: Klass.
The class Klass has a parameter for its constructor that is an array with a default value of null.
I create an object of the class Klass inside another class, lets call it: "MotherClass".
Now is when it gets weird, after I instance the object Klass, the constructor of Klass gets called again, just right after the constructor of the MotherClass ends (I placed a breakpoint and I followed step by step), with null constructor parameters.
The thing is, I don't have the stack trace of anything that is calling the constructor of Klass for the second time, no clue what could be calling that constructor again...
Any ideas?
Thanks.
(Klass implements an interface, and I'm making an instance using an array, not sure if that is affecting anything)
added code as requested:
this is the class MotherKlass:
public class Unit extends EntityVO{
public function Unit(level:int = 1)
{
//init vars and stuff
//...
//
initLevelData();
applyLevel = level;
}
private function initLevelData():void {
levelData[1] = [500, [[Spawn, this.entityToSpawn.type, this.entityToSpawn.level, 120]], "unit_level1"];
levelData[2] = [1000, [[Spawn, this.entityToSpawn.type, this.entityToSpawn.level, 90]], "unit_level2"];
levelData[3] = [2000, [[Spawn, this.entityToSpawn.type, this.entityToSpawn.level, 80]], "unit_level3"];
levelData[4] = [5000, [[Spawn, this.entityToSpawn.type, this.entityToSpawn.level, 60]], "unit_level4"];
}
override public function set applyLevel(level:int):void {
power = power / maxPower * levelData[level][0];
maxPower = levelData[level][0];
behavior = levelData[level][1];
for (var i:int = 0; i < behavior.length; i ++){
_behaviorSteps[i] = new behavior[i][0](behavior[i].slice(1));
_behaviorReqs.push(_behaviorSteps[i].req);
}
}
}
}
}
and this is Klass:
public class Spawn {
public class Spawn implements IBehavior
{
private var _entityType:String;
private var _entityLevel:int;
private var _spawnRate:int;
public function Spawn(params:Array = null){
//had to put the if because of the second weird call to the constructor with null
if(params){
_entityType = params[0];
_entityLevel = params[1];
_spawnRate = params[2];
}
}
}
}
}
Ok, this is what appears to be happening:
You have a setter for applyLevel which is overriding the super class' setter. I think your super class setter is also getting executed. Some observations that lead me to this conclusion:
your setter method overrides the super class method, but no where does it do super.applyLevel = level. This means that in the super class, the storage variable that should be keeping the level value is uninitialized. An uninitialized integer in Actionscript defaults to 0.
you mention that the second invocation of Spawn's constructor has no parameters. This occurs because your array of levelData starts out at index 1. So index 0 of this array is null.
so the super class version of the applyLevel setter method is passing in the null element from above.
I think these facts are 100% correct.
What's not clear to me is who is calling the super class' version of applyLevel Perhaps the super class (EntityVO) is doing that in it's constructor ... Hopefully this should be enough to point you in the right direction.
I'm receiving an instance of the class Unit throught Cirrus, and using RegisterClassAlias to deserialize the object. When I do that, seems like an instance of Spawn must be automatically instantiated for some reason. That is why you cant pass ojbects without default arguments. In this case, it throws an error because I'm using (params[0]) the argument that is null. I use Cirrus in other parts of my code, and it works ok because there are all ints and strings in their parameters constructors.