Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

passing method as a parameter to another method -- does not work!!!!!!

New Here ,
Jul 17, 2006 Jul 17, 2006
Inside a class, I am trying to pass one member method as a parmaeter to another member method. It seems not to work, although the same code would work in languages like C++/Java. What is wrong?

Now, there must be a way to do it, right? Anybody ever done something like that?

You can see a discussion on this issue here. However, no solution has been found:
http://www.kirupa.com/forum/showthread.php?t=227111

Here is my code (I have an instance of MyClass on the stage, no other code on the stage):


class MyClass extends MovieClip {

public function load_pic():Void {
this.createEmptyMovieClip("holder",100);
this["holder"].loadMovie("peas_n_carrots.jpg");
}

public function do_something(f:Function):Void {
f();
}

// Constructor

public function MyClass() {

load_pic(); //works
do_something(load_pic); //DOES NOT WORK!!!!!!!!!!!!!!!!! WHY?????????

}

}

BTW here somebody suggests a way that really works only for global functions.....
http://www.actionscript.org/forums/showthread.php3?t=56488
TOPICS
ActionScript
995
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advisor ,
Jul 17, 2006 Jul 17, 2006
that code worked for me... are you using Flash 8?
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 17, 2006 Jul 17, 2006
Are you sure?
Try to comment out the 1st line in the constructor.
Leave only the do_something(load_pic);
Do you still get a pic loaded?
Yes I am using Flash 8 pro.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advisor ,
Jul 17, 2006 Jul 17, 2006
i see your problem now - i ignored the loadMovie and substituted it with a trace, to test your concern that a method can not be passed as a parameter. but it wasn't passing the method that was the problem...

though the method passed okay, 'this' inside that method became undefined as the parameters and therefore what they refer to are only local variables. to get around this, you would need to pass the location of the function as well.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advisor ,
Jul 17, 2006 Jul 17, 2006
Alternatively you could just pass the name of the function:
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 17, 2006 Jul 17, 2006
Yes! It works!

Two questions:

1. Why does the "this" inside become undefined?... I pass a member method, right? So when do_something() gets load_pic() as a parameter, how come it does not know which instance load_pic() belongs to? The rule is that inside a class, if you use a member method without specifying what instance it belongs to, then it belongs to " this". And within a method that belongs to " this", every this means " this".... what that I am trying to say is that in every other language that I know, my original code would work... so why not in AS?

2. How did you check out the value of variables during running.....?
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advisor ,
Jul 17, 2006 Jul 17, 2006
1. It's been too long since i used C++ and I haven't used Java, so I can only speak for A/S. My interpretation of what's happening here is that the parameter is a placeholder for a function, rather than a pointer to the function. Meaning that the function itself is getting passed as a parameter. Parameters are local temporary variables that do not exist in the movie clip hierarchy. 'This' in the parameter function is therefore undefined.

2. There are two ways of checking out the values of variables during running - using trace and using Debug Movie(in the control menu below Test Movie)
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 18, 2006 Jul 18, 2006
regarding (1) this is strange, because as far as I know only primitive variables are passed by value in AS functions.... just like in Java. Why would they build the compiler to pass Function variables by value and not by reference? It's so weird, as one of the things that you always use in member methods is the context, i.e. other member variables (including the default "this") & methods.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jul 18, 2006 Jul 18, 2006
scriptkiddie wrote:

> 1. Why does the "this" inside become undefined?... I pass a member method,
> right?

No, you passed a (independant) function object.


> So when do_something() gets load_pic() as a parameter, how come it
> does not know which instance load_pic() belongs to?

The compiler knows load_pic belongs to your instance. However the compiler
doesn't know that 'f:Function' (the argument of your 'do_something' method)
actually is 'load_pic.' For all the compiler knows, 'f:Function' is a
Delegate that executes code on a completely different object.


> The rule is that
> inside a class, if you use a member method without specifying what
> instance it belongs to, then it belongs to " this".

That's right. However in your case, you didn't use a member method, you used
a local variable function object.


> And within a
> method that belongs to " this", every this means " this"....
> what that I am trying to say is that in every other language that I know,
> my original code would work... so why not in AS?

