pointers in Monkey C - bug or by design?

this code

function f(arr)
    {
        arr[0]=11;
        arr[1]=12;
        arr[2]=13;
    }

    function test()
    {
        var x = [1,2,3];
        SYS.println(x);
        f(x);
        SYS.println(x);

    }

produces in console:
[1, 2, 3]
[11, 12, 13]

It means that f  modified external var x. Is it by design or bug?

sdk 4.1b, 4.0.6, 4.0.5...
eclipse CIQ plug in: 4.1.0.beta1
eclipse ver: 2021-09 (4.21.0) Build id: 20210910-1417
windows 10
minSdkVersion 2.4.0
java jre1.8.0_311

  • Everything in monkey c is "by value" so I've thought system makes copy of array (including contents).

    A different way of trying to explain this:

    - Yes, everything is *passed by value* to functions

    - But primitive vars hold values, and array/object vars hold reference types

    Take the following code:

    var x = [1,2,3];

    x is a *reference* to an array, not the contents of the array.

  • ok, this is the nicest "bug" I have ever seen :)

    it resolves many troubles

  • Sure, but I would encourage you to try similar code in Python and JavaScript. You'll get similar results. It's not a bug in the language.

    And as for the meaning of "pass-by-value", JavaScript is also described as "pass-by-value". But when you pass in an array or object, the "value" that you're passing in is a *reference* to an array or object.

    So it's not a bug in the documentation, either.

    https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language

    It's always pass by value, but for objects the value of the variable is a reference. Because of this, when you pass an object and change its members, those changes persist outside of the function. This makes it look like pass by reference. But if you actually change the value of the object variable you will see that the change does not persist, proving it's really pass by value.

    The way to think about it is that "pass by reference" (as in arguments to a function) really means that the function can change the value of the argument. It says nothing about whether that value is a primitive type, pointer or reference type.

    Pass by value means the function can't change the value of the argument. But if the argument is a pointer or a reference, you can still change whatever the value *refers* to.

    In other words, suppose we have:

    function f(a, b) {
      a = b;
    }

    function test() {
      var x = ...; // anything
      var y = ...; // anything else
      f(x, y);
    }

    Did x change?

    - If yes, then that's "pass by reference"
    - If no, then that's "pass by value"

    You'll see that languages like C++ and C# explicitly let you pass by reference. e.g. C#:

    void f(ref int a, int b) {
      a = b;
    }

    void g(int a, int b) {
      a = b;
    }

    void test() {
      int x = 42;
      f(x, 888); // x now equals 888 (x was passed by ref)
      g(x, 42); // x is still equal to 888. (x was passed by value)
    }

    However, in C# you can still pass an array by value, and change the contents of the array. Just like Monkey C.

    docs.microsoft.com/.../passing-arrays-as-arguments

  • Arrays can be huge.

    It would be a bad thing to create copies of them for function argument by default.

  • Arrays can be huge.

    It would be a bad thing to create copies of them for function argument by default.

    No argument here. C/C++ is the only popular language I can think of (off the top of my head) that passes objects (structs) by value (where that value is a copy of the object), as opposed to most other languages which pass a reference to an object by default (but they're still "passing by value").

    But almost nobody passes structs by value (*) in C. (Especially since C is often used for embedded systems, where passing a whole struct copy by value would be a horrible idea.)

    I'm just trying to provide ammo for the idea that, in this context, "pass by value" says nothing about *what* you're passing (a copy of an object, a pointer, a reference, or a primitive value), it only specifies that you can't reassign the variable that was passed in.

    (*) It doesn't help that we say stuff like "pass struct by value in C", since it again muddies the waters for the phrase "pass by value" in other contexts.

    stackoverflow.com/.../are-there-any-downsides-to-passing-structs-by-value-in-c-rather-than-passing-a

    TL;DR sometimes when we say "pass X by value to F" we mean "X won't be modified by F" and sometimes when we say "pass X by value" we mean "pass in a copy of X as opposed to a pointer or reference."

  • C programmers are supposed to know how not to shoot themselves in the foot.

    Structures have predictable sizes. Arrays don't.

    Arrays are really two pieces of data: the value of the first item and the number of items.

    The idea with Monkey C (and some other languages, like C#) is to avoid copying non-primative blocks of memory.

    If you need to make a copy, you have to do so explicitly.

    In C++ (for example), there are copies and deep copies of structures/classes.

  • However, in C# you can still pass an array by value, and change the contents of the array.

    No, that link is showing arrays passed by reference.

    "Because arrays are reference types, the method can change the value of the elements."

  • C programmers are supposed to know how not to shoot themselves in the foot.

    Structures have predictable sizes. Arrays don't.

    Arrays are really two pieces of data: the value of the first item and the number of items.

    The idea with Monkey C (and some other languages, like C#) is to avoid copying non-primative blocks of memory.

    If you need to make a copy, you have to do so explicitly.

    In C++ (for example), there are copies and deep copies of structures/classes.

    Thanks, I'm violently agreeing with you.

    I'm just trying to provide some context behind why "pass by value" is an overloaded and confusing term.

    It's just like "garbage collection" has two meanings:

    - (more common) tracing garbage collection

    - (less common) either tracing garbage collection or reference counting.

  • That's funny because your original (pre-edited) response said "No that link is showing arrays passed by value".

    I encourage you to read this:

    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref

    Note

    Don't confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.

    My point is that "pass by value" can refer to the semantics of whether the function can modify the passed in argument (i.e. it can't) OR it can refer to whether the thing that's passed in is itself a value.

    When ppl say "Monkey C is pass by value", they mean the former.

    If the link showed arrays passed by reference, you would see the ref keyword.

  • I'll also quote this stackoverflow discussion on whether JavaScript is "pass by value" again:

    https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language

    It's always pass by value, but for objects the value of the variable is a reference. Because of this, when you pass an object and change its members, those changes persist outside of the function. This makes it look like pass by reference. But if you actually change the value of the object variable you will see that the change does not persist, proving it's really pass by value.

    I think it's pretty clear that "pass by value" has two different meanings, based on context.