JAN
24
2004
|
An Alternative Syntax for Multiple Return Values in C-based LanguagesMost functions do not need more than one return value, but when you need
// implementation: int parseInt(const char *str, bool *success) { const char *s = str; int r = 0; while (*s) { char c = *s; if ((c < '0') || (c > '9')) { *success = false; return 0; } r = r * 10 + (c - '0'); } *success = true; return r; } // invocation: bool s; int v = parseInt("2004", &s);
// implementation: int parseInt(const char *str, bool *success = 0) { const char *s = str; int r = 0; while (*s) { char c = *s; if ((c < '0') || (c > '9')) { if (success) *success = false; return 0; } r = r * 10 + (c - '0'); } if (success) *success = true; return r; } // invocation int v = parseInt("2004");
// implementation: int parseInt(const char *str, bool &success) { const char *s = str; int r = 0; while (*s) { char c = *s; if ((c < '0') || (c > '9')) { success = false; return 0; } r = r * 10 + (c - '0'); } success = true; return r; } // invocation: bool s; int v = parseInt("2004", s);
// implementation: int parseInt(String str, out bool success) { char s[] = str.ToCharArray(); int r = 0; foreach (char c in s) { if ((c < '0') || (c > '9')) { success = false; return 0; } r = r * 10 + (c - '0'); } success = true; return r; } // invocation: bool s; int v = parseInt("2004", out s);
Disadvantages:
Using Python-style tuples An alternative to the C# syntax would be using Python-like tuples. int x, y, z; (x, y, z) = (1, 2, 3); // The equivalent of the last line is: x = 1; y = 2; z = 3; // The source tuple can contain expressions as items: (x, y) = (z-2, 5*5); // the right side can have more items than the left (but not the other way round): (x, y) = (1, 2, 3, 4, 5); // the left side can be a regular value; then only the first item is taken: x = (1, 2, 3); // local variable declaration in a tuple (int a, int b, int c) = (10, 20, 30); // A tuple can combine several types, as long as the types of both sides match: (x, bool f, double d) = (5, true, 3.14); // Unlike other languages, the assignment is processed item-by-item: (x, y) = (5, 10); (x, y) = (y, x); // now a and b are both 10! Swapping is not possible. // When you embed the statement it returns the first item's value: if ( (f, a) = (true, x) ) { // always executed }
Note that tuples only exist as a helper construct for assignments. You can not use Now that there are tuples it becomes easy to extend the function syntax to have // implementation: (int, bool) parseInt(String str) { char s[] = str.ToCharArray(); int r = 0; foreach (char c in s) { if ((c < '0') || (c > '9')) return (0, false); r = r * 10 + (c - '0'); } return (r, true); } // invocation: (int v, bool s) = parseInt("2004");
What I like most about that syntax is that it makes the code more compact. In int v = parseInt("2004");
You can name the return value and then use it like a C# reference void inc2(ref int number1, ref int number2) { number1++; number2++; } could be written as (int number1, int number2) inc2(int number1, int number2) { number1++; number2++; } Note that input and output values have the same name and no return (int r = 0, bool success = true) parseInt(String str) { char s[] = str.ToCharArray(); foreach (char c in s) { if ((c < '0') || (c > '9')) return (0, false); r = r * 10 + (c - '0'); } } Another two LOC's less. As tuples can have only a single item, it's also possible (int r) add(int a, int b) { r = a+b; } To summarize it, I think that tuples are a better solution for the multiple-return-value problem than argument references. They feel more natural because they bundle input and output values in declaration and invocation. The concept is closer to the Smalltalk concepts of messages, which makes it easier to create bindings to message-based protocols like SOAP. And last but not least it would help you to write shorter code.
|
![]() |
Comments
Just some thoughts to the c++
Just some thoughts to the c++ variant
>int parseInt(const char *str, bool &success)
>Disadvantages:
>The invocation does not have any hint that the second argument will be modified.
It has. If it wasn't supposed to be modified it would have been const bool& instead of bool&
A reference without const modifier as function argument should usually be "output values", at least atm i don't see a reason to have a non-const reference for any other purpose.
>Default values are not possible, you always need to have a bool even if you do not look at it
I'm not sure i'm getting this(probably you mean something else, than i understand), but default values are of course possible for reference parameters.
There is even a way to get your tuples in c++, e.g. take a look at Loki::Tuple.
Re: Just some thoughts to the c++
If it wasn’t supposed to be modified it would have been const bool&
instead of bool&
Hmm.. you're right, didn't think of it. You would have depend on the API developer to use const for all unmodified values though, and it does not answer the question whether the argument will be read or not.
I’m not sure i’m getting this(probably you mean something else, than I understand), but default values are of course possible for reference parameters.
But they don't do what you want. You can't write
to save the API user from giving the second argument. You can avoid the problem by working around it with a second variable
but I would call that extremely ugly, and it won't look good in the API docs.
> There is even a way to get your tuples in c++, e.g. take a look at
>Loki::Tuple.
You can emulate almost every feature with plain C and a preprocessor, the only difference is how short and concise the syntax is.
Why not do:
Why not do:
int parseInt( const char *str );
...
try
{
int v = parseInt( "2006" );
} catch(...) {
...
}
This is C++ after all :D
A reference without const mod
A reference without const modifier as function argument should usually be “output values".
Or an input/output value. In this later case it would need to be initialized. I remember Ada let you specify if a parameter is "in", "out" or "in out". Does C# has "in out" too?
A reference without const mod
Does C# has “in out
C++ Templates: std::pair and QPair
You can easily achieve what you proposed with a simple C++ struct template:
Of course, the ugly thing is that you must write code like this to use that function:
The first problem could be easily alleviated by adding a cast operator to the first type of the template.
Further improvements would call for more arguments than just two typenames to the template, as well as an assignment operator (and copy constructor) against other, larger tuples.
Talking about the cost of such constructs, remember that practically every ABI out there has a method of returning ONE and one only return value. So, extending this to multiple values necessarily introduces the need of a structure and, therefore, an implicit first parameter.
Assume using namespace std;, since writing std::pair requires quoting the second : to :. How do I make paragraphs in here?
ABIs
Talking about the cost of such constructs, remember that practically every ABI out there has a method of returning ONE and one only return value. So, extending this to multiple values necessarily introduces the need of a structure and, therefore, an implicit first parameter.
It's hardly possible with the Linux binary ABI or Java, but quite easy with CLI. Just add every 'out' argument to the list of return values, and have every 'ref' argument in both lists.
How do I make paragraphs in here?
<br><br> :)
It's quite messy, but I am getting used to escaping text on this site. Since I started posting code snippets www.asciitable.org became one of my most frequently visited sites...
Tuples and C++ Standard
Tuples will be a part of the upcoming C++ Standard.
For more information: http://std.dkuug.dk/jtc1/sc22/wg21/docs/library_technical_report.html or http://www.cuj.com/documents/s=8250/cujcexp2106sutter/
Re: Tuples and C++ Standard
Thanks, interesting, didn't know that. My problem with most template-based features is that they create pretty verbose code, and the compilers create horrible error messages when you do something wrong.
tuples available in boost
The code for the proposed extensions already exists as part of boost (same author):
http://www.boost.org/libs/tuple/doc/tuple_users_guide.html
BTW... Jan, your article series is quite interesting to read. Great stuff!
Pages