In AS, functions' scope vary depending on where they are called form: 'this'
is dynamic. Because of that, as soon as you pass a function object around,
it is detached from its container object. You can attach the function to
another object and 'this' inside will then point to it. If you call the
function without explicit scope (as a local variable in another function
for example), then 'this' will be undefined.

To manipulate functions dynamically, you have 2 options:
1) use method names to call the function explicitely on an object:
myObj["myMethod"]();
2) Use Function.call and Function.apply to so that the function object will
be invoked in the scope you specifically determine.

In your case, I'd go for 2 and your code would then become:
f.apply(this);

Tim.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jul 18, 2006 Jul 18, 2006
> 1. Why does the "this" inside become undefined?

Because you passed (by value) a reference to a function object (like all
objects are passed), and called it as a function, not as a method.

> ... I pass a member method, right?

No .. you passed a reference to a function object.

Both methods and functions are function objects. There is no difference
between them. Whether they are treated as a method (and have a 'this')
depends on how they are called.

A 'method' in a class is nothing more than a function object reference
assigned to a member variable. ie you have a member variable called
'load_pic' whose value is a reference to a function object.

Unless you call the function object via a member variable, it is treated as
a function (and so there is no 'this')

> So when do_something() gets load_pic() as a parameter, how come it does
> not know which instance load_pic() belongs to?

How would it know ? .. you only passed a value that is a reference to the
function object. Function objects are just code, they don't know that they
might be used as a method in a class, just like a number value does know it
might be stored in a member variable. There is no context passed with a
function object.

> The rule is that inside a class, if you use a member method without
> specifying what instance it belongs to, then it belongs to "this".

Yes .. but inside do_something, f is NOT a member method .. its a local
variable (function argument).

> what that I am trying to say is that in every other language that I know,
> my original code would work... so why not in
> AS?

It wouldn't work it other languages either.
--
Jeckyl


Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Aug 13, 2006 Aug 13, 2006
This issue has been confusing me too. I guess it is because we are fammiliar with languages with statically scoped semantics of "this" and of functions - which is so much easier to understand. In Java, you always know that "this" refers to the object of the class you are currently coding. You never have to wonder if it might all of a sudden refer to something else. In Scheme (Lisp variant) (and Java), every function always remembers its context. There is no such thing as a function without a context, where "this" would be undefined. My oppinion is that the dynamical scoping of AS is horrible, so much easier for bugs to crop up and harder to debug. Are there even any benefits of removing the context of a function so that "this" becomes undefined?

My wishlist for AS includes: make it statically scoped! But until then, is there some good document that covers this topic, AS scoping etc?
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 13, 2006 Aug 13, 2006
A function object has no context until it is called ... there is nothing
being removed. Unless it is called as a method, it will not have a 'this'
defined because there is no 'this' that one can use. If the function object
is called as a method, then 'this' refers to the object in whose context the
function was called as a method.

By having functions as objects (like Smalltalk) AS and JavaScript make them
first-class objects .. which is a good thing from an OO point of view.. Not
many languages do support that concept fully though. With the power and
flexibility comes responsibility though .. and the unwary can find
themselves in unfamiliar territory. However, most of the time it makes no
difference to any other than those doing more 'advanced' things.
--
Jeckyl


Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Aug 15, 2006 Aug 15, 2006

You say that A function object has no context until it is called. My point is that this dynamical semantics of functions is a feature of some languages, like AS. However I think most languages use statical semantics because it makes better design, because then you know just by looking at the context you are coding, what all references mean. Statical semantics = all functions have statical context, and does not depend on where they are called. To allow functions to be first-class objects doesn't in any way prevent statical scoping. Scheme makes virtually all objects first-class, but is completely statically scoped. (True Java doesn't fully make functions first-class, I'm guessing thats an easy way of implementing statical scoping, since you always have to call a function via its object = context.)
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 15, 2006 Aug 15, 2006
There are few languages where a context is bound to a method statically.

Every time you call a method of a different object of a given class, the
'this' is set to that object .. the binding happens when the method call is
made.

The difference is that you can ONLY call methods as methods in many
languages .. so you HAVE to have a context in order to call the function.

