ENIGMA Forums
Contributing to ENIGMA => Proposals => Topic started by: RetroX on January 06, 2011, 07:50:50 pm
-
It would be really cool if, somehow, ENIGMA would be able to do something like:
obj.instance_destroy();
instead of:
with(obj)
{
instance_destroy();
}
Basically, calling a function as a member function would merely mean applying it as a with() statement with only one line. And there might be optimisations for it, too, for example:
obj.f1();
obj.f2();
would be parsed to:
with (obj)
{
f1();
f2();
}
Granted, you could abuse this and do things like obj.draw_set_color(), but it's still a nicer syntax (and you can do that in with(), too). Obviously, with() would have to be used for ifs and loops, but for simple functions, writing it out this way just looks nicer.
I dunno how doable that this would be, but I think that it would be a really nice thing to have.
-
AGREED!
-
I'm with you.
-
Looks like some sort of "exceptional rule", but then again, there's a lot of those in GML.
Would save time nonetheless.
-
Given this suggestion, how would this be interpreted?
a = obj.f1();
-
@polygone
//a declared outside the with
with (obj)
a = obj.f1();
-
What?
Anyway never-mind it would clearly have to syntax error. This couldn't be used for anything other than straight executing functions.
-
Given this suggestion, how would this be interpreted?
a = obj.f1();
global var ______ENIGMATEMP;
with (obj)
{
______ENIGMATEMP = f1();
}
a = ______ENIGMATEMP;
By "parse," I didn't mean textually. I meant to replicate its usage.
All that with() does is change enigma::instance_event_iter to the current object. a = obj.f1() simply would mean change the event iter, however, operate on a local variable.
-
Using with seems counter-intuitive to me given how gml works. Because when an object_index is given in gml in variable assignment it only assigns to the first instance of the object, unlike with which assigns to all the instances.
obj.a = value; //assigns to just the first instance of obj
with (obj)
{
a = value; //assign to all instances of obj
}
Thus if the dot syntax was used for executing functions it seems better to me if it does not use with, but rather only executes to the first instance of obj in order to keep the notation consistent.
-
Yeah, that would make sense. Still think that it would be a good idea to have an option for all objects, though.
-
Yeah, that would make sense. Still think that it would be a good idea to have an option for all objects, though.
Given that you would want to change the object_index.variable = value interpretation to every instance at the same time. Otherwise this code would be counter-intuitive:
obj.a = obj.f1();
As it would only assign a to the first instance of obj whereas it would loop f1() with all instances of obj. It is not possible though to change them to loop through all instances of objects because it will be too much work for the interpreter to do.
Which is why I originally suggested it should just syntax error, but given that only the first instance of obj is used than I believe it is doable, it would just be like replacing obj.f1() to the return value of f1() executed in the scope of the first instance of obj.
-
That's why I'm saying that it should be made as an option. :V
Use member functions like regular variables. Then, add a configuration option to make both variables and functions operate on all objects.
-
Then, add a configuration option to make both variables and functions operate on all objects.
It's not reasonable to let them to be changed to loop through all instances otherwise you can start doing all sorts of crazy shit. Like this:
obj1.a = obj2.array[obj1.f1(), obj2.f2()];
-
You're going to have to explain that one to me... because I don't see what's wrong with it.
-
How would that be interpreted?
-
Suppose f1 and f2 return 0, and obj2.array[0,0] = 0.
The statement would be equivalent to the following:
obj1.a = 0;
As you can see, I'm totally lost, which is why someone needs to explain this one to me.
-
It would be expansion hell.
Now, that makes sense, I guess.
with() will do what it will, I suppose.
-
Suppose f1 and f2 return 0, and obj2.array[0,0] = 0.
The statement would be equivalent to the following:
obj1.a = 0;
As you can see, I'm totally lost, which is why someone needs to explain this one to me.
f1() is performed for all objects, f2() is performed for objects, and set to a for all objects. It would be expansion hell, and really, in the end, the last one executed would actually be stored. That's why it's a bad idea to make one variable operate on multiple objects.
-
Suppose f1 and f2 return 0, and obj2.array[0,0] = 0.
The statement would be equivalent to the following:
obj1.a = 0;
As you can see, I'm totally lost, which is why someone needs to explain this one to me.
As RetroX has just said, because what if there are multiple instances of obj1 and obj2? You can't run things so straight then. f1 and f2 might return different values depending on the instance it was executed with.
RetroX has stated as a solution:
in the end, the last one executed would actually be stored
But to me this is really not nice and I don't think it is a viable solution. Which is why I mentioned previously:
obj.a = obj.f1();
People would naturally expect this to work like:
with (obj)
{
a = f1();
}
But it would instead work like:
global var ______ENIGMATEMP;
with (obj)
{
______ENIGMATEMP = f1();
}
with (obj)
{
a = ______ENIGMATEMP;
}
-
Suppose f1 and f2 return 0, and obj2.array[0,0] = 0.
The statement would be equivalent to the following:
obj1.a = 0;
As you can see, I'm totally lost, which is why someone needs to explain this one to me.
As RetroX has just said, because what if there are multiple instances of obj1 and obj2? You can't run things so straight then. f1 and f2 might return different values depending on the instance it was executed with.
RetroX has stated as a solution:
in the end, the last one executed would actually be stored
But to me this is really not nice and I don't think it is a viable solution. Which is why I mentioned previously:
obj.a = obj.f1();
People would naturally expect this to work like:
with (obj)
{
a = f1();
}
But it would instead work like:
global var ______ENIGMATEMP;
with (obj)
{
______ENIGMATEMP = f1();
}
with (obj)
{
a = ______ENIGMATEMP;
}
There are no ______ENIGMATEMP. The parser will just convert "obj." to enigma_varaccess and everything will be as fast as a c++ member function call and assignation.
-
Unfortunately, r9k, it's not that simple. It's not as simple as polygone's suggestion, either.
The only way to implement this cleanly is too flawed to implement:
obj1.func()
becomes
(enigma::with_iter(obj1), func())
When the expression starts, it will be as though it was executed for obj1. When the expression ends, the with_iter will destruct, and the code will be back in its original scope. However, this will fail catastrophically:
obj1.func(obj2.func())
Both will be executed for obj2. This is because at the beginning of the expression, obj1 is pushed as the current instance, then obj2 is as well.
I haven't yet found a way around this.
-
Polygone, I wasn't suggesting any solution. I was mentioning what would actually happen.
I think that, like obj.x, obj.func() should only operate on one instance.
-
Perhaps you should have with_iter use some sort of stack?
(enigma::push_with(obj1), func(enigma::push_with(obj2), func(), enigma::pop_with()), enigma::pop_with());
-
That was actually what he mentioned doing, I believe.
-
That's how with_iter works, luis. Issue is, you just passed func() the return value of enigma::pop_with().
-
I see.
What about:
(enigma::push_with(obj1), enigma::pop_with((enigma::push_with(obj2), enigma::pop_with(func()))))
where pop_with(K) returns K.
If with_iter is already a stack, then I don't see how "obj1.func(obj2.func())" would fail. After all:
(enigma::with_iter(obj1), func((enigma::with_iter(obj2), func())))
The inner func is called after obj2 is pushed to the stack, and before it is poped, so it is applied to obj2 alone, the top() of the stack(assuming a STL stack)
The outer func is called after obj1 and obj2 are pushed to the stack, but obj2 was already poped, so obj1 is the top() of the stack and therefore func() is applied to obj1 alone.
So I think it would work. That is, unless C++ sequence points are playing tricks on me.
-
The stack is pushed twice at the beginning of the expression in my example, then popped twice right after.
pop_with(K) was what I was considering. But it wasn't until you posted it again that I realized I was thinking about it incorrectly. My first instinct was that there'd be no way to instantiate a template because the return type of func() can't be gathered from &func. But now I see that a simple template function would have done it.
inline template<typename any> any& pop_with(any &r) { return r; }
So thank you, Luis; the simplicity of the matter escaped me.