New users sometimes wonder why the "Arduino language" doesn't provide the kind of concatenation or streaming operations they have become accustomed to in Java/VB/C#/C++, etc.
Serial.print("The button was pressed " + counter + " times."); // newbie q: why doesn't this work?
I myself chafe at having to synthesize streams with clumsy blocks of repetitive code like this:
This syntax is familiar to many, is easy to read and learn, and, importantly, consumes no resources. (Because the operator functions are essentially just inline aliases for their print() counterparts, no sketch gets larger or consumes more RAM as a result of their inclusion.)
Who would support providing these in a future revision of Print?
Here is a fragment from the communications example sketch, asciiTable.pde:
Serial.print(number, BYTE); // prints value unaltered, first will be '!'
Serial.print(", dec: ");
Serial.print(number); // prints value as string in decimal (base 10)
Serial.print(", hex: ");
Serial.print(number, HEX); // prints value as string in hexadecimal (base 16)
Serial.print(", oct: ");
Serial.print(number, OCT); // prints value as string in octal (base 8)
Serial.print(", bin: ");
Serial.println(number, BIN); // prints value as string in binary (base 2)
I'm hoping to add a string library / class at some point which should (I hope) provide concatenation capabilities. I think that might be more elegant than introducing the << operator.
Having written string class libraries for PC platforms in the past, I briefly considered what it would take to write one for Arduino, but came to the conclusion -- and please correct me if I'm wrong -- that Arduino's tight 1K memory space would make it impossible to write one that was both useful and robust.
I assume you envision each string object having a dynamically allocated buffer? What happens when the allocation fails? Simple concatenations, for example,
string str = "Counter value is: ";
str += counter;
str += " rpms";
consume lots of extra RAM, at least temporarily.
Or do you propose having each string object having its own static buffer? This has its shortcomings too, of course.
I appreciate the positive feedback but am sorry to say that your example doesn't in fact work correctly, because
Serial << (9, HEX); //ignores 9 and prints 16 -- the value of HEX
is not the same thing as
Serial.print(9, HEX); // prints 9 in HEX format
The insertion operators, alas, do not work with the modifiers OCT, HEX, etc., and I don't think there is any way that using them can actually reduce the size of your code.
This week I realized that even if streaming doesn't get into Print.h, you can get all the benefit by adding just a single line at the top of your sketch (or any header):
This one (admittedly ugly) line allows you to write code like:
Serial << "My name is " << name << " and I am " << age << " years old.";
I'm afraid my proposal to have this included in the system is not likely to go very far. On the developer's forum, Nicholas Zambetti noted that as Arduino is "part of the Processing family", we "should be mindful to adopt only technically and stylistically compatible syntax".
I don't think I quite understand the syntax. Are you choosing to override the existing "<<" operator to cause immediate function execution (and in that case could some other operator be uses as well?) Or is "<<" already magical in some way ("streaming" ??)
"adopt only technically and stylistically compatible syntax"
Well, if we were to take that literally then we should be doing chip code in java, or processing
cout<< was one of the things I did like about C++, and I always liked function chaining since the smalltalk days. I think it is an interesting example you have there. Returning void all the time doesn't do anyone any good (unless you are optimizing). Return self at least.
If lines upon lines of print statements are "stylistic", then, well, they aren't, so never mind
I don't think I quite understand the syntax. ... Or is "<<" already magical in some way ("streaming" ??)
When C++ started supporting "overloaded operators," the first bit of wisdom was to say, don't overload an operator with something completely different from its original intent. A Vector plus a Vector should use the operator + to add them.
But then C++ creator Bjarne Stroustrup (or "Barney Shoestrap" as some like to say) broke this sensible wisdom in a big way with operator << and operator >>. He didn't use them for shifting, but for streaming. It's a love/hate thing with C++ programmers. Some love it, some absolutely loath it.
The usage mikalhart shows is quite common: it lets you bang a bunch of things through the various print() methods in sequence, using only one expression. I think his idea to include it in the Print header makes a lot of sense, even if I'm not too warm on the syntax.
If print() returned a reference, *this, you could do the same with Serial.print(x).print(y).print(z), but that's not obvious either.
@dcb: Part of the beauty of it is that the "return self" stuff IS optimized out! It's no different at runtime than the series of Serial.prints.
@halley: I think I read a Stroustrup interview once in which tried to justify '<<' as the best choice among all available left-to-right binding operators. You might have preferred something like
Serial += "Age: " += age;
but because += binds right-to-left it would print things backwards.
mikalhart: I really like this addition, but I'm not sure it makes sense in the Arduino core. I would encourage you to document it on the Code library page on the playground: Arduino Playground - GeneralCodeLibrary as I'm sure there are a lot of people who would find it useful.
I am coming around to this point of view myself, mellis. I appreciate Massimo's comment (on the developers' list) that we try to keep the core as simple as possible and use the libraries for everything else.
Cool. But please do post this to the playground (or somewhere). Because while it's good to have a small, simple, consistent core, it's also good to have an varied, easily accessible selection of more advanced (or just different) things for people to use. I added a reference to the playground page from the Reference in the hopes that it would make it easier for people to find and share useful code that doesn't necessarily fit in the core. Other suggestions for helping capture this sort of thing are very welcome.
I'm not using the Arduino core, but the Sanguino one (based on the ATmega 644p). Do you have any idea where the problem can be? I'm not quite used to this level of programming...
Can you post your whole sketch? It must be something about the context. The Print class wasn't supported until Arduino 0012; it's probably not available in your version.