In AS that is not the case. You can call a method as a function and a
function as a method. Simply because AS does not distinguish between the
two types of function object. Its does leave you open for errors in your
logic .. but (like most things) if you are aware of it, and do the right
things, then the right things will happen.

The problem is that, at compile time, the AS compiler doesn't know that
there is anything wrong.
--
Jeckyl


Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Aug 16, 2006 Aug 16, 2006
Whether the binding is actually done when the call is made, is more a question of how the implementation is made at the machine level. What interests me as a programmer, is the meaning of my code at "compile time". And with statical scoping, I know that the context of a function I am coding, will always be the context that I see right there in the code. Very straight forward and simple to understand. I never have to think: "Maybe this function will be used in another context, where the variables this function referenses might be something else than they are here". As you say, with dynamical scoping the compiler can't know if you are making a logical error.

You seem to think that forcing a function to have a context is like a punishment, something you "have to have" in statically scoped languages. Why? To me, statical scoping is a way to make the code simpler to understand. I like type systems too, but some think having to declare what types objects are, is a punishment too. You don't lose anything by forcing each function having a statical scope, I think you gain.

In AS things get more confusing, because sometimes, functions need to be "called" with call(), and in some cases, where this is not possible (eg. onEnterFrame() since it is called automatically by Flash) you have to use Delegate. With statical scoping, all these problems would dissapear.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 16, 2006 Aug 16, 2006
I don't think that its a punishment at all

I'm just explaining what happens in AS. That function objects are
effectively untyped (in terms of their parameters and whether they are
methods or functions.

I'm not saying its better .. it is simpler though

Flash AS has grown from roots where its was merely for very simple movie
control (stop and play etc) and really needs re-doing now that it is being
used for more involved and complicated programming .. hence AS3.
--
Jeckyl


Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Aug 16, 2006 Aug 16, 2006
If you mean that the way AS behaves now is easier to implement for the language designers, you're probably completely right. I would guess that it is harder to implement a statically scoped language. And yes I think AS would gain alot from taking some steps forward. One great thing would be to integrate AS closer to the stuff on the Flash side, like MovieClips. It would be great if you could do:
mc:SomeMC = new SomeMC(arg1, arg2, arg3);
someOtherMC.attachMovie(mc);
So that you wouldn't be forced to handle MCs in classes by composition. That's a whole other thread tho, one I tried to discuss on a thread on classes and MovieClips¨.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 07, 2006 Sep 07, 2006
LATEST
An excerpt from here:
http://www.adobetutorialz.com/articles/1953/1/ActionScript-3.0-Overview

Method closures

Event handling is simplified in ActionScript 3.0 thanks to method closures, which provide built-in event delegation. In ActionScript 2.0, a closure would not remember what object instance it was extracted from, leading to unexpected behavior when the closure was invoked. The mx.utils.Delegate class was a popular workaround; to use it, you would write code as follows:

myButton.addEventListener("click",
Delegate.create(this, someMethod));

Delegate.create(this, someMethod)

This class is no longer needed because in ActionScript 3.0, a method closure will be generated when someMethod is referenced. The method closure will automatically remember its original object instance. Now, one can simply write:

myButton.addEventListener("click", someMethod);
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jul 18, 2006 Jul 18, 2006
> class MyClass extends MovieClip {
> public function load_pic():Void {
> this.createEmptyMovieClip("holder",100);
> this["holder"].loadMovie("peas_n_carrots.jpg");
> }
> public function do_something(f:Function):Void {
> f();
> }
> // Constructor
> public function MyClass() {
> load_pic(); //works
> do_something(load_pic); //DOES NOT WORK!!!!!!!!!!!!!!!!! WHY?????????
> }
> }

What that does is pass a reference to the function load_pic to the method
do_something via variable f, and then when it calls f(), that is treated as
a function call, not a method call, because f is a local variable.

That means 'this' is not defined for load_pic when it is called via the
variable f.

That is correct behavior.

You need to use 'call' to call a function as a method. eg

public function do_something(f:Function):Void
{
f.call(this);
}

(or you could use 'apply' instead of 'call' .. seeing there are no function
arguments being passed, these will work the same)
--
Jeckyl


Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines