1. Hello Guest! It's with a heavy heart that we must announce the removal of the Legacy GMC Archive. If you wish to save anything from it, now's the time! Please see this topic for more information.
    Dismiss Notice

OFFICIAL GML Updates in 2019 (Follow up AMA)

Discussion in 'Announcements' started by rmanthorp, Apr 4, 2019.

  1. Pfap

    Pfap Member

    Joined:
    Apr 30, 2017
    Posts:
    551
    Yea, minimum viable product is a fine line to tread. If that is what they are doing and by your examples it would appear to be so... the virtual keyboard seems to be another candidate.
    https://en.wikipedia.org/wiki/Minimum_viable_product

    Anyways, I think GameMaker is a good tool really quite impressive with all it has going on and with the ease a lot of features can be implemented. But, I anticipate these new features to have their issues too.
     
  2. Ephemeral

    Ephemeral Member

    Joined:
    Mar 1, 2017
    Posts:
    185
    SYNTAX QUESTION:
    Will
    Code:
    array[0, 0, 0, 0, 0] = value;
    be equivalent to
    Code:
    array[0][0][0][0][0] = value;
    ?
    For clarity, multi-dimensional arrays are not a thing? All arrays are nested arrays, regardless of the syntax used to create them? Is that correct?
    And the [0] to the right is the one inside the [0] to the left?

    TERMINOLOGY QUESTION:
    I'm kind of straddling the two camps, "excited for new features" and "feeling alienated". And as someone who can see both sides, I agree it is not that the new features are too advanced. It's that to describe them, SCARY NEW TERMINOLOGY WE'VE NEVER HEARD BEFORE is being bandied about like we're already supposed to know what words like "method", "class", "bound", and "constructor" mean in context, with no explanation what so ever. Personally, the part of the announcement about "binding selfs" still reads like word salad to me; I have no idea what it means.
     
    Last edited: Apr 19, 2019
  3. Lukan

    Lukan Gay Wizard Freak

    Joined:
    Jun 20, 2016
    Posts:
    397
    So, I think this was answered in the help desk topic, but I'm not positive...
    GML QUESTION:
    I have a several years old project that makes heavy use of Scripts, these will still work as expected with no changes?
    Also, if these old scripts work as expected, will I still be able to update and make new scripts that use these new features?
     
  4. Posh Indie

    Posh Indie Member

    Joined:
    Dec 5, 2016
    Posts:
    200
    For the first time in a long time I will say, "Well done!". This is the right direction to be moving in.
     
    Karlstens and fireday2 like this.
  5. FlameRooster

    FlameRooster Member

    Joined:
    Feb 14, 2017
    Posts:
    138
    The only thing left this year I am curious about is Sequences and what we will be able to achieve with them. Would be nice if we could use Sequences to do story cutscenes easier.
     
    Taddio likes this.
  6. NeutronCat

    NeutronCat Member

    Joined:
    Mar 9, 2017
    Posts:
    20
    Good things!
     
  7. RanDumSocks

    RanDumSocks Member

    Joined:
    Oct 23, 2018
    Posts:
    6
    Wow, been waiting for a few years for these features! This is the start of GML becoming a fully functional object-orientated language! Now I almost want to pause development and wait for these features because using the shortcuts I have been doing to get around them will just cause more refactoring when they do come out.
     
    Karlstens and fireday2 like this.
  8. Nocturne

    Nocturne Friendly Tyrant Forum Staff Admin

    Joined:
    Apr 13, 2016
    Posts:
    7,044
    Yes

    Yes

    :)
     
    Lukan likes this.
  9. Coercive

    Coercive Member

    Joined:
    Jul 19, 2016
    Posts:
    13
    Any updates on any of the topics brought up here? Any decisions on calling the current objects "actors" or any of the sorts?

    I totally can't wait for it to drop so we can fix this redundant change that was made with real(). Wrap it in a try..catch instead of using a JSON object.
     
  10. gnysek

    gnysek Member

    Joined:
    Jun 20, 2016
    Posts:
    1,313
    I think that if they made up any decisions, we won't know until beta of GML changes, which may be sometime between end of summer and November ? I hope that there will be beta... this is too big change to just release it in Q4.
     
  11. Shadowblitz16

    Shadowblitz16 Member

    Joined:
    Jun 23, 2016
    Posts:
    601
    GML QUESTION: will lightweight objects have operator overloading?
    GML QUESTION: will lightweight objects have inheritance?
     
  12. Archer6621

    Archer6621 Member

    Joined:
    Aug 10, 2017
    Posts:
    6
    Amazing news, to me it makes GM quite relevant again for larger projects. Would be nice to add even more QOL features later, e.g. default values for function arguments, or maybe even something akin to Python's keyword arguments.
     
    fireday2 likes this.
  13. Crescent

    Crescent Member

    Joined:
    Aug 4, 2017
    Posts:
    2
    I believe they answered these questions in the follow-up on their bugtracking site.

    They're not planning to implement operator overloading, and LWOs have inheritance in that they can be defined with another LWO executed inside their body, eg:

    Code:
    var A = {
        foo: 0,
        bar: 1,
        func: function( ) {
            // stuff
        }
    }
    
    var B = {
        A();
    }
    This ties into the new() operator and constructors, since all LWOs can be executed as functions.
     
  14. Nux

    Nux Member

    Joined:
    Jul 7, 2016
    Posts:
    374
    Considering we can't even overload normal functions and/or scripts, I have a hunch that operator overloading is far beyond anything planned right now.

    Also, I don't know why, but a lot of people seem to have the idea that lightweight objects are going to be some sort of 'lesser class,' when they are actually just going to be the objects we have right now, except without events. I think a lot of people adopted this idea just because of the way the new keyword was handled: these functions are not classes, but rather constructors for that object. You've seen these before if you've ever encountered array_create or ds_map_create, it's just a different syntax for lightweight objects, i.e. using new vec2(x, y) instead of vec2_create(x, y).

    Lightweight objects will not be able to be executed as functions; you'll need to use a constructor to construct the instance of that object, these are functions:
    Code:
    function A() {
        // constructor for 'A' object
        foo = 0;
        bar = 1;
        func = function() {
            // stuff
        }
    };
    
    function B() {
        // constructor for 'B' object, inherits 'A'
        A();
    };
    
    var a = new A(); // instance of 'A'
    var b = new B(); // instance of 'B,' which inherits 'A'
    The reason this will work is because the new operator will create a new empty instance and automatically scope it. Imagine it like this:
    Code:
    // new 'A' instance
    var inst = {}; // the empty instance
    with (inst) {
        foo = 0;
        bar = 1;
        func = function() {
            // stuff
        }
    }
     
    Last edited: Jul 8, 2019
  15. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,470
    @Nux perhaps look at the method function syntax. This will make lwos into lesser classes.
     
  16. Nux

    Nux Member

    Joined:
    Jul 7, 2016
    Posts:
    374
    @GMWolf That's a good point, I could agree with that making them lesser classes. But being able to attach a function to an instance makes me think more of a struct containing closures rather than a class containing methods.

    I think the use of class just makes people assume a lot more than we're getting.
     
  17. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,470
    A struct with closures?
    To me that's either a lambda, or a class :)
    Its pretty much the model I have when using c++ classes... A bunch of data, and functions that can be applied to said data.
     
  18. Fool

    Fool Member

    Joined:
    Dec 19, 2017
    Posts:
    3
    Some observations on implementing programming languages:

    If you're going toward the "Js-like" or even total scripting support with JS as the new language, don't. This is a horrible direction, and anyone thats used javascript understands why. If it goes that direction I plan on never purchasing again.

    On that note: prototypes have been tried by lua, by javascript, and others. Likewise closures. Prototypes lead to problems with correctness. Likewise closures, or first class scopes, make debugging difficult because it makes flow control more dependent on runtime state, and runtime state tends to be opaque enough.

    For languages that did it right, look at Wren, or a less known language, Moonscript. Classes with single inheritance plus mixins for flexibility in behavior.

    I second the motion for a spread operator.

    ON DATATYPES
    As far as classes vs datatypes, I like julias approach to OOP, which is to have a hierarchy of datatypes, and datatype inheritance, rather than objects--while using multidispatch 'methods' instead of interfaces and all other sorts of hacks.

    In this way, multidispatch, gains much of the benefits of 1. single inheritance, 2. multiple inheritance, 3. interfaces, 4. abstract base types, 5. composition, and a host of other benefits of OOP with hardly any of the downsides.

    The PROBLEM with multidispatch match-on-type is that it causes it to be hard to determine when an object implements an interface or method and so it becomes easy to accidentally call types you didn't intended.

    Also, thinking about state over objects is a step in the right direction, but the majority of programs already think in objects, and for the average programmer their natural mode of thinking is objects+action to mutate state. State is harder to reason about because it tends to be so mutable and dependant on run time.

    A better solution is to disguise Julias type system in the language of OOP.

    Datatypes becomes Classes.

    Classes have methods through 'mixins' which are really just non-abstract base methods that use multidispatch, and the mixin method forms a contract that removes the risk of accidental type matching while also giving avenues for 1. self documenting code, 2. performance improvements.

    ON AUTOMATIC RETURN

    On systems designed to work or interoperate with C, automatic returns on the last statement could cause unexpected problems down the line in execution. Worse, for a beginner, these sorts of bugs are likely invisible, because the intent to return is assumed in languages where the last statement is ALWAYS treated as a return.

    Worse still, this sort of design encourages 'pyramid coding recursion hell', where some users will first decompose their program into respective scopes, and then return and compose them..atomically as possible, meaning execution flow becomes distorted, run time state becomes dependant not on obvious plain-at-sight code, but on the run time state itself, and finally it encourages a form of thinking where programmers attempt to write code that 'just works' without thinking about how it *looks* or reads. The problem with opaque-programming is that while it may or may not be effortless, much more time is spent in reading, debugging, understanding, and maintaining code than is spent writing it--which is obviously problematic if we have a bunch of invisible returns everywhere, which requires new and even senior developers reading it down the line to stop each and every time to mentally 'insert' a return statement.
    Wherever possible code should be WYSIWYG in terms of the effects per statement. Intent and the effects thereof should always be explicit per statement, not implicit, otherwise effects not intended will eventually slip in, and be missed.
    It's hard to catch, and fix the effects of a statements intent where the statement is *implicit* because the effect is a *byproduct* of another statement.

    ON DESTRUCTURING

    Python does this as do a number of other languages, and it makes serialization/deserialization far easier.

    In moonscript, the process of declaring a constructor means leads to arguments being initialized and bound automatically, so doing...

    Class Foo
    new(@x, @y, @z, @otherargs)


    ..which saves time. And unless you override those arguments, then x, y, z, and otherargs are implicitly declared and set to the value of the respective arguments that were passed in. Which is absolutely lovely.

    PROPERTY ITERATORS

    In kotlin theres some example code…

    fun main() {
    val pair = "Ferrari" to "Katrina" // 3
    println(pair)

    infix fun String.onto(other: String) = Pair(this, other) // 4
    val myPair = "McLaren" onto "Lucas"
    println(myPair)

    val sophia = Person("Sophia")
    val claudia = Person("Claudia")
    val ron = Person("Ron")
    sophia likes claudia // 5
    claudia likes ron
    ron likes sophia
    ron likes claudia

    println(sophia.likedPeople)
    }

    class Person(val name: String) {
    val likedPeople = mutableListOf<Person>()
    infix fun likes(other: Person) { likedPeople.add(other) } // 6
    }


    .. and I was thinking, if I wanted to list all the people Sophia likes, by name, then I'd have to do a foreach. But instead, what if I could do..


    println(sophia.likedPeople.nameS)

    or

    println(sophia.likedPeople.name's)

    or

    println(sophia.likedPeople.name%s)

    the idea being it looks like a string placeholder, but actually is an iterator placeholder for the given property in question.


    RIPPED SHAMELESSLY FROM SWIFT

    Nil-Coalescing Operator
    The nil-coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression b must match the type that is stored inside a.
    The nil-coalescing operator is shorthand for the code below:
    a != nil ? a! : b


    ONE SIDED RANGES

    One-Sided Ranges
    The closed range operator has an alternative form for ranges that continue as far as possible in one direction—for example, a range that includes all the elements of an array from index 2 to the end of the array. In these cases, you can omit the value from one side of the range operator. This kind of range is called a one-sided range because the operator has a value on only one side.

    SCOPES AND OTHER RAMBLINGS
    In go, you can create and initialize a variable in one line using ":="
    which works well but can cause bugs if you miss the colon (which is easy to do)

    A better approach is how javascript does it, requiring the
    use of 'strict' (or leaving it out) to determine if things should be declared beforehand or not.

    var is a better, clearer means of doing declarations on a line anyway. It's less likely to be skipped over or missed, it's simple, and it's familiar

    Finally, lexical scoping makes WAY more sense than other types of scoping. It allows you to reason about scope simply by LOOKING at the code itself.

    PACKAGES

    For an understanding of what not to do, an illustrative example, look no further than the mess that is python package management, or the modular mess that is javascript. Dependency management is and always will be a nightmare. Golang gets this right by including all dependencies in the build itself where possible. Go had the right idea, unlike python. Compile EVERYTHING (where possible) into the executable so the program itself carries around it's own dependencies.

    Do that. Developer experience is critical, and in a few years, you'll see people leaving android for apple development in droves because of googles failure to focus on developer experience.

    TUPLES

    If you allow tuples to bewritten like so..

    (x=0; x<=10;x++)

    or

    (x=0, x<=10, x++)

    Then for-loops become idiomatic, as well as method and function signatures.


    GENERICS AND THINGS SHAMELESSLY STOLEN FROM A LANGUAGE CALLED KIT

    Assuming you implement strict typing, you're probably going to want generics or type inference.

    Now, in the case of generics, the problem with them is they almost always devolve into
    a bunch of T's all scattered throughout your code, depending on the language, and make
    it difficult to discern what the hell is going on.

    I know C# used square brackets for generic types
    But they ALSO used them for directives (because generics were compile time), which is actually pretty clever, giving you the syntax for generics and directives at the same time.

    An extension of all this thinking is 'traits'.

    Traits, which can be compared to typeclasses, are interfaces that can be implemented on some type.

    Taken from a language called Kit:
    "After a trait is implemented for a certain type, values of that type can be converted to "boxed" pointers
    which look the same regardless of the type's identity; this enables open polymorphism.


    CONCLUSION

    These are just a set of ideas worth *exploring*. Not all of them are a good fit, and some of them are taste based, but if we're fielding suggestions for improvements, we have to start somewhere.
     
    Pfap likes this.
  19. xDGameStudios

    xDGameStudios Member

    Joined:
    Sep 15, 2016
    Posts:
    586
    Will there be a sign up form for beta testing this functionalities as earlier release?!
     
    fireday2 likes this.
  20. fireday2

    fireday2 Member

    Joined:
    Jun 17, 2017
    Posts:
    21
    1) Will be default values for function arguments?
    2) Will be possibility to transit (send) variable in function by reference and by value?
    3) Will be straight access to instance (like in real OOP)? I mean access witout "With" but by point
     
    Last edited: Jul 17, 2019
  21. xDGameStudios

    xDGameStudios Member

    Joined:
    Sep 15, 2016
    Posts:
    586
    I think some of these were already answered....
    1) defaults can be used using the current system "argument_count" and "argument[x]" those will still work that way.
    2) The reference/value thing I think is more a less like it is right now... Arrays/DS_* are the only ones using reference
    3) The last one is a "YES" :)
     
  22. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,470
    dont forget light weight objects. They could be used as a way to wrap variables in references. Probably not super efficient but might be very useful when dealing with callbacks, user data, etc.
     
  23. fireday2

    fireday2 Member

    Joined:
    Jun 17, 2017
    Posts:
    21
    1) you didn't understand...
    Code:
    "argument_count" and "argument[x]"
    it's not correct solution
    Default values for function arguments mean that you get possibility to skip one or more of argument!
    and you don't need to invent a bicycle!
    2) help: QIP Shot - Screen 011.png
    check it and get prove: QIP Shot - Screen 012.png
     
    Last edited: Jul 17, 2019
  24. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,470
    Not ideal but:
    Code:
    var arg0 = defaultArg0;
    var arg1 = defaultArg1;
    var arg2 = defaultArg2;
    
    switch(argument_count)
    {
       case 3: arg2 = argument[2];
       case 2: arg1 = argument[1];
       case 1: arg0 = argument[0];
    }
    
     
    fireday2 likes this.
  25. fireday2

    fireday2 Member

    Joined:
    Jun 17, 2017
    Posts:
    21
    Hah. It's not ideal - it doesn't work :)
     
  26. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,470
    Does it not?
    Does fall through not work that way anymore?
    Perhaps the same idea but with a bunch of if statements then.

    The bits of the docs you quoted confuse me.
    You would not pass arguments in an array, you would call the function as usual.
     
    fireday2 likes this.
  27. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,698
    It does work if you noticed the absence of break; statements at the end of each of the cases.

    Don't believe me? See this example.
    Code:
    ///@func foo([a, [b, [c]]]);
    var arg0 = "Alice";
    var arg1 = "Bob";
    var arg2 = "Caitlyn";
    
    switch(argument_count)
    {
       case 3: arg2 = argument[2];
       case 2: arg1 = argument[1];
       case 1: arg0 = argument[0];
    }
    
    return arg0 + " and " + arg1 + " and " + arg2;
    
    Code:
    show_message("With no arguments: " + foo()); // Alice and Bob and Caitlyn
    show_message("With 1 argument: " + foo("Apples")); // Apples and Bob and Caitlyn
    show_message("With 2 arguments: " + foo("Apples", "Oranges")); // Apples and Oranges and Caitlyn
    show_message("With 3 arguments: " + foo("Apples", "Oranges", "Pears")); // Apples and Oranges and Pears
    
    You should have used the [@ ] accessor if you wanted to modify the passed array in-place.
    Code:
    var m = argument0;
    m[@ 1] = 99;
    
    Arrays are still passed by reference, you just need to watch out for copy-on-write. That means knowing when to use the [@ ] accessor.
    The way you showed does work, it's probably because he misread your solution as this (which genuinely doesn't work):
    Code:
    var arg0 = "defaultArg0";
    var arg1 = "defaultArg1";
    var arg2 = "defaultArg2";
    
    switch(argument_count)
    {
       case 3: arg2 = argument[2]; break;
       case 2: arg1 = argument[1]; break;
       case 1: arg0 = argument[0]; break;
    }
    
    Given your level of experience, you should have stood your ground much firmer than you just did.
     
    Last edited: Jul 17, 2019
    fireday2 and GMWolf like this.
  28. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,470
    Tbh when I wrote that I couldn't remember if GML had fall through or not.

    I assumed @fireday2 would have at least tried my code before saying it doesn't work.
     
    fireday2 likes this.
  29. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,439
    See this for how optional argument retrieval is structured and GMEdit-specific shorthand syntax if you may
    https://github.com/GameMakerDiscord/GMEdit/wiki/Using-#args-magic
     
    fireday2 likes this.
  30. fireday2

    fireday2 Member

    Joined:
    Jun 17, 2017
    Posts:
    21
    @GMWolf You are right. I did't check it. Because I don't need to execute the code to understand it. But i understood wrong by inattention (in a hurry)
    Anyway - your example is a bicycle. With some restrictions (e.g. you can't skip argument in the middle)
    I am very experienced in inventing bicycles. In that way i don't need examples of the invention the bicycles. I can do it by my self
    And, don't forget that the invention of bicycles spend your expensive time. Besides, you can't see the default values when call the function (unless, of course, you're using another bike)
    p.s. i made this question because there will be a new update with implementing functions. And it will be great to see the default values in that case

    Speaking about
    Code:
    [@ ]
    I don't know it, thx. (didn't see it in the help)
     
    Last edited: Jul 17, 2019
  31. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,470
    Yet despite your experience you forgot to check if the bicycle had brakes ;)


    Ah! but i just remembered functions will have named parameters! yes, native default arguments would probably be needed.
     
    fireday2 likes this.
  32. fireday2

    fireday2 Member

    Joined:
    Jun 17, 2017
    Posts:
    21
    I am just a human ;)
     
    GMWolf likes this.
  33. xDGameStudios

    xDGameStudios Member

    Joined:
    Sep 15, 2016
    Posts:
    586
    Yesterday a question popped into mind... how will JSDoc work with these new additions? I guess it won't work for anonymous functions but for global ones we will still have JSDoc, right?
    my question is based on the following when we have a many of functions inside the same script file will the IDE be able to link the JSDocs to the function it is intended to? (supposedly the one below it?)
    I'm asking this because right now if I write

    Code:
    /// @func print_string(str)
    /// @param {string} str
    
    // Cache arguments
    show_debug_message(argument0);
    or

    Code:
    // Cache arguments
    show_debug_message(argument0);
    
    /// @func print_string(str)
    /// @param {string} str
    
    it's exactly the same thing. The IDE links the documentation to the script no matter the placement of the documentation.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice