How to execute a function inside a String?

82 views
Skip to first unread message

JustGabe

unread,
Mar 6, 2016, 1:33:48 PM3/6/16
to HaxeFlixel


I found a tutorial that I made in Flixel and trying to do it in HaxeFlixel. Everything was running smooth until I got this error from the lines starting with "this"

private function runEvent(line:String):void
{
  if (line.substring(0,2) == "::")
  {
      // Check if the function has arguments.
    if (line.split("@")[1] != null)
        // Execute function written in string with arguments.
      this[line.split("@")[0].substring(2)](line.split("@")[1]);
    else
      this[line.split("@")[0].substring(2)]();
  }
}

What I'm trying to do is that I call the runEvent function that receives for example the String "::removeInv@Pencil" and after finding that there is an event from the first IF, it should run the function "removeInv" with the argument "Pencil", but I get these errors:

characters 9-40 : String should be Int
characters 4-8 : Array access is not allowed on PlayState

So, what is the correct way in HaxeFlixel to split a String and then execute the subString like if it were a function?

Gama11

unread,
Mar 6, 2016, 1:50:06 PM3/6/16
to HaxeFlixel
Could you provide a link to that tutorial?

JustGabe

unread,
Mar 6, 2016, 1:59:36 PM3/6/16
to HaxeFlixel
Sure, but it's REALLY outdated and made in Flixel: http://www.kcnhgames.com/blog/?p=703

Gama11

unread,
Mar 6, 2016, 2:08:49 PM3/6/16
to HaxeFlixel
I just wanted some context for that code. :)

It's not "executing a function inside a String", it's using Reflection to call a function of the current object (this). To be honest, this is really nasty code and should be avoided. If you have to translate it to have though, you'll have to use Reflect.callMethod(). Pseudocode:

Reflect.callMethod(this, line.split("@")[0].substring(2), [line.split("@")[1]]);

JustGabe

unread,
Mar 6, 2016, 2:31:33 PM3/6/16
to HaxeFlixel
I see! it works now, but if you think this is a very awful coding, how would you improve it?

Thanks a lot!

Gama11

unread,
Mar 6, 2016, 2:49:05 PM3/6/16
to haxef...@googlegroups.com
There is no reason to encode the function names into strings, you can just store references to the functions directly. That way everything stays statically typed / type-safe. The fact that the dialog array can contain either text or an event can be expressed using an ADT.

I've created a small example that you can run here: http://try.haxe.org/#3A395

class Test {
    static function main() {
        new Test();
    }
    
    function new() {
        var dialog = [
            Line("First line of the dialog"),
            Line("Next we execute a function"),
            Event(eventWithoutArguments),
            Line("Next up, we use bind() to call a function with arguments"),
            Line("see http://haxe.org/manual/lf-function-bindings.html for more info"),
            Event(eventWithArguments.bind(-3, 10)),
            Line("Dialog done!")
        ];
        runDialog(dialog);
    }
    
    function runDialog(dialog:Array<DialogEntry>) {
        for (entry in dialog) {
            switch (entry) {
                case Event(func):
                    func();

                case Line(text):
                    trace(text);
            }
        }
    }

    function eventWithoutArguments() {
        trace("No-argument-function called");
    }

    function eventWithArguments(x:Int, y:Int) {
        trace("Function called with x=" + x + " and y=" + y);
    }
}

enum DialogEntry {
    Event(func:Void->Void);
    Line(text:String);
}
Reply all
Reply to author
Forward
0 new messages