Results 1 to 10 of 10

Thread: Extended array functions...

  1. #1

    Extended array functions...

    No rush on these suggestions...

    With javascript, PHP, blah...blah... I find that the functions which provide greatest data manipulation are absent here. (Not that I expected them to be here, as they are not in a lot of other languages.)

    Specifically, I have a strong interest in these functions. (Ignore the names, I hate those.)

    Push, Pop, Shift and UnShift. (Descriptions below have been edited to reflect suggestion/desire.)

    Push: Adds one or more elements to the end of an array and returns the new length.
    Example: x = ARRAY_RADD(MyArray, 300, 45, 80, 99)
    Result: MyArray() = (123, 555) is now... MyArray() = (123, 555, 300, 45, 80, 99) and... x = 6

    Equivelent code: {Not quite TB code}
    [code=thinbasic]FUNCTION ARRAY_RADD(ArrayName, x(1), OPTIONAL x(2), x(3), x(N)) AS DWORD
    DIM i AS LONG
    REDIM PRESERVE ArrayName(UBOUND(ArrayName) + UBOUND(x))
    FOR i = UBOUND(ArrayName) TO UBOUND(x)
    ArrayName(i) = x(i)
    NEXT
    RETURN UBOUND(ArrayName)
    END FUNCTION[/code]

    Pop: Removes and the last elements of an array, and returns the new length.
    Example: x = ARRAY_RTRIM(MyArray, 3)
    Result: MyArray() = (123, 555, 300, 45, 80, 99) is now... MyArray() = (123, 555, 300) and... x = 3

    Equivelent code: {Not quite TB code}
    [code=thinbasic]FUNCTION ARRAY_RTRIM(ArrayName, x) AS DWORD
    REDIM PRESERVE ArrayName(MAX(UBOUND(ArrayName) - x, 0)
    RETURN UBOUND(ArrayName)
    END FUNCTION[/code]

    Shift: Removes first elements of an array, and returns the new length.
    Example: x = ARRAY_LTRIM(MyArray, 4)
    Result: MyArray() = (123, 555, 300, 45, 80, 99) is now... MyArray() = (80, 99) and... x = 2

    Equivelent code: {Not quite TB code}
    [code=thinbasic]FUNCTION ARRAY_LTRIM(ArrayName, x) AS DWORD
    IF UBOUND(ArrayName) - x > 0 THEN
    DIM i AS LONG
    FOR i = 1 TO MIN(UBOUND(ArrayName) - x,1)
    ArrayName(i) = ArrayName(i+x)
    NEXT
    REDIM PRESERVE ArrayName(i+x-1)
    ELSE
    REDIM ArrayName()
    END IF
    RETURN UBOUND(ArrayName)
    END FUNCTION[/code]

    UnShift: Adds one or more elements to the beginning of an array, and returns the new length.
    Example: x = ARRAY_LADD(MyArray, 300, 45, 80, 99)
    Result: MyArray() = (123, 555) is now... MyArray() = (300, 45, 80, 99, 123, 555) and... x = 6

    Equivelent code: {Not quite TB code}
    [code=thinbasic]FUNCTION ARRAY_LADD(ArrayName, x(1), OPTIONAL x(2), x(3), x(N)) AS DWORD
    DIM i AS LONG
    REDIM PRESERVE ArrayName(UBOUND(ArrayName) + UBOUND(x))
    FOR i = 1 TO UBOUND(ArrayName) - UBOUND(x)
    ArrayName(i + UBOUND(x)) = ArrayName(i)
    NEXT
    FOR i = 1 TO UBOUND(x)
    ArrayName(i) = x(i)
    NEXT
    RETURN UBOUND(ArrayName)
    END FUNCTION[/code]

    NOTES:

    I am not even sure if that code works... Looks good in my head! (I use similar code, slightly more complex.)

    These suggestions are for single dimension arrays, not multi-dimension arrays. Though, they could be done in multi-dimensions. Not fast, but possibly faster and safer than we could do it.

    I know those functions can be severely reduced even more... I only mentioned the "Long way", to show the method.

    For example... Since the values in fixed-length numeric arrays are a solid block of data. (I think they are.), TB could just split that data-block at the point of the split, and free the unused half. That would sort-of work for variant arrays also, but since the other data-block being discarded is pointers, the pointers in that half would have to be released. (As opposed to just deleting that part of memory.)

    Eg, if the array is actually a block like this... Lets say the array is 4byte pointers.
    (00001111222233334444), and you wanted to ARRAY_LTRIM the first two arrays (00001111)
    (00001111)(222233334444), The (222233334444) is the new array dimension, while the (0000) and (1111) are set free, after the pointers (0000) and (1111) have been set free. The UBOUND now sees LEN(MyArray/4) as the UBOUND result of 3, no looping is needed to push them from (----++++222233334444) to (2222++++====33334444) then (22223333====----4444) then (222233334444----++++) then REDIM to remove the moved values, so it reflects the trimmed size of (222233334444).

    Like I said... the long way... LOL. (Not fast, not efficient, not optimized, but it works.)

  2. #2
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10

    Re: Extended array functions...

    Very nice suggestions.
    I will consider them.

    Ciao
    Eros
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  3. #3

    Re: Extended array functions...

    These arrays could be made efficient by internally using a floating base and an automatic redim for buffering the array space. I think this could work well in compiled code too.

  4. #4

    Re: Extended array functions...

    Well, I was thinking that RESIZE memory-block would work, if you knew the array-split.

    If block is 000000-001234... Resize @ array-start 4, which is offset +000145...
    New memory block is 000145-001234... Resize @ array-end 4, which is offset -000200...
    New memory block is 000125-001034...

    Growing is a little more involved. Obviously.

  5. #5

    Re: Extended array functions...


    By using buffer cells on either side of the array, you only have to resize the block when you run out of cells. Most of the time, it is only necessary to shift the internal base and the notional bounds, which is of course invisible to the user.

    I am implementing dynamic arrays in Oxygen right now. There is a performance cost - boundary checking every time an array is used, but I am negotiating the best deal with the CPU . and I am thinking about whether to implement shift/unshift push/pop this time round.

    Perhaps cue / uncue as a complement to push/pop would be better terms than shift / unshift.

  6. #6

    Re: Extended array functions...

    Part of the reason I renamed the functions, is to make them more relevant to the "New Actions"... besides hating those original make-shift names... (They don't tell you what they do.)

    Just in case it was not clear... the samples-names is the names I suggest... the names above the samples, were just the stolen similar functions. (Originally, the RETURN is not the new UBOUND, but the actual items removed, as an array of values, which is great for Javascript, but not for basic. It is more relevant for us, and more commonly desired, to know the new size, as it has changed. EG, we say remove 3, but how many were actually removed? 3, 2, 1, 0... an what is the actual new size... 15, 14, 13, 12, 11? Since that would normally require more code, on our half, to get those new values. Calling UBOUND before, after, and a formula to derive at what was actually removed. When we say remove 4 but there is only 3 to remove.)

    As for the performance hit...

    It is not a hit, if doing it manually takes longer...

    If needed, you can always use a "Switch" to use the fast mode, if there is one. (User discretion advised.) LOL.

  7. #7

    Re: Extended array functions...


    How about lpush/lpop and upush/upop - being semantically consistent with lbound /ubound and even ltrim$/rtrim$ left$/right$

    dynamic queues and stacks could then be implemented like this: (no need to specify subscript)


    dim a() as long=(1,2,3,4,5)
    dim l,r as long
    l=lpop(a)
    r=rpop(a)
    lpush(a,l)
    rpush(a,r)
    if count(a)=0 then ..


    Such arrays are always going to be dynamic. For raw speed, the programmer can use the more primitive fixed array without boundary checks.


  8. #8

    Re: Extended array functions...

    I don't see "Push" and "Pop" being basic... Though, I could live with them...

    Pop = to explode = convert delimited data to ARRAY. (In basic mind-set)
    Push = to shove = move X spaces to the left, creating empty space for more stuff. (In basic mind-set)

    EG, you pop a balloon, you push your sister, you pop corn, you push paper

    Where as...
    Trim = to remove = take away and shorten
    Add = to add = to append in positive terms

    EG, you trim your hair, you add value, you trim fat, you add structure

    The "ARRAY_" just signifies that it is a macro, or large move, or grouped move. As opposed to the singular bit counterparts of the same familiar functions. The "L" and "R" are needed, to signify which direction the change is taking place. Left-Pop, does not tell me what it does, unless I am familiar with GL... GL programmers hate Push and Pop, for the same reason, also, the results would not be the same, so it adds to confusion. Just my $0.02

    Also, in the help fies... that scatters the "Array specific functions" mixed in with the other functions.

    If need be, he could just recycle the LEFT$ function, and have it respond to arrays in the new way. (No new functions, just new function to an existing function.)

    LEFT$, RIGHT$, LTRIM$, RTRIM$

    Which can do nothing on an array now... (It would have to detect the TYPE as an array, or have a constant/switch.)

  9. #9

    Re: Extended array functions...

    As a low level coder, about 10% of everything I write is Push and Pop, and the Oxygen compiler/assembler itself is highly dependent on queuing and stacking. I cannot imagine hardcore programming without them, in one form or another. But as long as the names are easy to remember and evoke the essential idea of the operations it does not really matter. Naming is the easy bit

  10. #10

    Re: Extended array functions...

    I hate that term too... Low level coder...

    Why is everything backwards... LOL

    That is like saying our brain is a low level organ, and our appendix is a high level organ. Computing is sooo backwards. Top level is naturally up, above us. While low level is here, on the ground, in the dirt, easy to reach, see and use. You would think the low level would be the easy stuff, and the first thing you see from the outside, not the inside out. I see windows as the lowest level, and pure machine code as being the highest level, deep within the core, and hard to get to.

    Again, this is what happens when programmers are allowed to use human terminology. They don't think like normal humans, so they/we end up isolating terminology that makes it even harder for others to learn. They create a language only they understand, and then wonder why no-one gets it. Not that they are selfish, they are just not developing for others they are developing for themselves, so they understand it. However, they allow others to develop, but so did Einstein, but because he used such high-level hand-made terms... few understood him. Basic un-does that damage, bringing understanding of our twisted minds, back out to those who are only slightly twisted thinkers. You can't advance to a higher level... um... lower level, until you have a slight understanding of the outer-levels of programming. Teaching them that Push and Pop are an array manipulator, will surely double the Push Pop posts in the future.

    That was actually sort of my point, I think... not about the high and low part, but about Push and Pop being of another language set, based off something that is more advanced than basic. While basic is a focus on more human/obvious/literal terms. IF...THEN, WHILE...WEND, SUB, FUNCTION, TRIM, SAVE, LOAD, PLAY, SLEEP...

    But ThinBasic is a between-basic, which is why I cold actually live with the mix of push/pop... as long as they had a good description in the help files. (The description of push and pop for matrix related stuff is clear, just not well understood, as it is unclear what happens to many people. Those are two of the most confused functions, which is the source of several thousands of posts, asking for help. Mostly related to the question. "What does push and pop actually do?")

    Plus, as per the description, push and pop are single item commands. Even when used in GL, it doesn't match the description.

    Push
    - Data1
    - Data2
    Pop
    Push
    - Data3
    - Data4
    Pop

    Thus the confusion... By the description, you would think the use is...
    {Data 3} in memory
    {Data 4} in memory
    Push(Data 1) {Add to}
    Push(Data 2) {Add to}

    Then, when you want to remove...
    {Data 1} in memory
    {Data 2} in memory
    {Data 3} in memory
    {Data 4} in memory
    Pop(Data 1) {Remove from}
    Pop(Data 2) {Remove from}

    Even they could have simplified it, by indexing all items in the stack. And instead of pushing and popping, inserting and removing indexes. Seems stupid that the stack has to continually be remade. Even more out of place, that you can't slide things around by an index of commands. Than again... it is not a game-element, it is a still-image renderer, by design. If it was designed to be a game element, it would realize that it holds all the translations that are also needed for internal display, as well as visual display.

    Ok, now I am getting a little far off topic...

Members who have read this thread: 0

There are no members to list at the moment.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •