Navigation

    Fuze Arena Logo
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Users
    • Groups
    • Help
    • Discord

    The ref keyword coming to FUZE

    Coding
    8
    24
    1533
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • PB____
      PB____ last edited by PB____

      Some things are not entirely clear to me on how the ref keyword will work when it comes to FUZE. When the update video came out, I thought the update would soon follow, so back then I decided to respond supportive. However, as we're still waiting, I'm kind of still curious on how the keyword will behave exactly. And I do think this is a keyword that deserves some discussion.

      First of all, in many languages (but not all of them), objects and arrays are accessed by reference by default. However, the main reasoning behind this default is memory and performance (to prevent creating a lot of useless copies of the same array or object). However, we're living in a different time now, where the resources to do this are plentiful. For example, the following snippet of JavaScript creates 5000 unique objects, adds them to an array and prints how many milliseconds that took. On my laptop from 2016, this takes less than 1 millisecond (meaning it sometimes prints 0 to the console, as if no time has passed while doing this, while running in my browser):

      //JavaScript snippet:
      (() => { // module
          var start = new Date();
          var arr = [];
          for(var i = 0; i<5000; i++) {
              arr.push({i});
          }
          var end = new Date()
          console.log(+end - start);
      })();
      

      So if you look at this decision with this in mind, and thinking about young learning programmers. I do actually think that being pure about passing an array by value, is more intuitive to them. Especially when you offer the option to reference the original array, so they are made aware that this is something that you need to think about.

      So as I said before, I like this addition to the language.

      However, the ref keyword may introduce other expectations, of which I'm not sure that FUZE will meet them in the update (I don't know).

      For example, what will the following code print out?

      var list = [1,2,3]
      change(list)
      print(list) // what will this output?
      
      function change(ref lst)
          lst = [4,5,6]
      return void
      

      If this would print out [4,5,6] I think that would be really cool.

      Then it could be used for more advanced stuff as well:

      string strVal = input("enter a number", false)
      int result // no value yet?
      if toInt(strVal, result) then
          print(result, " is a valid number")
      else
          print(strVal, " is not a valid number")
      endif
      
      function toInt(strVal, ref intVal)
          intVal = int(strVal)
          int isNaN = str(intVal) == "nan"
      return !isNaN
      

      On the other hand, if ref is only a keyword to decide between copying structs, vectors and arrays, or not, then I think that's still a valuable addition to the language, that enables learning programmers to think about the difference between the two. I mean in the end when they switch to different languages, they will learn how that language works. And things will be different anyway (what ever language they learn).

      So in my opinion, I don't mind which ever direction FUZE has chosen to go with this. But I'm curious about peoples expectations concerning the announced keyword and where the language is actually going :)

      T 1 Reply Last reply Reply Quote 1
      • PickleCatStars
        PickleCatStars F last edited by

        Memory and performance are still important. I’m wishing ref was already implemented to help with my project, for those reasons and to improve readability.

        As far as I know, your first example is exactly what should happen. I don’t understand your second thing though, so I can’t comment on that.

        1 Reply Last reply Reply Quote 2
        • T
          thedos @PB____ last edited by thedos

          @PB____
          my two cents for what it's worth. the switch (and there for fuze) uses c++ under the hood which does not pass objects by reference hence the purpose of pointers. since fuze is a "basic" language built on top of an object oriented language that has no native memory management, the issues we have been seeing on this topic are artifacts on how the underlying c++ language handles the fuze interpreted code. the ref keyword is most likely being used as a translation for & in c++. i could be completely wrong, but would make sense.

          1 Reply Last reply Reply Quote 1
          • SteveZX81
            SteveZX81 F last edited by

            I hope this is purely optional, it looks way too complex for me.

            spt games 1 Reply Last reply Reply Quote 2
            • PickleCatStars
              PickleCatStars F last edited by

              Will I be able to have a = 1 b = 2 c = [ref a, ref b]?

              spt games Martin 2 Replies Last reply Reply Quote 1
              • spt games
                spt games @PickleCatStars last edited by

                @toxibunny That seems like it would work, then your array values would always be up to date with a and b.

                1 Reply Last reply Reply Quote 1
                • PB____
                  PB____ last edited by

                  I think that usage would be as Dave specified as a by-variable basis in this post: link.

                  That response was over 6 weeks ago though, so there might be some new insights by now, but I wouldn't expect to be able to use ref other than in the signature of a user-defined function.

                  spt games 1 Reply Last reply Reply Quote 0
                  • spt games
                    spt games @SteveZX81 last edited by spt games

                    @SteveZX81 I believe so. From Dave's explanation at 20:00 its to address a bug that was making FUZE behave unpredictably when copying values between certain types of variable.

                    Instead of just reading the value into another variable it was creating a kind of link ("a reference") which meant the original would mimic the new variable, which you probably didn't intend - especially if you're new to coding and you've never heard of "passing by reference".

                    But then wait a sec, what if you DID want this to happen, thus the "ref" keyword that allows you to say "yes I do want to modify the original, not just copy its values".

                    They're giving you a choice to avoid confusing people who are new to coding vs those who expect the latter to happen.

                    Hope that helps (even just a little bit)

                    1 Reply Last reply Reply Quote 1
                    • spt games
                      spt games @PB____ last edited by spt games

                      @PB____ Hard to say as FUZE seems to be modelled/inspired by BASIC but with features borrowed from other languages. So I guess its down to how the development team choose to make it work.

                      Coming from a C# background, I would probably find "ref" most useful in functions. I can see it being useful for games like real time strategy where you have hundreds of units (tanks, soldiers, etc) that you want to track individually, sometimes you might want to clone "unit a" (a copy) othertimes you want a handle that represents "unit a" - so you can affect it. Having the choice is good 😊

                      1 Reply Last reply Reply Quote 1
                      • PB____
                        PB____ last edited by PB____

                        @spt-games I agree, having a choice is good, and I also think you're spot on with your response to Steve. If it's fuzzy what this is about, your code will probably keep working just fine. And should something break, then it would probably be an easy fix.

                        I'm not sure if I was clear about the nuances that I used in my example codes.

                        • To me it's clear that if you use ref: then changing properties/elements on the ref variable will have the same effect the original.

                        What's not clear to me is:

                        1. What happens when you assign a value to the variable (in stead of changing a property or element of the ref argument)?
                          • Will the reference be lost: like when assigning a string to an int variable, it just becomes a different type of variable
                          • Will the reference be kept: and would the original variable outside of the function be assigned the new value
                            For example in C# it would be possible to assign to the original variable by using ref.
                        2. If the reference is kept, will it then be required to have initially assigned a value to the variable?
                          If you could assign from within the function, then you could use this as an additional output of your function. (in C# you would use the out keyword for this).

                        Sorry that this was a half post earlier (I accidentally hit tab and then space while typing).

                        1 Reply Last reply Reply Quote 0
                        • spt games
                          spt games last edited by spt games

                          I reckon for simplicity they will go for the former. FUZE's language likes simplicity over headache inducing complexity (I am looking at you C language). For example:

                          /* Would update whatever actual variable "thePerson" refers to */
                          thePerson.favouriteFood = "Pizza"

                          /* Reference to the original variable is lost and thePerson becomes an integer. Original variable unaffected. */
                          thePerson = 2

                          1 Reply Last reply Reply Quote 1
                          • Gothon
                            Gothon F last edited by

                            Memory references are an important concept in programming. 'Handles', 'indexes', 'pointers' and even 'variable names' are all different kinds of memory references. Ultimately the underlying idea is the same: There is a place where my data is stored and this 'reference' is how I keep track of that place.

                            When passing this data to functions, there is no difference (in behavior) between value and reference parameter passing conventions if all you do is read the data. However there is a significant behavioral difference when you write back to the parameter variables.

                            Some functions only purpose is to compute a return value by reading the parameters without altering them. However for other functions the purpose is specifically to write to and change the data that are referenced by the parameters.

                            It is possible to write to these locations without reference passing by instead storing the data in global arrays. You can then pass an index to any desired element by value and use this index like a reference to the data in the global array. However writing functions that specifically access global arrays is not considered good practice because the function is dependent on the name of the global variable. It will be difficult to reuse the function in a later program that needs it but has differently named or even name conflicting global variables.

                            So the feature is definitely useful. It allows the writing of generalized code free of ties to the global space of variable names.

                            Making reference variables as @toxibunny suggests is another whole feature. Implementing good memory management with reference variables is a complex thing, that might require a sophistcated garbage collector to detect and free structures with cyclical references.

                            Ultimately what is needed is that whatever features and behaviors are implemented are well defined and documented so that no one has to do trial and error guesswork to figure out what a program will do. (you still can if you wan't to though ;-P)

                            spt games 1 Reply Last reply Reply Quote 3
                            • spt games
                              spt games @Gothon last edited by

                              @Gothon Yours is a much better explanation! Especially about having to use global variables in the meantime. Functions are currently good for breaking up code and making it re-usable in a program, but as you suggested you can "tightly couple them" to specific global variables which means potentially a lot of modification when you want to use it in another program, instead of a nice black box that just does the thing you need, but how it does it and on what doesn't matter.

                              1 Reply Last reply Reply Quote 1
                              • Martin
                                Martin Fuze Team @PickleCatStars last edited by

                                @toxibunny said in The ref keyword coming to FUZE:

                                Will I be able to have a = 1 b = 2 c = [ref a, ref b]?

                                No. Unless things have changed since I was last aware, the ref keyword can only be used as a modifer for function parameters. Nowhere else.

                                spt games 1 Reply Last reply Reply Quote 3
                                • spt games
                                  spt games @Martin last edited by

                                  @Martin Thanks for clearing that up. Its good to know this in advance.

                                  1 Reply Last reply Reply Quote 1
                                  • PB____
                                    PB____ last edited by PB____

                                    Thanks for the responses, I think this is an interesting discussion, but I'm still not sure if everybody is on the same page :)

                                    To prevent confusion, I'd like to summarize in code some things that are clear and not clear to me about how ref will behave in FUZE:

                                    var list = ["a"]
                                    print(list[0]) // prints "a"
                                    var otherList = noRef(list)
                                    print(list[0]) // still prints "a"
                                    otherList[0] = "b"
                                    print(list[0]) // still prints "a"
                                    var refList = withRef(list)
                                    print(list[0]) // now prints "c"
                                    refList[0] = "d"
                                    print(list[0]) // I'm not sure if this will print "c" or "d" now.
                                    list = ["e"]
                                    assignRef(list, ["f"])
                                    print(list[0]) // I'm not sure if this will print "e" or "f"
                                    
                                    print(refList[0]) // Bonus question...
                                    
                                    function noRef(values)
                                        values[0] = "b"
                                    return values
                                    
                                    function withRef(ref refValues)
                                       refValues[0] = "c"
                                    return refValues
                                    
                                    function assignRef(ref valueList, var toAssign)
                                        valueList = toAssign
                                    return void
                                    

                                    I think it's clear that ref will only be used in the function signature. So no list = [ref a, ref b]. But the underlying mechanics pose a question:

                                    var list = [[1]]
                                    var element = list[0]
                                    element[0] = 2
                                    print(list[0][0]) // should this print 1 or 2?
                                    
                                    var linkedList = [
                                        .value = 1,
                                        .previous = [],
                                        .next = [],
                                        .hasPrevious = false,
                                        .hasNext = false
                                    ]
                                    
                                    linkedList.next = [
                                        .value = 2,
                                        .previous = linkedList,
                                        .next = [],
                                        .hasPrevious = true,
                                        .hasNext = false
                                    ]
                                    linkedList.hasNext = true
                                    
                                    linkedList.next.previous.value = 3
                                    print(linkedList.value) // does this print 1 or 3? Would this behavior be consistent with the previous print example?
                                    

                                    So even though you're not using the ref keyword, there are some expectations about references when they are used in an array or a struct. If a property or element is always a copy, then it's not possible to make a proper linked list for example (since you need multiple references to the same instance in that case).

                                    Of course I have my expectations about how these things will be handled, but at this point, I still don't know. And I don't need to have the answers before the release, but I thought a discussion about these questions would do no harm.

                                    T 1 Reply Last reply Reply Quote 1
                                    • T
                                      thedos @PB____ last edited by thedos

                                      @PB____
                                      i think the thing to remember here is what fuze actually is and how it works under the hood on the actual hardware. as i mentioned before the underlying codebase for the switch is c++, which arrays and structs are copied. the key thing to differentiate however, is when speaking to the assignment operator (aka =) vs. passing into a function.

                                      the default behavior is to do a shallow copy in which member elements are duplicated and initialized with their source value. this gets tricky when one of those members might point to something in dynamic memory. by virtu of the shallow copy process the value of that "location" is what is copied, not the actual "data" stored in that location. this is where deep copy comes in and it will actually allocate new memory space and take the source data from that original memory location and duplicate it, essentially "decoupling" it away from the original location and its data, to its own exact duplicate of that information.

                                      when passing something into a function like void myFunc(int x), it is also copied by value. however you can change this behavior to pass by reference by simply changing it to be void myFunc(int& x). so now x inside the function will actually be a reference back to the original value that was passes in.

                                      this is why my suspicion as i mentioned in my earlier reply is that ref is just an alias for & under the hood (which in itself is just syntax sugar for * as well)

                                      PB____ 1 Reply Last reply Reply Quote 1
                                      • PB____
                                        PB____ @thedos last edited by PB____

                                        @thedos
                                        I do get what your saying, but I think differently about it. You can write any type of compiler or interpreter in C++ and the language it interprets can be completely different from how C++ behaves. In the end, it should matter how the FUZE team thinks it lands with their user base and targeted audience. However, it's interesting to see the different expectations people have with this.

                                        I like your point about shallow versus deep copy, to put it in code:

                                        var data = [["0"]]
                                        dataCopy = makeCopy(data)
                                        data[0][0] = "1"
                                        print(dataCopy[0][0]) // if passing by value creates a shallow copy, this would print "1", if it's a deep copy, it prints "0".
                                        function makeCopy(value)
                                        return value
                                        

                                        And if I understood you correctly about ref being an alias to &, then I think this is a scenario that I had already written out in code:

                                        var data = [0]
                                        assign(data, [1])
                                        print(data[0]) // I think you're saying you expect this to print: 1
                                        function assign(ref reference, value)
                                            reference = value
                                        return void
                                        

                                        It could be that I misunderstood the second scenario though, my C++ is a little rusty.

                                        In the end it's interesting to see peoples expectations about this. Since the nuances in it appear to be different per person.

                                        T 1 Reply Last reply Reply Quote 0
                                        • vinicity
                                          vinicity F last edited by

                                          As for me, it does not really matter as long as it is clearly communicated what kind of behavior is actually supported. One can always get around how things work by writing the appropriate code yourself.

                                          Besides, I trust the Fuze team to have thought this over a lot and come up with a good implementation.

                                          PB____ 1 Reply Last reply Reply Quote 2
                                          • PB____
                                            PB____ @vinicity last edited by

                                            @vinicity
                                            I completely agree. I'm not trying to divide here. If anything, I think it's good if people feel like they've been heard.

                                            I do hope people don't get too high expectations though from the discussion.

                                            As @spt-games said:

                                            I reckon for simplicity they will go for the former. FUZE's language likes simplicity over headache inducing complexity (I am looking at you C language).

                                            So I think it's better at this time not to anticipate any fancy patterns to use in FUZE if you were not able to do them before the update. But rather think of this as a fix for inconsistencies. Maybe the fix also leads to new things you can do, but maybe not.

                                            1 Reply Last reply Reply Quote 1
                                            • First post
                                              Last post