String concatenation feature or bug?

Found this the usual way (meaning the hard way):

Background: 2024-10-13,06:25:21 beginLP _nextPos 0

		l_pos = '_' + _nextPos;
		_util.logTime("requestLogPos " + _nextPos + ", l_pos " + l_pos);
		
Background: 2024-10-13,06:25:21 requestLogPos 0, l_pos _

		l_pos = "_" + _nextPos;
		_util.logTime("requestLogPos " + _nextPos + ", l_pos " + l_pos);

Background: 2024-10-13,06:25:21 requestLogPos 0, l_pos _0

Characters can work, as in this:

	public function httpURL(php, rest) {
		return _host + php + '/' + G_uID + '_' + System.getTimer() + '_' + _httpRetrys + '/' + rest;
	}

		_util.logTime("requestLogPos l_pos " + l_pos + ", l_url " + l_url);
	
Background: 2024-10-13,06:25:21 requestLogPos l_pos logPos_0, l_url https://my.example.com/g1/lp/ffa0f28f1a9e91d2133a05fc4ff987c817fb2ab4_361254406_0/logPos_0

Multiple characters OK, single characters bad and have to use string as workaround. Normally it wouldn't matter except that strings are objects which add up after a while.

  • Why do you keep screenshotting and quoting the same text that I quoted first as if I didn't quote it first?

    "The + operator is also used to concatenate String values."?

    Right, I never said "+" isn't the String concatenation operator. I said "+" isn't the Char/String concatenation operator.

    String concatenation, not Char/String concatenation

    Idk how many times I have to call out that distinction.

    In all the cases where characters (or other non-string types) are concatenated with the "+" operator, they are (effectively) implicitly converted to string first. As I mentioned above, there are only two concatenation rules to learn here:

    1) If one or both operands are Strings, any non-String operand is (effectively) implicitly converted to String, and concatenation occurs

    2) If both operands are Chars, they are both (effectively) converted to String and concatenation occurs

    Any other use of "+" will not result in string concatenation.

    Just try to let go of the assumption that "+" should work the same for String and Char data types. Or don't. Either way Garmin won't change this.

  • Would you also say that the C compiler is inconsistent/nondeterministic in this regard:

    char *s1 = "abcd" "ef"; // results in "abcdef"
    char *s2 = 'a' 'b'; // compilation error
    char *s3 = "abcd" 'e'; // compilation error

    Hey look, it's a concatenation operation which works on string literals and not character literals.

  • Back to the prize, what are the use cases for doing math with chars besides a caesar cipher or looping through the alphabet?

  • Help me out here. What does the text in the red ellipse in the Monkey C Language Reference say if it does not say:

    "The + operator is also used to concatenate String values."?

    People have repeatedly said + was a STRING concatenation operator. 

  • Keep moving the goalposts.

    1) misunderstand the nature of the observed behavior, arguing it must be a bug

    2) when the behavior is explained, argue that it's non-deterministic or inconsistent

    3) when that fails, argue that it's useless

    Apparently your use case for chars (and the only valid use case) is to save memory/cpu cycles although I don't think you've ever verified that there's any noticeable performance/memory impact with your code vs similar code which uses only strings.

    After all, you realize that when you type an expression like "A" + 'b' + x + "defgh" + y (I've helpfully omitted the types of x and y, just like the OP), the runtime is almost certainly creating temporary intermediate strings at each concatenation, which would clearly be inefficient.

    i.e. It's likely that first "A" and 'b' are concatenated, forming "Ab" (a temporary string). Then "Ab" has to be concatenated with x, creating a 2nd temporary string. Then that 2nd temporary string is concatenated with "defgh". And so on.

    And it's entirely possible that when you type "A" + 'b', the runtime is in fact literally converting 'b' to a String first (instead of only effectively doing so), which would negate any theoretical performance savings. Ofc neither of us knows what's actually happening here. (I concede that Garmin would be wise to avoid a superfluous conversion to String if it's possible to do so without writing too much extra code, assuming that a conversion from Char to String is more expensive than the overhead of the specialized code to directly concatenate a String and a Char.)

    Maybe you should create your own StringBuilder-like class (or helper function) which takes an array of objects, converts each element to a string, and concatenates all of them without creating unnecessary temporary strings? Then you could have your cake and eat it too, except for the overhead associated with the helper function, of course.

    Who knows, this might even be more efficient than native concatenation, if you do huge amounts of string concats in your app (which seems unlikely for a Monkey C app but who knows.)

    Something like this:

    function cat(list as Array<Object>) as String {
        const stringOrCharList = new Array<String or Char>(list.size());
        var totalLength = 0;
        for (var i = 0; i < list.size(); i++) {
            if (list[i] instance of String or list[i] instance of Char) {
                stringOrCharList[i] = list[i];
                if (list[i] instance of Char) {
                    totalLength += 1;
                } else {
                    totalLength = list[i].length();
                }
            } else {
                stringOrCharList[i] = list[i].toString();
                totalLength += stringOrCharList[i].length();
            }
        }
    
        const charArray = new Array<Char>(totalLength);
        var lengthWritten = 0;
        for (var i = 0; i < stringOrCharList.size(); i++) {
            if (stringOrCharList[i] instance of Char) {
                charArray[lengthWritten] = stringOrCharList[i];
                lengthWritten += 1;
            } else {
                for (var j = 0; j < stringOrCharList[i].length(); j++) {
                    // Using substring instead of accessing chars directly
                    // because idk if toCharArray() is O(1) or O(n).
                    // If it's O(1), then it would be better to use toCharArray()
                    // and access the chars directly.
                    // Hopefully substring is as efficient as possible
                    charArray[lengthWritten] = stringOrCharList[i].substring(j, j+1);
                    lengthWritten += 1;
                }
            }
        }
    
        return StringUtil.charArrayToString(charArray);
    }

    (This function is called "cat" because the forum apparently thinks "concat" followed by parens is a code injection attack.)

    If the only use case for the Char type is to save memory and speed up concatenations, then perhaps Garmin could just do away with the Char type altogether and optimize single-length strings under the covers.

  • You don’t need ‘A’ + 1 to concatenate. 

    Concatenation is done on strings.

    If you want concatenation, do so with an explicit string. That would be fine to do because you are getting strings with concatenation in any/every case.

    (It appears you think strings would be avoided by the behavior you want. That’s not true: it wouldn’t avoid the use of strings.)

    Your concern is pointless anyway. Garmin isn’t going to change the language and easy alternatives exist to get the result you want.

  • Is there a use case for char + number?

  • But 'A' + 1 is so much more efficient than "A" + 1!!1111!

    Like flocsy said, if predictability and excess code are considerations, then use x + "" to coerce your values to string with (theoretically) less overhead than toString(), while preserving your char literals.

    e.g. Instead of 'A' + x, you could use 'A' + "" + x

    Ofc it's not at all clear that the 2nd option is any better than "A" + x

  • Is there a use case for char + number?

    Ask the CIQ team, the designers of Java, Dennis Ritchie (the inventor of C), etc.

  • Is there a use case for char + number?

    If it were concatenation, you’d be getting implicit conversions to strings (you would NOT be avoiding the use of strings).

    It would duplicate other existing concatenation expressions. So, nothing would be added but the ability to add integers to chars would be removed.

    There isn’t a use case for it being concatenation since other expressions exist for that.