From: Rick M. <obj...@gm...> - 2007-04-14 14:00:08
|
On 4/14/07, Rony G. Flatscher <Ron...@wu...> wrote: > > > Rick McGuire wrote: > > ... cut ... > > The real problem here was this should never have been a MAKESTRING method, > but rather something like "TOSTRING", so it didn't get hooked into the > automatic string coercion mechanisms. The second assumption was that all of > the elements in the array were going to be strings in the first place. > Also, adding options to MAKESTRING really shouldn't have been done. The > MAKE* methods are really intended for the automatic REQUEST processing and > are not expected to have arguments. This really should have been something > like a "TOSTRING" method instead. Rony, MAKEARRAY on CircularQueue has a > similar problem. > > I see. > > ... cut ... > > As a short term fix, I'm going to default any value in the array that is > not a string to a "" value. We can debate other replacement values later, > but right now I want to avoid the recursion problems. I'm also going to > revert my "fix" to the makestring problem back to the original behavior to > avoid the accidental behavior that could be very bad. > > I'd really like to "deprecate" MAKESTRING and introduce TOSTRING, which > supports the same options. Then, I'd also like to cap the length of the > value returned by the no-argument form of MAKESTRING to some "reasonable" > value. To get everything converted to a string, you need to be explicit > about what you want. Once that's done, I'll convert the REQUEST stuff back > to the "proper" behavior of calling the MAKESTRING method. > > Resolution sounds fine. > > However, we should discuss the methods "DEFAULTNAME"/"OBJECTNAME", > "STRING" and "MAKESTRING" in this context a little bit more, as they somehow > play each a role when a default string value is requested, and in that > context the role of the "TOSTRING" method. > > Up to now my understanding was as follows: > > - any requested MAKE method would be able to render the object in an > alternative representation that is *equivilant* (i.e. one can > recreate the original object from it, knowing its class), > - as long as a MAKE method has a safe default, supplying to it > arguments should be allowable; the CircurlarQueue class' MAKEARRAY uses this > to allow FIFO or LIFO ordering of the objects for the resulting array; this > allows employing the request, no matter of arguments (comparable to the Java > concept of a "default constructor", that works without arguments), > - MAKESTRING should *only* be supplied , if it is possible > for the object to supply a full rendering of itself as a string (or with > other words: it should be possible from the string representation to > re-create the original object, if its class is known); > - for that reason I did only implement a STRING method > in CircularQueue and only send STRING messages to its collected objects as > it would not have been possible to create a full string rendering of all > collected objects, as it would be unlikely that all of them would have a > MAKESTRING method available to them > > I have no idea where you got the idea the value returned by MAKESTRING had the requirement that it return a string value that can be used to reconstruct the original object. That was NEVER the intent of the method. The object coercion capabilities were just for the cases of if an object had a reasonable value it could supply in those situations, it could. For example, MAKEARRAY is sent by DO OVER to an object to see if it had what it considered an ARRAY representation. That array representation cannot be used to reconstruct the original object, except in some rare cases. Even the MAKEARRAY method for ARRAY cannot do this, because it returns a non-sparse array from the original. Similarly, MAKESTRING for array compresses out the sparse entries, so the string representation cannot be used to recreate the original object. > - the explanations on the "required string values from "4.1.3.14Required String Values" in the current reference doc: > > - If you supply an object other than a string in these contexts, by > default the language processor converts it > to some string representation and uses this. However, the > programmer can cause the language processor > to raise the NOSTRING condition when the supplied object does > not have an equivalent string value. > To obtain a string value, the language processor sends a > REQUEST("STRING") message to the object. > Strings and other objects that have string values return the > appropriate string value for Rexx to use. (This > happens automatically for strings and for subclasses of the > String class because they inherit a suitable > MAKESTRING method from the String class.) For this mechanism > to work correctly, you must provide > a MAKESTRING method for any other objects with string values. > > For other objects without string values (that is, without a > MAKESTRING method), the action taken > depends on the setting of the NOSTRING condition trap. If the > NOSTRING condition is being trapped > (see Conditions and Condition Traps), the language processor > raises the NOSTRING condition. If the > NOSTRING condition is not being trapped, the language > processor sends a STRING message to the > object to obtain its readable string representation (see the > STRING method of the Object class STRING) > and uses this string. > > When comparing a string object with the .nil object, if the > NOSTRING condition is being trapped, then > > if string = .nil > > will raise the NOSTRING condition, whereas > > if .nil = string > > will not as the .nil objects "=" method does not expect a > string as an argument. > > Example: > > d = .directory~new > say substr(d,5,7) /* Produces "rectory" from "a Directory" */ > signal on nostring > say substr(d,5,7) /* Raises the NOSTRING condition */ > say substr(d~string,3,6) /* Displays "Direct" */ > > For arguments to Rexx object methods, different rules apply. > When a method expects a string as an > argument, the argument object is sent the REQUEST("STRING") > message. If REQUEST returns the > NIL object, then the method raises an error. > > - The .Object's defintions/explanations of DEFAULTNAME and > OBJECTNAME: > > 6.8.5. DEFAULTNAME > >>-DEFAULTNAME------------------------------------------------->< > > Returns a short human-readable string representation of the object. > The exact form of this representation > depends on the object and might not alone be sufficient to > reconstruct the object. All objects must be able > to produce a short string representation of themselves in this way, > even if the object does not have a > string value. See Required String Values for more information. The > DEFAULTNAME method of the > Object class returns a string that identifies the class of the > object, for example, an Array or a Directory. > See also OBJECTNAME and STRING. See OBJECTNAME= for an example using > DEFAULTNAME. > > 6.8.9. OBJECTNAME > >>-OBJECTNAME-------------------------------------------------->< > > Returns the receiver object's name that the OBJECTNAME= method sets. > If the receiver object does not > have a name, this method returns the result of the DEFAULTNAME > method. See Required String Values > for more information. See the OBJECTNAME= method for an example > using OBJECTNAME. > > There is a difference between a REQUIRED string value and an automatically converted STRING value. In traditional classic Rexx contexts, non-string values are automatically converted into string values using a 2 step process: 1) Try obj~REQUEST('STRING') 1a) Raise NOSTRING if it is enabled. 2) Use the value returned by obj~STRING In places where a string is REQUIRED, only step 1 is used. For example, consider the following sequence: d = .directory~new ........................................... rexxtry.rex on WindowsNT say d a Directory ........................................... rexxtry.rex on WindowsNT say pos(d, "a Directory") 1 ........................................... rexxtry.rex on WindowsNT say "a Directory"~pos(d) Oooops ! ... try again. Incorrect call to method Method argument 1 must have a string value The POS built-in function does automatic conversion, since it is a traditional Rexx context (as does the SAY instruction). The POS method requires that it receive a string value, so it raises an error message. OBJECTNAME/DEFAULTNAME are just part of the default object implementation of the STRING method. That is the method that ends up creating the string "a Directory", but it checks for other things first before falling back to the final default value. Here's an example of all of these at work: a = .array~of(1,2,3) ........................................... rexxtry.rex on WindowsNT say a 1 2 3 ........................................... rexxtry.rex on WindowsNT say a~makestring 1 2 3 ........................................... rexxtry.rex on WindowsNT say a~string an Array ........................................... rexxtry.rex on WindowsNT a~objectname = "Rick's array" ........................................... rexxtry.rex on WindowsNT say a~string Rick's array Say ends up displaying the MAKESTRING value for the first two conditions, and does not attempt to raise NOSTRING because the object has a MAKESTRING method. The "a~string" directly invokes the array string() method, which is not overridden. This invokes the default Object string method, which just returns the value of "obj~OBJECTNAME". The default OBJECTNAME method checks to see if an object name was explicitly set, and if not, it returns the value of "obj~DEFAULTNAME". The default Object DEFAULTNAME method is the thing that returns the string "a Directory". The current reference documentation of ooRexx (cf. "4.1.3.17. Summary of > Methods by Class") does only list a MAKESTRING method for the .String class. > > > Unfortunately, the Array class itself lists the MAKESTRING method, which I > agree, should have never been defined for the Array class. So actually, I > would strongly suggest to remove MAKESTRING altogether from the Array class > and supply the "an Array" string instead. Anyone who uses REQUEST would be > able to deal with .nil to be returned again; those who use MAKESTRING on > array would get an error, but I would doubt that there are too many cases > for that. Those affected should be able to correct it. However in the case > of its removal, we should announce this prominently well ahead of time of > the next release, such that new code does not send directly the MAKESTRING > message to array objects. > Unfortunately, removing MAKESTRING will break a lot of programs. Originally it was implemented to create a string that was a concatenation of string values for uses in situations like a Charout() call. Removing this would result in breaking a lot of programs. Unfortunately, in the original implementation, they did't fix a special optimization bypass for Rexx primitive objects, so REQUEST('STRING') was returning .Nil, causing it to eventually return "an Array". It's fairly easy to revert that behavior back, but it's still lying there in wait if you subclass Array, since subclasses of primitive classes bypass the optimization path. Rick HTH, > > ---rony > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by DB2 Express > Download DB2 Express C - the FREE version of DB2 express and take > control of your XML. No limits. Just data. Click to get it now. > http://sourceforge.net/powerbar/db2/ > _______________________________________________ > Oorexx-devel mailing list > Oor...@li... > https://lists.sourceforge.net/lists/listinfo/oorexx-devel > > |