Jump to content


Photo

Game Maker Suggestions


  • This topic is locked This topic is locked
1176 replies to this topic

#981 rwkay

rwkay

    YoYo Games CTO

  • YoYo Games Staff
  • 1440 posts
  • Version:Unknown

Posted 24 January 2012 - 03:25 PM

Most of the issue with that behaviour is down to how the '=' is interpreted in GML as it is not only the assignment operator but also the equality operator this is the reason that the a = b = c; does not work properly (as the b=c is interpreted as an equality not assignment) due to this the behaviour of short circuiting would not be very good.

Now I know that is a bit woolly but it is buried within the language definition and due to the nature of GML it is problematic - currently the parser enforces that the && || ^^ MUST have boolean arguments (the left and right of the operator) this stops the type propagation which is what you are desiring - in the long term for type safety I think this is a good idea (though I would like to hear the arguments for and against).

Russell
  • 0

#982 Rusky

Rusky

    GMC Member

  • New Member
  • 2450 posts

Posted 24 January 2012 - 03:51 PM

It is currently possible to do something like "a = b && c" as a statement, so I'm not entirely sure what the problem is parser-wise.

I do wonder how possible it would be to enforce == without confusing people though (or if it would even be beneficial).
  • 0

#983 rwkay

rwkay

    YoYo Games CTO

  • YoYo Games Staff
  • 1440 posts
  • Version:Unknown

Posted 24 January 2012 - 04:08 PM

In GM9 you will need to use == as it simplifies things so much at the parser

Trust me when I say that the Delphi parser it is complicated to do the propagation - for HTML5 and Studio it is a bit easier and I will investigate how to propagate the type correctly from left and right arguments of || && and ^^ - the problem is when you have 2 types that are not the same (say <int> && <boolean>) then the propagation rules have to make sense and be easily understood - some of C's more basic problems originally stemmed from arbitrary and ill understood edge case rules for things like this...

I will need to sit down and think about them when finalising GM9's GML

Russell
  • 0

#984 IceMetalPunk

IceMetalPunk

    InfiniteIMPerfection

  • Retired Staff
  • 9314 posts
  • Version:Unknown

Posted 24 January 2012 - 05:57 PM

Can I make a request for short-circuiting behavior? Scripting languages often allow logical operators to evaluate not to true/false, but to whichever object decided their truth/falsehood, which is then treated equivalently by e.g. if statements. This allows for things like default values with ||, or similar checks to the "b != 0" example in more contexts.

For example, to give argument3 a default value, since 0 (or null, that would be nicer) is treated as false, you could say

arg3 = argument3 || my_default
You could also do something like this, using &&, saving the result of some_call in foo:
foo = some_check && some_call()
This even allows for implementing ?: yourself, although it's not very readable:
a = cond && yes || no

I don't understand that second one at all...why would some_call() necessarily be stored in foo? With an && operator, both must be true to evaluate to true, so why is some_call() stored instead of some_check?

-IMP
  • 0

#985 Rusky

Rusky

    GMC Member

  • New Member
  • 2450 posts

Posted 24 January 2012 - 11:26 PM

If some_check evaluates to false, foo gets some_check. If some_check evaluates to true, foo gets some_call(). It doesn't matter what some_call() evaluates to at that point because if it evaluates to true, it will evaluate to true again; if it evaluates to false, it will evaluate to false again.

@rkway: I was thinking it would be pretty simple for && and || just to evaluate to the operand that decided their result, the way e.g. Lua, Python, JavaScript, Ruby, Lisp... do. There's no need to bring in C-like type coercion, and since GML is dynamically typed the result doesn't need to be coerced either.

Edited by Rusky, 24 January 2012 - 11:29 PM.

  • 0

#986 paul23

paul23

    GMC Member

  • Global Moderators
  • 3383 posts
  • Version:GM8

Posted 25 January 2012 - 12:06 PM

If some_check evaluates to false, foo gets some_check. If some_check evaluates to true, foo gets some_call(). It doesn't matter what some_call() evaluates to at that point because if it evaluates to true, it will evaluate to true again; if it evaluates to false, it will evaluate to false again.

@rkway: I was thinking it would be pretty simple for && and || just to evaluate to the operand that decided their result, the way e.g. Lua, Python, JavaScript, Ruby, Lisp... do. There's no need to bring in C-like type coercion, and since GML is dynamically typed the result doesn't need to be coerced either.

So.. the TYPE of returned value may differ depending on the first operand? :yucky: That's even more places where you have to watch runtime behaviour. Ah well, I suppose it's not clever to feed strings to a place where you expect booleans anyways.
  • 0

#987 Rusky

Rusky

    GMC Member

  • New Member
  • 2450 posts

