Re: foreach routine

new topic     » goto parent     » topic index » view thread      » older message » newer message

duke normandin wrote:
> 
> Hi...
> 
> Where are we at on this issue? 

Here is a first cut at an interim solution...
-- foreach.e

-- Extended version. Covers the full functionality.

--/func every_item(pTheList, pRID, pData, pStart, pEnd, pSpan)
--/desc Process each specified item in the list
--/ret SEQUENCE: If no errors, a 4-element sequence;
--               [1] = 0 (zero)
--               [2] = 0 (if pRID sees each item)
--                   = integer (whatever pRID returned to end the processing)
--               [3] = The index of the last item processed.
--               [4] = The (possibly updated) list.
--               If errors, a 2-element sequence;
--               [1] = Error code:
--                      1 => The supplied low index is < 1
--                      2 => The supplied low index is > list length
--                      3 => The supplied high index is < 1
--                      4 => The supplied high index is > list length
--                      5 => The supplied routine id is invalid
--               [2] = The parameter in error.
--
-- This function calls the routine id /i(pRID) for each of the items
-- requested in the list /i(pTheList). The range and direction is
-- specified by /i(pStart) and /i(pEnd). /i(pStart) is the index
-- of the first item to be processed and /i(pEnd) is the index
-- of the last item to be processed. If /i(pStart) is higher than
-- /i(pEnd) then the items are processed in right-to-left order
-- otherwise they are processed in left-to-right order. /n
--
-- The /i(pSpan) parameter specifies the 'gap' between successive
-- items to be processed. To process each item use 1 as the span, to
-- process every second item use 2, etc... /n
--
-- The /i(pRID) parameter is a routine id of a caller defined function
-- which is called for each item processed. It is passed three parameters:
--     [1] => The index of the item being processed.
--     [2] => The value of the item being processed.
--     [3] => The /i(pData) parameter. This can be any object.
-- The routine must return either a single integer or a one-element
-- sequence. If it returns a 0 (zero) then next item is processed. If
-- it returns a non-zero integer, the processing of items is stopped.
-- If it returns a sequence, the first element is used to replace the
-- item just processed in the list.
--
-- Example:
--/code
-- sequence res
-- function showit(integer pIdx, object pItem, object pExtra)
--     printf(1, "%d: %s\n", {pIdx, pItem})
--     if pItem = pExtra then return 1 end if
--     return {pItem - ('A' - 'a')}
-- end function
--
-- res = every_item("ABCDEF", routine_id("showit"), 'D', 2, 5, 1)
-- printf(1, "%d %d %d %s\n", res)
--/endcode

----------------------------------------------------------
global function every_item(sequence pTheList, integer pRID, object pData,
                           integer pStart, integer pEnd, integer pSpan)
----------------------------------------------------------

    integer lDir
    object lRes
    integer lLastI
    integer lLow
    integer lHigh

    if length(pTheList) = 0 then
        return {0,0,0, pTheList}
    end if

    if pStart > pEnd then
        lDir  = -1
        lLow  = pEnd
        lHigh = pStart
    else
        lDir  = 1
        lHigh = pEnd
        lLow  = pStart
    end if

    if lLow < 1 then
        return {1, lLow}
    end if

    if lLow > length(pTheList) then
        return {2, lLow}
    end if

    if lHigh < 1 then
        return {3, lHigh}
    end if

    if lHigh > length(pTheList) then
        return {4, lHigh}
    end if

    if pRID < 0 then
        return {5, pRID}
    end if

    lRes = 0
    for i = pStart to pEnd by lDir * pSpan do
        lLastI = i
        lRes = call_func(pRID, {i, pTheList[i], pData})
        if integer(lRes) then
            if lRes != 0 then
                exit
            end if
        else
            pTheList[i] = lRes[1]
        end if
    end for

    return {0, lRes, lLastI, pTheList}

end function

--/func foreach(pTheList, pRID)
--/desc Process every item in the list, from left to right.
--/ret SEQUENCE: If no errors, a 4-element sequence;
--               [1] = 0 (zero)
--               [2] = 0 (if pRID sees each item)
--                   = integer (whatever pRID returned to end the processing)
--               [3] = The index of the last item processed.
--               [4] = The (possibly updated) list.
--               If errors, a 2-element sequence;
--               [1] = 5 (The supplied routine id is invalid)
--               [2] = The pRID value.
--
-- This function calls the routine id /i(pRID) for each of the items
-- in the list /i(pTheList). They are processed in left-to-right order. /n
--
-- The /i(pRID) parameter is a routine id of a caller defined function
-- which is called for each item processed. It is passed three parameters:
--     [1] => The index of the item being processed.
--     [2] => The value of the item being processed.
--     [3] => 0
-- The routine must return either a single integer or a one-element
-- sequence. If it returns a 0 (zero) then next item is processed. If
-- it returns a non-zero integer, the processing of items is stopped.
-- If it returns a sequence, the first element is used to replace the
-- item just processed in the list.
--
-- Example:
--/code
-- sequence res
-- function showit(integer pIdx, object pItem, object pExtra)
--     printf(1, "%d: %s\n", {pIdx, pItem})
--     if pItem = 'D' then return 1 end if
--     return {pItem - ('A' - 'a')}
-- end function
--
-- res = foreach("ABCDEF", routine_id("showit"))
-- printf(1, "%d %d %d %s\n", res)
--/endcode

----------------------------------------------------------
global function foreach(sequence pTheList, integer pRID)
----------------------------------------------------------

    return every_item(pTheList, pRID, 0, 1, length(pTheList), 1)

end function

--/func foreach_reverse(pTheList, pRID)
--/desc Process every item in the list, from right to left.
--/ret SEQUENCE: If no errors, a 4-element sequence;
--               [1] = 0 (zero)
--               [2] = 0 (if pRID sees each item)
--                   = integer (whatever pRID returned to end the processing)
--               [3] = The index of the last item processed.
--               [4] = The (possibly updated) list.
--               If errors, a 2-element sequence;
--               [1] = 5 (The supplied routine id is invalid)
--               [2] = The pRID value.
--
-- This function calls the routine id /i(pRID) for each of the items
-- in the list /i(pTheList). They are processed in right-to-left order. /n
--
-- The /i(pRID) parameter is a routine id of a caller defined function
-- which is called for each item processed. It is passed three parameters:
--     [1] => The index of the item being processed.
--     [2] => The value of the item being processed.
--     [3] => 0
-- The routine must return either a single integer or a one-element
-- sequence. If it returns a 0 (zero) then next item is processed. If
-- it returns a non-zero integer, the processing of items is stopped.
-- If it returns a sequence, the first element is used to replace the
-- item just processed in the list.
--
-- Example:
--/code
-- sequence res
-- function showit(integer pIdx, object pItem, object pExtra)
--     printf(1, "%d: %s\n", {pIdx, pItem})
--     if pItem = 'D' then return 1 end if
--     return {pItem - ('A' - 'a')}
-- end function
--
-- res = foreach_reverse("ABCDEF", routine_id("showit"))
-- printf(1, "%d %d %d %s\n", res)
--/endcode

----------------------------------------------------------
global function foreach_reverse(sequence pTheList, integer pRID)
----------------------------------------------------------

    return every_item(pTheList, pRID, 0, length(pTheList), 1, 1)

end function


-- 
Derek Parnell
Melbourne, Australia
Skype name: derek.j.parnell

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu