Rather than just including the code for the two 'from' class methods, I have attached a file that you can use via ::requires stemarray.cls or, if you are in rexxtry, call stemarray.cls as I assume you might want to try them out.  This file contains the mixin classes and the sub-classes which would not be needed if the methods were part of the orderedCollection and stem classes. Because of the sub-classing, the names are .xrray and .xtem - the first letter of the super class being replaced by x.  I will have more to say about this as part of my Symposium presentation.

The code is pretty well commented but I should point out that when a stem instance is to be converted, there exists the possibility that it is sparse, i.e. an expected tail is missing. E.g. cv.0 = 3; cv.1 = 'Gil'; cv.3 = 'Rony' (no cv.2). I allow for both possibilities for the resulting array - ignore the missing tail so that the array only has 2 items or supply the 'default' stem value for any missing tails.  The choice is controlled by the presence/absence of a second argument.  The default is to NOT have the array include the missing tails on the assumption that what is important is the sequence of the items.  Two possible errors are raised - one if the argument is not the right type (a string for example) and the other if the input is a stem that has an invalid tail (not a positive integer or zero).  Finally, if a stem instance has a zero tail, that value will determine the (maximum) number of array items (any tails greater than the zero tail are discarded).

For the other 'from' method (converting to a stem), a third (optional) argument is supported which corresponds to the (optional) first argument of the stem class 'new' method that supplies the derived name of compound variables.  The previous comments apply to this method as well in regard to sparse stems and error reporting.

One final note that applies to both methods and relates to array instances only.  Of the four ordered collection classes, array is the only one that can be sparse - missing an index.  Again, the assumption is that the sequence is what is important so missing indexes are ignored; a sparse array will NEVER be output.

Here are some examples showing the basic syntax:
nm. = .xtem~from(names) where names is an array   or
names = .xrray~from(nm.)   to go the other direction

Questions and comments are encouraged.

Gil

On 3/11/2025 9:25 PM, Gilbert Barmwater wrote:

This project started many years ago - the earliest file I have located was dated 21 Sept. 2009 - and was initially only concerned with converting one type of ordered collection to another.  Each of the four classes - array, list, queue and circularQueue - provided a different "view" of a sequence of items (and, hence, different methods to operate on them) but they all shared the property that the order of the items was what was significant.  I thought it would be useful to be able to easily change "views" and came up with the idea of a 'from' class method, similar to the 'of' class method but taking an ordered class instance as its argument instead of an enumeration of the items.  The code was relatively straight forward but making the 'from' method available took some time.  I finally settled on creating a mixin class with the single 'from' class method and then four sub-classes that inherited from the mixin class.

As with all projects, they are never 'finished' and this one wasn't either.  I realized that stem arrays are often used in place of one of the four ordered collection classes and that converting to or from a stem array would also be useful. Allowing my 'from' method to take a stem array instance as its argument was the next step and it solved the conversion "from" part but to allow conversion "to" a stem array required a different approach.  I experimented with a 'toStem' (instance) method but wasn't happy with the asymmetry so I created a 'from' class method for the stem class with the same syntax.  This required another mixin class and another sub-class but it worked.

As this solution provides the functionality requested in the original post, I offer it as a way to not "reinvent the wheel" so to speak.  In my next post, I will include the code for the two 'from' methods and provide some (additional) comments on how it works and some examples of its use.  Stay tuned...

On 3/11/2025 9:27 AM, Gilbert Barmwater wrote:

Thanks for the interest in my approach.  My plan is to post the code - two class methods, both named 'from' - to this list with a better description of where they are added and some examples of how one might use this functionality.  I'm hoping to do so later today depending on the time I have available.

Gil

On 3/11/2025 8:26 AM, Josep Maria Blasco wrote:
Hi Rony,

Missatge de Rony G. Flatscher <rony.flatsc...@wu.ac.at> del dia dl., 10 de març 2025 a les 17:44:

    Hi Josep Maria,

    On 09.03.2025 14:40, Josep Maria Blasco wrote:
    Missatge de Rony G. Flatscher <rony.flatsc...@wu.ac.at> del dia
    dg., 9 de març 2025 a les 14:04:
    (cut)

            1a) In order to create an ooRexx array from a stem
            array the following method should be added to the stem
            class:

                makeArrayFromStemArray

            This name makes it clear that a stem array is to be
            processed and that the resulting array should not have
            the stem value with the tail 0.
            (The existting stem method makeArray continues to
            create an array that represents all tails of a stem,
            including a tail with the value 0.)

        I'm not sure that using "makeXXX" for the message names is
        a good idea, because the request method of the Object
        class uses the "make" pattern for class conversions.
        Yes, that is the reason why using that name.


    Ah, but a class called "ArrayFromStemArray" does not exist, and
    that breaks the "make" semantics. Rexxref 5.4.1.18 "request"
    says "Any conversion method *must return an object of the
    requested class*. For example, makeArray must return an array"
    (emphasis mine). But, since there is no such thing as an
    ArrayFromStemArray class, this could be misleading.

    Yes. The conversion method must start with "make" and be
    followed by the classid (a string) supplied as argument to the
    .Object's request method.

    This protocol could be used for creating an array from a stem
    (by implementing a method "make" || supplied_classId_as_arg,
    however, there is already a makearray method defined for stem.
    Hence the first idea to add the variant to the name of the
    conversion method yielding "makeArrayFromStemArray". The reason
    being that .Object's request method does only accept the classid
    argument and by using another name that includes the intent
    ("fromStemArray") one could add another make conversion method
    to the stem class. However, I concur that a) the name becomes
    too long and b) probably "classid" should be an existing
    classid. :) Then it becomes possibel to change the name of the
    method tonot start with "make" hence not adhering to the request
    protocol.