Posted 25 January 2012 - 02:35 PM

I don't see how that's a problem, especially with dynamic typing. The value will behave exactly the same when used in a boolean context with or without this behavior, and instead of throwing out information it just keeps it around to enable some useful idioms.
  • 0

#988 paul23

paul23

    GMC Member

  • Global Moderators
  • 3383 posts
  • Version:GM8

Posted 25 January 2012 - 05:01 PM

I don't see how that's a problem, especially with dynamic typing. The value will behave exactly the same when used in a boolean context with or without this behavior, and instead of throwing out information it just keeps it around to enable some useful idioms.

I've never been a fan of dynamic typing. Weak typing is nice, however when a variable changes it's type of their life I frown upon that heavily. Just a trivial example of a "bug":
var i, s;
i = 10;
s = random(1000) < 1 && "hello world";
s += i;
That's a 1 in 1000 chance the program will crash.
  • 0

#989 Dark Matter

Dark Matter

    RPG Expert

  • GMC Member
  • 3196 posts
  • Version:GM:Studio

Posted 25 January 2012 - 06:56 PM


I don't see how that's a problem, especially with dynamic typing. The value will behave exactly the same when used in a boolean context with or without this behavior, and instead of throwing out information it just keeps it around to enable some useful idioms.

Just a trivial example of a "bug":

Well then, you make sure your code is better written than that, don't you?
  • 0

#990 Rusky

Rusky

    GMC Member

  • New Member
  • 2450 posts

Posted 25 January 2012 - 11:37 PM

I've never been a fan of dynamic typing. Weak typing is nice, however when a variable changes it's type of their life I frown upon that heavily. Just a trivial example of a "bug":

var i, s;
i = 10;
s = random(1000) < 1 && "hello world";
s += i;
That's a 1 in 1000 chance the program will crash.

You can crash a program the same way with or without this feature, and this feature can exist with or without dynamic typing. It's a completely separate issue.
  • 0

#991 paul23

paul23

    GMC Member

  • Global Moderators
  • 3383 posts
  • Version:GM8

Posted 26 January 2012 - 12:04 AM

I've never been a fan of dynamic typing. Weak typing is nice, however when a variable changes it's type of their life I frown upon that heavily. Just a trivial example of a "bug":

var i, s;
i = 10;
s = random(1000) < 1 && "hello world";
s += i;
That's a 1 in 1000 chance the program will crash.

You can crash a program the same way with or without this feature, and this feature can exist with or without dynamic typing. It's a completely separate issue.

Well the problem is how the error may be reported.

With such a feature, the crash occurs at the "s += i" - line 4. Yet the actual bug is in the s = random(1000) < 1 && "hello world"; - line 3. Here the lines are directly below each other, but with these features you'll always have subtle cases where things may crash, making it much more difficult to track the bug down to the correct line.
When to operands of the && operator are forced to be "convertable to boolean", the above example would crash at line 3.


Well sure it's not deal breaking, but I'm not really seeing any advantage of such syntax? Especially if a ternary operator is added I don't see any use to this - well only thing would be if the left side operator is an expression with a side effect...
  • 0

#992 Rusky

Rusky

    GMC Member

  • New Member
  • 2450 posts

Posted 26 January 2012 - 12:59 AM

Your "bug" and its "problems" with error reporting are 100% independent of both short-circuit evaluation and value propagation:
var i, s;
if (random(1000) < 1) s = true
else s = "hello world"
s += i
There are plenty of much more realistic situations where the cause of the bug is not on the reported line; just because you can write a sample with that problem that just happens to use a feature doesn't mean the feature is in any way to blame. In fact, you can't even really blame it fully on dynamic typing, as the same thing can happen in statically typed languages.

On the other hand, I have already given several examples where value propagation is more concise:
foo = argument0 || default_value // default values when an argument is null
bar = do_something() || handle_error() // also when some operation fails
if (baz != 0 && some_condition(qux / baz)) // checking before performing an operation that can error
There are more that may or may not apply depending on other changes, such as checking if an array index exists before using it, etc.

Edited by Rusky, 26 January 2012 - 01:01 AM.

  • 0

#993 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1619 posts
  • Version:GM:Studio

Posted 26 January 2012 - 06:48 AM

It would also be nice if ds_lists were implemented as doubly linked lists internally instead of normal arrays (i.e. vectors). Index-based functionality would still be supported, for the new programmers, but it could also support iterators which are much more efficient.

I created my own version of doubly-linked lists not too long ago, using constant-sized ds_lists to represent list nodes. They were much more efficient than ds_lists in everything except adding to the end, which I eventually realized is because if GM's arrays are vectors, they double in size whenever they reach the end, whereas my methods require new allocation for each new node. Still, everything else was orders better, so...I think it should be implemented "correctly" (i.e. in a more standard, generally more efficient way).


