Maybe a few remarks:

 * currently the code works for orderedCollections;  it also will convert any 
orderedCollection,
   not only stems according to the type supplied to the from class method,

 * it would be orthogonal if mapCollections would be supported as well (taking 
into account and
   handling errors for e.g. .bag or .set), using e.g. "do with index idx item val 
over ...",

 * an alternative to the "from" class methods would be using "toStem" instance 
methods as was
   suggested; because the from class methods work for all supplied classes 
orderedCollections, one
   would have to define individual "to..." instance methods (like "toQueue", 
"toCircularQueue",
   "toList", "toArray", "toStem"); it seems that using a class method "from" 
will keep the
   interface smaller (and hence simpler) than using "to..." instance methods.

---rony


On 13.03.2025 12:31, Rony G. Flatscher wrote:
On 12.03.2025 19:28, Gilbert Barmwater wrote:

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.

Thank you for sharing!

As an example says more than thousands words, here a program defining a stem array which gets used for conversion to the different orderedCollection classes taking advantage of Gil's "stemarray.cls":

    say "using a stem array named 's.':" s.='--> not set <--' -- default value 
s.1='hi (1)'
    s.3='hi (3)' s.0=5 -- tails '2' and '4', '5' are missing say "s.0="s.0", 
s.' default value:
    """s."""" do i=1 to s.0 say " s."i":" s.i end say "-"~copies(79) say call 
demoFromStem s.
    *::requires "stemarray.cls" **-- Gil's implementation* ::routine demoFromStem say 
.line":"
    .context~name "- begin" use arg s. say say "-- pass 1 -- not supplying a second 
argument ..."
    say do clz over .xrray, .xist, .xueue, .xircularQueue, .xtem 
obj=clz~from(s.) call dump obj
    end say say "-- pass 2 -- supplying a second argument ..." say do clz over 
.xrray, .xist,
    .xueue, .xircularQueue, .xtem obj=clz~from(s., "some value") call dump obj end say 
.line":"
    .context~name "- done." ::routine dump use arg coll say "dumping a" 
coll~class~id":" -- show
    type of received coll do counter c with index idx item val over coll say " #" 
c":
    index="pp(idx) "val:" pp(val) end say "---" ::routine pp return "["arg(1)"]"

Here the output:

    rexx G:\test\orx\stem\20250312\test_sa.rex using a stem array named 's.': 
s.0=5, s.' default
    value: "--> not set <--" s.1: hi (1) s.2: --> not set <-- s.3: hi (3) s.4: --> 
not set <--
    s.5: --> not set <--
    
------------------------------------------------------------------------------- 
18:
    DEMOFROMSTEM - begin -- pass 1 -- not supplying a second argument ... 
dumping a XRRAY: # 1:
    index=[1] val: [hi (1)] # 2: index=[2] val: [hi (3)] --- dumping a XIST: # 
1: index=[0] val:
    [hi (1)] # 2: index=[1] val: [hi (3)] --- dumping a XUEUE: # 1: index=[1] 
val: [hi (1)] # 2:
    index=[2] val: [hi (3)] --- dumping a XIRCULARQUEUE: # 1: index=[1] val: 
[hi (1)] # 2:
    index=[2] val: [hi (3)] --- dumping a Stem: # 1: index=[0] val: [5] # 2: 
index=[3] val: [hi
    (3)] # 3: index=[1] val: [hi (1)] --- -- pass 2 -- supplying a second 
argument ... dumping a
    XRRAY: # 1: index=[1] val: [hi (1)] # 2: index=[2] val: [--> not set <--] # 
3: index=[3] val:
    [hi (3)] # 4: index=[4] val: [--> not set <--] # 5: index=[5] val: [--> not 
set <--] ---
    dumping a XIST: # 1: index=[0] val: [hi (1)] # 2: index=[1] val: [--> not set 
<--] # 3:
    index=[2] val: [hi (3)] # 4: index=[3] val: [--> not set <--] # 5: index=[4] 
val: [--> not set
    <--] --- dumping a XUEUE: # 1: index=[1] val: [hi (1)] # 2: index=[2] val: 
[--> not set <--] #
    3: index=[3] val: [hi (3)] # 4: index=[4] val: [--> not set <--] # 5: 
index=[5] val: [--> not
    set <--] --- dumping a XIRCULARQUEUE: # 1: index=[1] val: [hi (1)] # 2: 
index=[2] val: [-->
    not set <--] # 3: index=[3] val: [hi (3)] # 4: index=[4] val: [--> not set 
<--] # 5: index=[5]
    val: [--> not set <--] --- dumping a Stem: # 1: index=[0] val: [5] # 2: 
index=[2] val: [-->
    not set <--] # 3: index=[1] val: [hi (1)] # 4: index=[5] val: [--> not set 
<--] # 5: index=[4]
    val: [--> not set <--] # 6: index=[3] val: [hi (3)] --- 36: DEMOFROMSTEM - 
done.

---

Here Gil's code ("stemarray.cls") syntax highlighted (using IntelliJ with the 
ooRexx plugin):

    -- 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

---

---rony


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

Reply via email to