Exactly!

    In the meantime Gil's idea seems to be interesting.

I like it too. Very elegant, simple and easy to remember.

  Josep Maria

    ---rony


    _______________________________________________
    Oorexx-devel mailing list
    Oorexx-devel@lists.sourceforge.net
    https://lists.sourceforge.net/lists/listinfo/oorexx-devel



_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel
--
Gil Barmwater


_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel
--
Gil Barmwater


_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

--
Gil Barmwater
-- This package adds the 'from' class method to the ordered collection classes
--  and the stem class.

::class orderedCollectionPlus mixinclass Object

::method from class
-- Expects one argument that is either an instance of an ordered collection or
--  a stem with only positive integer tails, w/ or w/o a .0 tail value.
-- An optional second argument w/ any value indicates sparse stems should be
--  expanded to include all tails
    use arg inCollection
    sparse? = arg(2, O)
    select
        when inCollection~isA(.orderedCollection) then do
            if self~isSubClassOf(.circularQueue) then
                -- size required for instance of .circularQueue
                instance = self~new(inCollection~items)
            else
                instance = self~new()
            instance~appendAll(incollection)
        end
        when inCollection~isA(rexx:stem) then do
            tails = inCollection~allIndexes~sort
            loop aTail over tails   -- tails must be whole numbers >= 0
                if datatype(aTail, 'W'), atail >= 0 then
                    nop
                else do
                    err_msg = 'Stem tails must be positive integers or zero;' -
                        'found' aTail
                    raise syntax 93.900 array (err_msg)
                end
            end
            if tails[1] = 0 then do -- if the .0 tail exists, use it
                stemSize = inCollection[0]
                tails = tails~section(2)    -- remove tail 0
            end
            else    -- otherwise use the largest tail
                stemSize = tails~lastItem
            if self~isSubClassOf(.circularQueue) then
                -- size required for instance of .circularQueue
                instance = self~new(stemSize)
            else
                instance = self~new()
            -- even if the stem is sparse, the new instance will NOT be sparse
            if sparse? then -- only include tail values that are defined
                loop idx over tails while idx <= stemsize
                    instance~append(inCollection[idx])
                end
            else
                loop idx = 1 to stemSize  -- include all possible tail values
                    instance~append(inCollection[idx])
                end
        end
        otherwise
            err_msg = 'Invalid argument; must be an ordered collection' -
                'instance or a stem with positive integer tails; found' -
                inCollection~objectName
            raise syntax 93.900 array (err_msg)
    end
    return instance

::class stemPlus mixinclass Object

::method from class
-- Expects one argument that is either an instance of an ordered collection or
--  a stem with only positive integer tails, w/ or w/o a .0 tail value.
-- An optional second argument w/ any value indicates sparse stems should be
--  expanded to include all tails
-- If a third argument is present it is used as the stemName of the new instance
    use arg inCollection, , stemName=''    --trace ?i
    sparse? = arg(2, O)
    select
        when inCollection~isA(.orderedCollection) then do
            newStem = rexx:stem~new(stemName)
            tail = 0
            loop anItem over inCollection
                tail += 1
                newStem[tail] = anItem
            end
            newStem[0] = tail
        end
        when inCollection~isA(rexx:stem) then do
            newStem = rexx:stem~new(stemName)
            tails = inCollection~allIndexes~sort
            loop aTail over tails   -- tails must be whole numbers >= 0
                if datatype(aTail, 'W'), atail >= 0 then
                    nop
                else do
                    err_msg = 'Stem tails must be positive integers or zero;' -
                        'found' aTail
                    raise syntax 93.900 array (err_msg)
                end
            end
            if tails[1] = 0 then do -- if the .0 tail exists, use it
                stemSize = inCollection[0]
                tails = tails~section(2)    -- remove tail 0
            end
            else    -- otherwise use the largest tail
                stemSize = tails~lastItem
            newStem[0] = stemSize   -- set the size
            if sparse? then -- the new stem will be sparse if the stem is sparse
                loop idx over tails while idx <= stemsize
                    newStem[idx] = inCollection[idx]
                end
            else    -- the new stem won't be sparse even if the stem is sparse
                loop idx = 1 to stemSize
                    newStem[idx] = inCollection[idx]
                end
        end
        otherwise
            err_msg = 'Invalid argument; must be an ordered collection' -
                'instance or a stem with positive integer tails; found' -
                inCollection~objectName
            raise syntax 93.900 array (err_msg)
    end
    return newStem

/* subclass names are the same as the name of their class with the first
    character replaced by x     */

::class xrray subclass array public inherit orderedCollectionPlus

::class xist subclass list public inherit orderedCollectionPlus

::class xueue subclass queue public inherit orderedCollectionPlus

::class xircularQueue subclass circularQueue public inherit 
orderedCollectionPlus

::class xtem subclass stem public inherit stemPlus
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to