Many people use lists as pointers to arrays (random access). Perhaps it would be better to change the implementation, but to add a set of ds_vector functions (or a class, if classes are added).

Some of the current data structures should have their current implementation overhauled. For example, I have written GML that replicates the ENTIRE set of ds_priority functions, and runs 10x faster on average than the built-in functions (~31000 elements). The DLL averages 120x faster on the same data set (includes the time required to determine whether input/output is string or real) (Mine: log n) (Built-in: n). If used properly, the DLL is faster than built-in for 32 or more elements.

GM seems to use the most naive method for managing priority queues (An unordered list, with finding/deleting max/min handled using a picking algorithm)
A better solution would be to use a min heap (or max heap, if people check the max more often than the min). The finding of the other one (min or max) can still be done using picking algorithms, but problems arise when changing or deleting random elements.
Best solution: Min-max heap. This is what I did. O(1) for finding min/max, O(log n) for adding/deleting. Care must be taken when editing/deleting a random element, but if its position is known, it can be done in O(log n)
  • 0

#994 Boreal

Boreal

    C++ Wackjob

  • GMC Member
  • 417 posts
  • Version:None

Posted 29 January 2012 - 06:39 AM

I don't know if this has been said yet or not, but we need the option to disable collisions/speed updates/automatic stuff for certain objects. Does a controller really need to be included in collision checks?
  • 0

#995 Big J

Big J

    GMC Member

  • GMC Member
  • 2825 posts
  • Version:GM8.1

Posted 29 January 2012 - 07:02 AM

The overhead for updating all the variables of 1 object is probably negligible compared to everything else that the engine has to do. Aren't controller objects usually made without a sprite? In that case, they would probably be excluded from collision checks. However, since I actually don't know, this post cannot be taken at face value because it is merely speculation. :P

Edited by Big J, 29 January 2012 - 07:03 AM.

  • 0

#996 falconfetus8

falconfetus8

    GMC Member

  • GMC Member
  • 38 posts
  • Version:Unknown

Posted 05 February 2012 - 04:09 PM

For the debugger, we already have the ability to exceute code one step at a time. However, this is useless when trying to solve many bugs. What we need is the ability to execute code one LINE at a time. This will make solving bugs dramatically easier, and cut down much of the trial and error involved.
  • 0

#997 Rusky

Rusky

    GMC Member

  • New Member
  • 2450 posts

Posted 05 February 2012 - 04:37 PM

That's already planned, and available in GM:HTML5.

Edited by Rusky, 05 February 2012 - 04:37 PM.

  • 0

#998 falconfetus8

falconfetus8

    GMC Member

  • GMC Member
  • 38 posts
  • Version:Unknown

Posted 08 February 2012 - 10:58 PM

That's already planned, and available in GM:HTML5.

Sorry, but who exactly were you replying to?
  • 0

#999 iam1me

iam1me

    GMC Member

  • GMC Member
  • 380 posts
  • Version:GM8

Posted 12 February 2012 - 08:13 AM

I have a couple suggestions to improve the language: if_with & return_with. As the names suggest, these will allow you to do an if then statement or return a value from a function while setting the scope, temporarily, at the same time.

For example, say I have an Object1 instance that has a script which will return true/false depending upon some condition which must be checked real-time. Right now, in order to do a conditional based upon that value from outside the scope of Object1, I have to take a rather verbose approach:

var temp;
with(Object1) temp = script_name();

if(temp){....}

The need for useless intermediate values and verbose code can be done away with by combining the if & with statements into one:

if_with(Object1,script_name()) {...}

of course, if_with is not exhaustive and could be improved with a return_with statement. For instance, say I needed to do a conditional using values from scripts using variables from different instances? I could make a bunch of temporary variables to store the values or I could have the much nicer return_with approach:

if(local_script() && return_with(instance1,another_script())) {...}


Still better yet, I would love to see a "->" operator, like in c++, which would essentially serve as a quick with statement. It would set the scope to the variable indicated on the left for the variable/script indicated on the right. Like so:

somevariable = someinstance->evaluate_script();

someinstance->do_function();

This would be an incredible improvement to the language for those of us who know how to program outside of GML.
  • 0

#1000 Dark Matter

Dark Matter

    RPG Expert

  • GMC Member
  • 3196 posts
  • Version:GM:Studio

Posted 12 February 2012 - 06:08 PM

This would be an incredible improvement to the language for those of us who know how to program outside of GML.

Alternatively, just add an additional argument to any scripts that require taking in local variables...
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users