On 05.11.2025 13:28, Josep Maria Blasco wrote:
Missatge de Jean Louis Faucher <[email protected]> del dia dc., 5 de nov. 
2025 a les 11:56:

    On 5 Nov 2025, at 11:05, Josep Maria Blasco <[email protected]> 
wrote:

    I can see two different topics here:

     1. Clearly differentiating between object creation and object 
initialization.
     2. Making all objects adhere to the "NEW passes all arguments to INI" idea.

    As far as I can see, item 2 can be readily fixed, but we'd run into the 
risk of breaking
    existing programs For example, TUTOR has been written against this anomaly, 
and would require
    some changes.

    I agree with the risk of regression
    Out of curiousity, can you show an example of impact on TUTOR?


Oh, the impact on TUTOR is really minimal, I was only using it as an example of 
possible regression.

  * BYTES is a subclass of STRING. It defines an INIT method that does nothing 
(in particular,
    it does /not/ call init:super). It's probably a remnant of a time when this 
INIT method was
    doing something, but I can't seem to remember.
  * CODEPOINTS is a subclass of BYTES. It also has an INIT method. In this 
case, the method does
    some things, but it does /not/ call init:super.
  * GRAPHEMES is a subclass of CODEPOINTS. INIT first calls super:init, and 
then breaks the string
    into graphemes.
  * TEXT is a subclass of CODEPOINTS. This is the only case that would need 
rewriting. A TEXT
    string is auto-normalized to NFC, so that we can't store the string as-is. 
That's why we have
    to operate at NEW nevel. We pick the string, convert it first to NFC, 
/then/ call new:super
    with the just normalized string, and finally return this same string as the 
result of NEW.

The important thing to remember is that NEW returns an object, while INIT doesn't return anything, and therefore it's NEW that should be responsible for object creation.

And, indeed, as we have seen, the impact on TUTOR is null. After all, no rewriting is necessary. But the NEW/INIT distinction is there. I think it should be explained and documented as clearly as possible.


    We could also opt for leaving things as they are, but then it would be 
imperative to document
    and explain the anomaly.

    +1


    Regarding item 1, it would be nice if we could add a new section to rexxref 
(maybe 4.2.8)
    called "Creation", or "Object creation". It would document the whole 
process of giving birth
    to an object as composed of two phases, creation and initialization. And it 
should explain
    that, in some cases, it can be necessary (or more convenient) to process 
the arguments in
    NEW, and, in other cases, in INIT.

    +1

    That could be illustrated by the Array class versus the Queue class.

    Array's NEW checks the arguments and allocate the requested storage.
    Then the INIT message is sent with no argument.

    Queue is a subclass of Array, so in theory, should follow the same protocol 
as Array.


Queue is a subclass of Array? You must be speaking of the implementation level (I remember the Dallas report, where many of the collections are implemented as arrays).

>rexx -e "q = .queue~new; Say q~isa(.Array)"
0

    But a design decision has been taken to let pass the NEW arguments to INIT.
    QueueClass::initRexx
        // It would be nice to do this expansion in the new method, but it sort
        // of messes up subclasses (e.g. CircularQueue) if we steal the first 
new
        // argument.  We will set the capacity here, even if it means an 
immediate expansion


    Some native classes respect the protocol "NEW sends the INIT message with 
all the received
    arguments):
        Bag, Directory, EventSemaphore, IdentityTable, List, MutexSemaphore, 
Object, Queue,
    Relation, Set, StringTable, Supplier, Table.

    Some native classes proceed differently:
        - Class, Method, MutableBuffer, Package, Routine, Stem, String and 
WeakReference
          remove the arguments they use, and pass the rest to INIT
          (well, there are special cases where it's not true)
        - Array send the INIT message but doesn't pass the arguments


This clearly does not make any sense, it's difficult to explain, and still more difficult to remember. If at all possible, it should be fixed. It's very ugly when you say how things should be and and the same time you proceed differently, as it installs the idea that what you're advising doesn't work -- even for yourself.

+1



    Finally, we should stress on the fact that calling the INIT method for the 
superclass is not
    mandatory in all cases, but only when the initialization is, so to speak, 
distributed in
    several scopes. For example, in example 4.12, class Savings calls the INIT 
method of its
    superclass, because the superclass has to store the balance, but class 
Account does not call
    the INIT method of its superclass (in this case, Object). And, of course, 
if some of the
    built-in classes needs that its INIT method is called by subclasses, this 
should also be
    documented.

    +1

    The interpreter could be made more robust to detect when a native INIT 
method has not be
    called by a subclass.
    Illustration with Supplier

    s = .myUnitializedSupplier~new
    say s~available     -- Segmentation fault: 11


This is horrible. The interpreter should/ never/ crash because of a user error!

+1



    ::class myUnitializedSupplier subclass Supplier

    ::method init
       say "I don't forward INIT"

Maybe one could approach these problems as follows?

 * Add an INIT method to all those built-in classes that do not have an INIT 
method yet, which
   forward the INIT invocation to the superclass (either "self~init:super" or 
"forward class
   (super)", depending on the current behaviour to remain backwardly compatible)

 * Change NEW in all those classes Jean Louis has identified, that do not send 
an INIT message yet,
   and have an INIT message sent to the newly created object with all supplied 
arguments. (Make
   sure that all NEW methods forward arguments, if they consume arguments so 
far, only supply the
   non consumed arguments? In the case of Array start to supply the 
non-consumed arguments on the
   INIT message which by default gets intercepted in the new INIT method needed 
for Array?)

   This should allow INIT methods in subclasses to get and learn about all 
arguments supplied to
   the NEW class method and passed on to the INIT message by it.

     o Maybe let NEW consume arguments it uses, if that is the current 
behaviour; if not documented
       yet, this must be documented in all affected classes.

Could that solve the problem in a backwardly manner, taking care of the possible problems mentioned so far?

Would that also solve the problem that native INIT methods get invoked by ooRexx subclasses (like the example myUninitializedSupplier class above)?

---rony

P.S.: Sorry for the communication delays, being "under-water" at the moment with other obligations off the computer...

_______________________________________________
Oorexx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to