#64 String class methods don't alter the original string

4.0.0
closed
Rick McGuire
Reference (110)
5
2012-08-14
2007-12-12
D.M.Wooster
No

In descriptions of several methods of the String class, text says the method does something to the receiving string. In fact, the method does not change the receiving string. It returns a copy of the receiving string, changed in such-and-such way. Example:
Topic 5.1.3.42. insert
"Inserts the string new, paddded or truncated to length length, into the receiving string, after the nth character. ..."
This indicates that code such as the following should work, but it doesn't (Strings are immutable, so it can't actually work as documented):

s = "abc123";
s~insert("def",3);
say s;
/ expected result, according to doc is "abcdef123" /
/ actual result is still "abc123" /

Please correct doc. to say, for example:
"Returns a new string which is a copy of the receiving string with the string new, padded or truncated to length length, inserted after the nth character. ..."

This doc. says the above example should've been:
s = "abc123";
s = s~insert("def",3);
say s;
/ get "abcdef123" as expected and documented. /

Note:
Topic 5.1.3.16. caselessChangeStr is an example of a topic which already contains the correct wording.

The following topics appear to have the above-described problem:
5.1.3.6 Concatenation Methods
5.1.3.40. format
5.1.3.42. insert
5.1.3.53. overlay
5.1.3.55. reverse
5.1.3.58. space
5.1.3.59. strip
5.1.3.63. translate (especially the second sentence)

Discussion

  • D.M.Wooster
    D.M.Wooster
    2007-12-12

    Logged In: YES
    user_id=389721
    Originator: YES

    Additional topics affected:
    5.1.3.35. decodeBase64
    5.1.3.38. encodeBase64

     
  • TheDavidFactor
    TheDavidFactor
    2007-12-12

    Logged In: YES
    user_id=1011368
    Originator: NO

    I don't think the Concatenation Methods section is incorrect, it doesn't say it returns the object. It says it concatenates the argument with the receiver object and I believe it can be inferred that this returns a new object.

    I believe the second sentence of translate was incorrect as demonstrated by the last example. I rewrote it accordingly.

    Committed Revision 1513

     
  • TheDavidFactor
    TheDavidFactor
    2007-12-12

    Logged In: YES
    user_id=1011368
    Originator: NO

    didn't address your added comment. I don't believe the documentation for either of these methods is incorrect. I think it should already be inferable that it returns a new string object. You could word it: Returns a new string containing the base64 de/encoded version of the receiving string. But I feel that is needlessly and unnecessarily wordy.

     
  • D.M.Wooster
    D.M.Wooster
    2007-12-12

    Logged In: YES
    user_id=389721
    Originator: YES

    I haven't figured out how to view the checked-in changes, so I'm only able to respond to the comments in this bug report, not to the actual changes.

    Thanks for updating translate.

    Re Concatenation and base64 methods. It's inferrable by someone who is familiar with how ooRexx String class works, but I think it is ambiguous for people who are not familiar with how Open Object Rexx works. Therefore, I think it should explicitly state that it's returning a new string.

     
  • Hagrinas
    Hagrinas
    2007-12-12

    Logged In: YES
    user_id=1796550
    Originator: NO

    In general, the behavior of string objects is not documented clearly, especially for those not familiar with classic Rexx. In particular, with respect to Say, assignments, Use, and most methods, it can be confusing.

    We probably all take for granted what Say does, and especially how it behaved in classic Rexx. But using a string object's name in a Say statement has inherently different behavior from other objects. The documentation for Say mentions "the string value," but that won't mean much to a user who needs to look up "say" in the manual. What's really going on is that the string method is getting inherited from the object class, but what it does for each member of the collection class is not documented with each particular object. In most cases, it means that what is returned is the result of the Objectname method. But I'd never get that from looking at the documentation for Say. With strings, it's the same as using the makestring method. It may seem obvious that the makestring method is not needed since we already have a string, but we have an object and we are trying to get an attribute, so an appropriate method might make the most sense to a person reading up on ooRexx for the first time. Explaining that it's not needed could be helpful. But if you are convinced that it's obvious, it should be clear why returning the Objectname would not be obvious.

    Plus, with the previous release of ooRexx, the name of an array in a Say statement resulted in the equivalent of using the MakeString method. And that made just as much sense with respect to the documentation, since it's a "string value." The current behavior is consistent with most other objects, which arguably makes more sense. But the documentation is not explicit in that respect.

    A more fundamental issue is what happens in general when an object is mentioned by name in a statement, and there is no associated method. With explicit methods, it's pretty clear what is expected. Without them, what happens in a Say command or in an assignment statement is very different. For an assignment statement, string values are passed by value, and other objects are passed by reference. That's not spelled out in simple terms for the documentation of "Assignments and Symbols," and since SAYing the object works as above, it will boil down to trial and error for users who just read the sections on assignment statements. Trying it and then saying it might be misleading since a user could reasonably expect A=B, where B is an array, to produce a string object A with a value of "an Array."

    And within a class definition, for an object that is inheriting from the string class, self will give the value of the string, rather than needing a Use statement in Init, or using a particular method, and that is consistent with how strings work but not with what a new user might expect.

    I'd recommend augmenting the introductory section "How Objects Interact" with a discussion of what happens when there is no explicit message sent to an object. Then I'd recommend cleaning up the documentation of Assignments and Symbols. It makes things clear for strings, but the meaning could get lost with respect to other objects, since there are no examples. The documentation says "The result of expression becomes the new value of the variable named by the symbol to the left of the equal sign." Than implies that for any a=b, a will have the value of b, not become another reference to the object. The example following the statement has a literal string in it, thus not touching on the issue. The section on stems makes it clear in a comment that the adjacent assignment is by reference, and not by value. But the example could be more illustrative. Nothing in the section goes into detail about more complex objects in general, and none of the examples in this section would be any different if the behavior were different.

    For example, the documentation shows:

    hole. = "empty"
    hole.19 = "full"
    say hole.1 hole.mouse hole.19
    / Says "empty empty full" /
    hole2. = hole. / copies reference to hole. stem to hole2. /
    say hole2.1 hole2.mouse hole2.19
    / Also says "empty empty full" /

    But the result would be the same if it had passed by value. If the example were followed by

    hole.mouse = "abc"
    say hole2.1 hole2.mouse hole2.19

    then it would drive home the point that the stems correspond even though there was no hole2.=hole. after hole.mouse was changed.

    And of course using Say in all these examples glosses over the "say" problem I mentioned. If Say is what you use to see the results, then things fall apart quickly.

     


Anonymous


Cancel   Add attachments