Home AMX User Forum AMX General Discussion

LENGTH_ARRAY(array_of_ints) Not Working Correctly

DEFINE_VARIABLE

PERSISTENT INTEGER SwitcherOutput[4]
NON_VOLATILE INTEGER SwitcherOutputNumber

DEFINE_START

//stick something into our integer array in case it can't be empty
SwitcherOutput[1] = 4
SwitcherOutput[2] = 3
SwitcherOutput[3] = 2
SwitcherOutput[4] = 1

SwitcherOutputNumber = LENGTH_ARRAY(SwitcherOutput)

----

Now if you Compile, Transfer and Debug that and Watch the SwitcherOutputNumber integer variable you'll see it stays at 0, why is this? The Netlinx book clearly shows a LENGTH_ARRAY working with an Integer array in this manner.

Thanks For Any Assistance in Advance.

Comments

  • Joe HebertJoe Hebert Posts: 2,159
    nherc wrote:
    //stick something into our integer array in case it can't be empty
    SwitcherOutput[1] = 4
    SwitcherOutput[2] = 3
    SwitcherOutput[3] = 2
    SwitcherOutput[4] = 1

    Now if you Compile, Transfer and Debug that and Watch the SwitcherOutputNumber integer variable you'll see it stays at 0, why is this?
    When you stuff data into individual elements of an array, the length does not change and in your case will remain at 0.

    You have a few options; here are a couple of them. You can do something like this which will set the length to 4.

    DEFINE_VARIABLE

    PERSISTENT INTEGER SwitcherOutput[4] = {4,3,2,1}

    Or you can set the length manually like this:

    DEFINE_START

    SET_LENGTH_ARRAY(SwitcherOutput,4)

    HTH
  • Maybe there is another language out there somewhere that allows an array's length to vary according to some arcane rules, (that is, somewhat unpredictably) but I've never used it.

    This feature might be more useful if an array's length was genuinely dynamic, but it isn't - the maximum size is set in the define_variable.

    You may wish to keep a count of the number of elements of an array, but it seems best to do so explicitly in a separate variable, or perhaps, taking an OO approach, use a struct and wrapper functions:
    define_type
    
    struct tArray
      {
      integer nValues[nSize]
      integer nCount
      integer nMax
      }
    
    define_function ArrayAdd{
      tArray ArgArray,
      integer ArgElement}
    {
    etc
    }
    

    It's probably best to treat every array as if its length does not vary, and to guarantee that its length is what you think it is, call something like this during startup:
    (******************************************************************************)
    (*
    The effective length of an array can vary, who knows why...
    This ensures that it never does.
    *)
    define_function IntegerArrayLengthSet  (
    	integer nArgArray[]                  )
    (******************************************************************************)
    {
    set_length_array(nArgArray,max_length_array(nArgArray))
    } (* IntegerArrayLengthSet *)
    

    This is the preference of someone who has coded for decades in a whole bunch of other languages. I feel safer making this language behave the same as all of the others. Your mileage may vary.
  • with MAX_LENGTH_ARRAY you get the value, you initialized the array with
  • nhercnherc Posts: 34
    with MAX_LENGTH_ARRAY you get the value, you initialized the array with

    Thanks Rebuild, you would have thought that the app note on LENGTH_ARRAY would have mentioned this other function for getting the true length of an array.

    I still don't get why you'd SET_LENGTH_ARRAY only to request it again with LENGTH_ARRAY when you already know the length as you set it. I guess it'd save a bit of memory not having another variable just to store the set array size initially.

    i.e.
    INTEGER arrayOneLen
    SET_LENGTH_ARRAY(arrayOne,4) = arrayOneLen = 4

    Now if I SET_LENGTH_ARRAY, shouldn't MAX_LENGTH_ARRAY give me that value as well as LENGTH_ARRAY? IF not, what's the difference? What's filled versus what's available? OH, I looked it up and will answer my own question: LENGTH_ARRAY give the effective length only set by the SET_LENGTH_ARRAY function or direct array + or - manipulation. MAX_ARRAY_LENGTH gives you the true length of an array.

    I see what you are saying NMarkRoberts, but I think the flexibility and simplicity of dynamic arrays is a benefit for simple bits of code where structures are overkill.
  • INTEGER nMyArr[4];
    
    nMyArr[1]=70
    nMyArr[2]=123
    
    MAX_LENGTH_ARRAY(nMyArr) returns 4
    LENGTH_ARRAY(nMyArr)     returns 0
    
    ...
    
    INTEGER nMyArr[]={1,2,3,4,5,6}
    MAX_LENGTH_ARRAY(nMyArr) returns 0
    LENGTH_ARRAY(nMyArr)     returns 6
    
    ...
    
    INTEGER nMyArr[8];
    SET_LENGTH_ARRAY(nMyArr, 6)
    MAX_LENGTH_ARRAY(nMyArr) returns i dont know
    LENGTH_ARRAY(nMyArr)     returns 6
    

    max length is the maximum size the array can have
    length is kind of a pointer that is set with SET_LENGTH_ARRAY or when initializing like the second example. note the difference between the first example (the pointer is not set), with the second (the pointer is set)
  • Joe HebertJoe Hebert Posts: 2,159
    Maybe there is another language out there somewhere that allows an array's length to vary according to some arcane rules, (that is, somewhat unpredictably) but I've never used it.
    Hmmm...most/many languages allow an arrays? length to vary. Nothing arcane about it, is there?
    This feature might be more useful if an array's length was genuinely dynamic, but it isn't - the maximum size is set in the define_variable.
    I see that as half true. Yes, the maximum size of an array must be predetermined (we can?t new up memory in Netlinx), however the reported length is indeed genuinely dynamic.
    It's probably best to treat every array as if its length does not vary
    Curious as to why you feel that way. The variation of length is one of the useful tools we have as programmers and I see no logical reason to completely dismiss it and throw it away.
    The effective length of an array can vary, who knows why...
    Umm...cuz it?s supposed to? :)
  • Joe HebertJoe Hebert Posts: 2,159
    (******************************************************************************)
    (*
    The effective length of an array can vary, who knows why...
    This ensures that it never does.
    *)
    define_function IntegerArrayLengthSet  (
    	integer nArgArray[]                  )
    (******************************************************************************)
    {
    set_length_array(nArgArray,max_length_array(nArgArray))
    } (* IntegerArrayLengthSet *)
    
    I apologize in advance if I sound like I?m picking on your post but there is one more thing I failed to mention. The function you wrapped around the built in SET_LENGTH_ARRAY() function doesn?t ensure that the effective length never varies. All it does is set the effective length to the max length at that point in time. A simple assignment can change the effective length at will.
  • DHawthorneDHawthorne Posts: 4,584
    Other programming languages work this way too. It's simply a low-level shortcut: when you allocate an array, a block of memory big enough for your stated dimensions is created. When data is manipulated via functions, methods, whatever, the length is set to match, and the extra data still exists, but is ignored. By directly manipulating a value in a specific slot, you have bypassed that process, and the runtime has no way of knowing to update that length value. The only alternative would be to dynamically deallocate and reallocate an array every time a value changed, and the overhead would be prohibitive, especially with large arrays.
  • excaliburexcalibur Posts: 7
    As someone who is proficient in a number of languages, and having a degree in computer science, with language and grammar theory, etc. I find this to be extremely annoying, if not bordering on retarded.

    If I have an array of size "n", that I use to populate UI menus varying by room, for instance, I'm going to need to loop over this array, between 1 and m; "m" is the size of valid menu items in this array, up to n, and everything in the array beyond that point will be just zero. In every other language I've worked with, PHP and Python being the major two, I would expect Length_Array() to give me the index "m" (the last valid element of the array), anything after which would be "false" or "null". Of course having associative or dynamic arrays would be nice too, but that's another conversation.

    Anyway, I find it very odd that Netlinx's Length_Array() doesn't behave in the standard manner, as that functionality would be very useful. As it is, you can use SET_ARRAY_LENGTH(), but that introduces the possibility of the programmer mistakenly setting it to a different value than the actual size of occupied array elements, or forgetting to change it after operations to the arrays.

    Just my $0.02, for what it's worth.
  • excaliburexcalibur Posts: 7
    DHawthorne wrote: »
    Other programming languages work this way too. It's simply a low-level shortcut: when you allocate an array, a block of memory big enough for your stated dimensions is created. When data is manipulated via functions, methods, whatever, the length is set to match, and the extra data still exists, but is ignored. By directly manipulating a value in a specific slot, you have bypassed that process, and the runtime has no way of knowing to update that length value. The only alternative would be to dynamically deallocate and reallocate an array every time a value changed, and the overhead would be prohibitive, especially with large arrays.

    This makes some since, however, I've observed that in some situations, such as initializing structure data you can only populate an array using the direct index manipulation technique. For example:
    sRoom[cnRoom_Lobby].aMenuOptions[1]          = 'basics'
    sRoom[cnRoom_Lobby].aMenuOptions[2]          = 'video'
    sRoom[cnRoom_Lobby].aMenuOptions[3]          = 'music'
    sRoom[cnRoom_Lobby].aMenuOptions[4]          = 'lights'
    sRoom[cnRoom_Lobby].aMenuOptions[5]          = 'shades'
    

    The non-direct alternative:
    sRoom[cnRoom_Lobby].aMenuOptions = {'basics', 'video', 'music', 'lights', 'shades'}
    
    Is not allowed by the compiler (syntax error).

    Also, when doing an operation like:
    aRoomsMenu = sRoom[nCurrentRoom].aMenuOptions
    

    This also results in LENGTH_ARRAY(aRoomsMenu) being equal to 0. :(

    EDIT:

    Apparently if you run Set_Length_Array() after populating the structure data, then the copied array will then have the correct length as well.
    sRoom[cnRoom_Lobby].aMenuOptions[1]          = 'basics'
    sRoom[cnRoom_Lobby].aMenuOptions[2]          = 'video'
    sRoom[cnRoom_Lobby].aMenuOptions[3]          = 'music'
    sRoom[cnRoom_Lobby].aMenuOptions[4]          = 'lights'
    sRoom[cnRoom_Lobby].aMenuOptions[5]          = 'shades'
    
    [b]Set_Length_Array(sRoom[cnRoom_Lobby].aMenuOptions, 5)[/b]
    
    ...
    
    aRoomsMenu = sRoom[nCurrentRoom].aMenuOptions
    

    Causes LENGTH_ARRAY(aRoomsMenu) to equal 5, as it should have all along.
  • ColzieColzie Posts: 470
    excalibur wrote: »
    ... initializing structure data you can only populate an array using the direct index manipulation technique. For example:
    sRoom[cnRoom_Lobby].aMenuOptions[1]          = 'basics'
    sRoom[cnRoom_Lobby].aMenuOptions[2]          = 'video'
    sRoom[cnRoom_Lobby].aMenuOptions[3]          = 'music'
    sRoom[cnRoom_Lobby].aMenuOptions[4]          = 'lights'
    sRoom[cnRoom_Lobby].aMenuOptions[5]          = 'shades'
    

    The non-direct alternative:
    sRoom[cnRoom_Lobby].aMenuOptions = {'basics', 'video', 'music', 'lights', 'shades'}
    
    Is not allowed by the compiler (syntax error).

    Or just to simplify, this works
    define_variable
    integer	MyArray[5]
    
    define_start
    MyArray[1] = 1
    MyArray[2] = 2
    MyArray[3] = 3
    MyArray[4] = 4
    MyArray[5] = 5
    

    While this fails:
    define_variable
    integer	MyArray[5]
    
    define_start
    MyArray = {1, 2, 3, 4, 5}
    
    Does anyone have an explanation as to why this is so?
  • PhreaKPhreaK Posts: 966
    Because the compiler developers are sadists who enjoy our pain?

    I'm definitely with excalibur on this one. Although having the the length of the array completely disassociated what the length of it's contents does theoretically open you up to the option of being able to process it in slightly more dynamic way, it really does add to the 'messiness' of the language. If you want to perform any logic based on only a component of the array then it's much neater to set a variable for use in the check in any conditional logic rather than continuously very the perceived length of the array. When you use a length_array() functions, regardless on language, chances are you are wanting to get the length of the array.
  • ericmedleyericmedley Posts: 4,177
    PhreaK wrote: »
    Because the compiler developers are sadists who enjoy our pain?

    I'm definitely with excalibur on this one. Although having the the length of the array completely disassociated what the length of it's contents does theoretically open you up to the option of being able to process it in slightly more dynamic way, it really does add to the 'messiness' of the language. If you want to perform any logic based on only a component of the array then it's much neater to set a variable for use in the check in any conditional logic rather than continuously very the perceived length of the array. When you use a length_array() functions, regardless on language, chances are you are wanting to get the length of the array.

    To pile on (I guess) based upon the way this works in Netlinx (or doesn't for that matter) I've just gotten in the habit of putting such info in as a constant. I never could quite get the hang of what was going on from one place to another. And debug sometimes didn't seem to tell the truth when trying to suss out what was happening.

    I did have some pretty good success with it by initiating the length_array command at the time that I needed it later as opposed to trying to get it from the get go. But here again, it wasn't 100%.

    So, I just hard-code the dumb thing and move on. It was kind of frustrating, but now that I'm in the habit of it, it's not so bad. I do wish it worked more like other languages, however.
Sign In or Register to comment.