module CallMethod { /** * This is a class with a method and a function. */ const Example(String text) { @Override String toString() { // <-- this is a method return $"This is an example with text={text}"; } static Int oneMoreThan(Int n) { // <-- this is a function return n+1; } } void run() { @Inject Console console; Example example = new Example("hello!"); String methodResult = example.toString(); // <-- call a method console.print($"Result from calling a method: {methodResult.quoted()}"); // Int funcResult = example.oneMoreThan(12); // <-- compiler error Int funcResult = Example.oneMoreThan(12); // <-- call a function console.print($"Results from calling a function: {funcResult}"); // methods and functions are also objects that can be manipulated; // note that "function String()" === "Function<<>, >" Method, > method = Example.toString; function String() func = method.bindTarget(example); console.print($"Calling a bound method: {func().quoted()}"); // by default, a method with target T converts to a function taking a T; // Ecstasy refers to this as "Bjarning" (because C++ takes "this" as a param) val func2 = Example.toString; // <-- type: function String() console.print($"Calling a Bjarne'd function: {func2(example).quoted()}"); // the function is just an object, and invocation (and in this case, binding, // as indicated by the '&' operator which requests a reference) is accomplished // using the "()" operator val func3 = Example.oneMoreThan; // <-- type: function Int(Int) val func4 = &func3(13); // <-- type: function Int() console.print($"Calling a fully bound function: {func4()}"); } }