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

  • If you say "let x  = 42" in js, then subsequently say "x = 13", that's considered a reassignment and not a change to the original value, even if the memory address of x remains the same.

    x and 42 are two separate things. The assignment is an instruction to copy the 42 to the memory pointed/referred to by x (so, you have the 42 data in two places after the assignment).

    Assigning 13 to x is a different copy. The 42 still exists (it's not being overwritten).

    Sorry, by "original value" I meant x's original value (upon initialization) not the "original 42 that was copied to x". Poor choice of words - my bad.

    What I meant is that in the following js code...

    let x = 42;
    x = 13;

    ... the second line is not considered to "change x's value" but rather "reassign x to a different value". (If we were looking at things strictly from the POV of addresses and memory, with similar code in C, we could say for sure that we simply changed the value that exists at &x.)

    Whereas here...

    let y = [42];
    y[0] = 13;

    ...the second line is said to "change the value of y". (y refers to a specific array; that array has been changed in the 2nd line)

    developer.mozilla.org/.../Primitive

    All primitives are immutable, i.e., they cannot be altered. It is important not to confuse a primitive itself with a variable assigned a primitive value. The variable may be reassigned a new value, but the existing value can not be changed in the ways that objects, arrays, and functions can be altered
  • Roughly speaking (sorry for not being formal), when you pass a value type to a function, it gets a copy of the content (e.g. an integer). When you pass a reference type it gets a "reference" to the content (e.g. an array of integers).

    Which pretty-much matches what I was saying.

    For values, the value gets copied to a new block of memory and the address/reference to that memory is provided to the function.

    For references, the address/reference to the original memory is provided to the function.

    Except there's the additional wrinkles of "passing a value type by reference" and "passing a reference type by reference", which aren't applicable to Monkey C, but which do explain why (apparently) someone said that Monkey C is "pass-by-value". Because while Monkey C has both "value and reference" types, the function call semantics are "pass-by-value" (which in this case, I'm taking to mean that a function cannot reassign its parameters in a way that's visible to the caller.)

  • Everything depends of rules. If rule says primitives are not changed it's a bug because integer in array is a primitive.

    But checking type of every element of array will have huge influence for energy consumption, so I suggest add information to documentation that each element of array is object (independent of base type) and example to show developer what happen if he changes array outside scope.

  • Everything depends of rules. If rule says primitives are not changed it's a bug because integer in array is a primitive.

    I was quoting js documentation, and it isn't a bug because when they say "primitives are immutable" they don't mean that a primitive array element can't be reassigned to a different primitive value. Technically you're not "changing a primitive", you're putting a new primitive value in the array position that used to hold the original primitive.

    But checking type of every element of array will have huge influence for energy consumption, so I suggest add information to documentation that each element of array is object (independent of base type) and example to show developer what happen if he changes array outside scope.

    You can reassign any element of an array, regardless of the type of the current element. The type of the new element doesn't even have to be the same as the type of the old element.

  • You don't have to explain everything to me because I am not a newbe :)

    This behaviour was just strange for me, I have integer values in the table, I change them and the changes are propagated to the outside. But if we establish that an array contains objects independent of a base type, or rather references to these objects, it will be understandable that making aby operation on array's element really modifies the object, and what happens in the object depends on its operators.

    Simple integer in array is something like:

    class intARR

    {

    var mI;

    function initialize(i){set(i);}

    function get() {return mI;}

    function set(i){mI = i;}

    }

    so when I make arr[1] = 12 I don't put  12 into array but create object intARR(12) or getting existing object and call it's set function.

  • You don't have to explain everything to me because I am not a newbe :)

    Thumbsup

    This behaviour was just strange for me, I have integer values in the table, I change them and the changes are propagated to the outside. But if we establish that an array contains objects independent of a base type, or rather references to these objects, it will be understandable that making aby operation on array's element really modifies the object, and what happens in the object depends on its operators.

    I get what you're saying -- the fact that everything is an object in Monkey C is confusing.

    It's because Monkey C "primitives" (inb4 "Monkey C does not have 'true' primitives") may be object types, but they are still value types, meaning that when you assign a Number, Long, Float, Double, String, Boolean, Char or Symbol to a variable, you get a copy of the contents.

    Monkey C refers to Array and Dictionary as "container types". When you assign an array or dictionary to a variable, you get a reference to the contents.

    In other words, everything in Monkey C is an object, but not all objects are the same. Some objects are what we could call "value types" and others are what we could call "reference types" (or as Garmin puts it, "container types").

    so when I make arr[1] = 12 I don't put  12 into array but create object intARR(12) or getting existing object and call it's set function.

    "getting existing object and call it's set function."

    No, this is incorrect. As I mentioned before, you can reassign an array element to an object of any type.

    e.g.

    var arr = new Array(1);
    arr[0] = 42; // line 2
    arr[0] = 12; // line 3
    arr[0] = "hello world"; // line 4

    There's no reason that line 3 should be any different than line 4 -- both should reasssign the value of arr[0], not get the existing object and call a hypothetical set() function (which wouldn't work if the new object has a different type.)

    In any case, Monkey C "primitives" don't have a set() function, as you know. Which makes sense because primitives are supposed to be immutable.

    "so when I make arr[1] = 12 I don't put  12 into array but create object intARR(12)"

    Sure you can think of

    arr[1] = 12

    as being equivalent to something like

    arr[1] = new Number(12); // except of course in Monkey C Number doesn't have a constructor which takes an arg

    As we all know, instead of putting a literal 12 (4 bytes equal to 0x000000C) in the array, Monkey C actually stores 5 bytes (iirc). I assume the first byte is a type tag (to identify the object as a Number) and the next 4 bytes are 0x000000C.

  • But if we establish that an array contains objects independent of a base type, or rather references to these objects,

    I wouldn't look at it that way. An array contains objects, not references to objects. If you have an array full of integers, the array will contain Number objects, not references to Number objects.

    (Earlier I implied an array has "references to objects", which was a bad choice of words. Again, my bad)

    But some objects are value types (primitives like Number or String) and other objects are reference types (container types like Dictionary and Array.) This is independent of the implementation where something like a Double or a String will actually have a pointer to the actual value on the heap. I'm just referring to what happens you assign objects of these types to a variable - you either get a copy (value type) or a "reference" (reference type).

    So if you put the "same" integer in two arrays, you're putting a copy of its value in each array. There's no way to change the value in one array that affects the other array.

    If you put the same dictionary in two arrays, you're putting a reference to its contents in the array. If you change the *contents* of the dictionary, both arrays will see the change. (If you reassign that element in one array, obviously the 2nd array won't see the change.)

  • You can reassign any element of an array, regardless of the type of the current element. The type of the new element doesn't even have to be the same as the type of the old element.