www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Tuple types/Anonymous structs

reply "John C" <johnch_atms hotmail.com> writes:
Python has the concept of a tuple to pack a set of values into a single, 
unnamed type. These would be useful in situations when, for example, a 
function needs to return more than one variable, say to indicate whether an 
operation was successful, but you don't want to define a specific type.

Currently we'd do something like this:

    bool parseCommandLine(char[] cmdline, out bool showHelp) { ... }

Which is fine, but I think tuples might be a more elegant way of doing this.

Python's syntax for declaring a tuple is

    t = 12.3, 456, 'wow'

To unpack the values, you call into it as you would a list

    t[1]

which would be 456.

I've been looking at implementing a tuple library for D, studying similar 
concepts from other languages and library implementations (C++ boost, etc). 
A rough stab might look like this:

    class Tuple(First, Second) {

        this(First first, Second second) {
            first_ = first;
            second_ = second;
        }

        First first() { return first_; }
        Second second() { return second_; }

        private First first_;
        private Second second_;
    }

And you could use it like so:

    Tuple!(bool, bool) parseCommandLine(char[] cmdline) {
        ...
        return new Tuple!(bool, bool)(success, showHelp);
    }

    Tuple!(bool, bool) result = parseCommandLine(getCommandLine());
    bool showHelp = result.second;

An alternative would be to have a built-in tuple construct in D. They're 
essentially anonymous structs, so the syntax might resemble the definition 
of a struct:

    struct { bool; bool } parseCommandLine(char[] cmdline) {
        return { success, showHelp };
    }

    struct { bool; bool } result = parseCommandLine(getCommandLine());
    bool showHelp = result[1];

The advantages of a built-in version over a library are not clear at this 
stage, but it does look a little cleaner and slightly more succinct. What do 
people think of these ideas? Where else might tuples be useful? Would people 
like to see a tuple library for D, or have support for them built into the 
language? 
Apr 01 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <d2jmqn$smi$1 digitaldaemon.com>, John C says...
An alternative would be to have a built-in tuple construct in D. They're 
essentially anonymous structs, so the syntax might resemble the definition 
of a struct:

    struct { bool; bool } parseCommandLine(char[] cmdline) {
        return { success, showHelp };
    }

    struct { bool; bool } result = parseCommandLine(getCommandLine());
    bool showHelp = result[1];

The advantages of a built-in version over a library are not clear at this 
stage, but it does look a little cleaner and slightly more succinct. What do 
people think of these ideas? Where else might tuples be useful? Would people 
like to see a tuple library for D, or have support for them built into the 
language? 

I don't mean to completely deconstruct your idea, but I think what you're looking for isn't a tuple system any more than runtime struct initalization. You can still do things kind of like a tuple if the struct initalizer would work at run-time; it's broken in the same fashion as arrays.
 struct MyTuple{
     bool a, bool b;
 }

 MyTuple myfunc(){ return( {a:true,b:false} ); } // look closely :)

If you need something with N elements returned, then you're looking at using an array. I'll add that this is what scripted languages do anyhow, and they can "cheat" since their type system is usually soft; generic arrays flourish in such environments. So dynamic array and struct initalziation, when implemented, will get you most of the way there, IMO. - EricAnderton at yahoo
Apr 01 2005
parent reply "John C" <johnch_atms hotmail.com> writes:
"pragma" <pragma_member pathlink.com> wrote in message 
news:d2jssi$12up$1 digitaldaemon.com...
 In article <d2jmqn$smi$1 digitaldaemon.com>, John C says...
An alternative would be to have a built-in tuple construct in D. They're
essentially anonymous structs, so the syntax might resemble the definition
of a struct:

    struct { bool; bool } parseCommandLine(char[] cmdline) {
        return { success, showHelp };
    }

    struct { bool; bool } result = parseCommandLine(getCommandLine());
    bool showHelp = result[1];

The advantages of a built-in version over a library are not clear at this
stage, but it does look a little cleaner and slightly more succinct. What 
do
people think of these ideas? Where else might tuples be useful? Would 
people
like to see a tuple library for D, or have support for them built into the
language?

I don't mean to completely deconstruct your idea, but I think what you're looking for isn't a tuple system any more than runtime struct initalization.

The struct-like syntax was an attempt to avoid introducing a new keyword, because they're similar to structs. But perhaps you're right -- maybe what I'm after actually *is* runtime struct initialisation coupled with unnamed types.
 You can still do things kind of like a tuple if the struct initalizer 
 would work
 at run-time; it's broken in the same fashion as arrays.

 struct MyTuple{
     bool a, bool b;
 }

 MyTuple myfunc(){ return( {a:true,b:false} ); } // look closely :)


I didn't realise this was on the cards. Not quite there, as the struct will still need to be named, I assume.
 If you need something with N elements returned, then you're looking at 
 using an
 array.  I'll add that this is what scripted languages do anyhow, and they 
 can
 "cheat" since their type system is usually soft; generic arrays flourish 
 in such
 environments.

 So dynamic array and struct initalziation, when implemented, will get you 
 most
 of the way there, IMO.

 - EricAnderton at yahoo 

Apr 01 2005
parent pragma <pragma_member pathlink.com> writes:
In article <d2k0eb$1640$1 digitaldaemon.com>, John C says...
"pragma" <pragma_member pathlink.com> wrote in message 
 struct MyTuple{
     bool a, bool b;
 }

 MyTuple myfunc(){ return( {a:true,b:false} ); } // look closely :)


I didn't realise this was on the cards. Not quite there, as the struct will still need to be named, I assume.

The naming of types in D would be the only "fly in the ointment" to the type of functionality you crave. However, using a formal type declaration is a little less wordy than what you'd have to do with anonymous structs:
 struct{bool a,b} myfunc(){return{a:true,b:false};}  // small as I can make it

For what it's worth there's another proposal that's been floating about for over a year now. Some feel that what is needed is an 'autotype' or 'implicit' keyword that forces the compiler to use type deduction instead of a formal declartion. In which case, the method signature becomes:
 autotype myfunc(){return{a:true,b:false};} // much easier on the eyes
 autotype foo = myfunc(); // foo is now a struct with members a and b

The concept is borrowed directly from the C++0x language draft/proposal. However, I gather that this won't make it into D anytime soon. :( - EricAnderton at yahoo
Apr 02 2005
prev sibling next sibling parent "Charlie" <charles jwavro.com> writes:
Looks good.  I like it as a library addition, Im not sure it would work well
as a language feature might cause some troubles with name resolution, but I
would use the lib :).

Charlie

"John C" <johnch_atms hotmail.com> wrote in message
news:d2jmqn$smi$1 digitaldaemon.com...
 Python has the concept of a tuple to pack a set of values into a single,
 unnamed type. These would be useful in situations when, for example, a
 function needs to return more than one variable, say to indicate whether

 operation was successful, but you don't want to define a specific type.

 Currently we'd do something like this:

     bool parseCommandLine(char[] cmdline, out bool showHelp) { ... }

 Which is fine, but I think tuples might be a more elegant way of doing

 Python's syntax for declaring a tuple is

     t = 12.3, 456, 'wow'

 To unpack the values, you call into it as you would a list

     t[1]

 which would be 456.

 I've been looking at implementing a tuple library for D, studying similar
 concepts from other languages and library implementations (C++ boost,

 A rough stab might look like this:

     class Tuple(First, Second) {

         this(First first, Second second) {
             first_ = first;
             second_ = second;
         }

         First first() { return first_; }
         Second second() { return second_; }

         private First first_;
         private Second second_;
     }

 And you could use it like so:

     Tuple!(bool, bool) parseCommandLine(char[] cmdline) {
         ...
         return new Tuple!(bool, bool)(success, showHelp);
     }

     Tuple!(bool, bool) result = parseCommandLine(getCommandLine());
     bool showHelp = result.second;

 An alternative would be to have a built-in tuple construct in D. They're
 essentially anonymous structs, so the syntax might resemble the definition
 of a struct:

     struct { bool; bool } parseCommandLine(char[] cmdline) {
         return { success, showHelp };
     }

     struct { bool; bool } result = parseCommandLine(getCommandLine());
     bool showHelp = result[1];

 The advantages of a built-in version over a library are not clear at this
 stage, but it does look a little cleaner and slightly more succinct. What

 people think of these ideas? Where else might tuples be useful? Would

 like to see a tuple library for D, or have support for them built into the
 language?

Apr 01 2005
prev sibling next sibling parent Sean Kelly <sean f4.ca> writes:
In article <d2jmqn$smi$1 digitaldaemon.com>, John C says...
I've been looking at implementing a tuple library for D, studying similar 
concepts from other languages and library implementations (C++ boost, etc). 

This approach works fairly well, and can be extended to to hold as many values as needed. But it's obviously not as elegant as a pure language solution. At this point, however, I think a language solution would be a 2.0 feature.
An alternative would be to have a built-in tuple construct in D. They're 
essentially anonymous structs, so the syntax might resemble the definition 
of a struct:

    struct { bool; bool } parseCommandLine(char[] cmdline) {
        return { success, showHelp };
    }

    struct { bool; bool } result = parseCommandLine(getCommandLine());
    bool showHelp = result[1];

I like the general idea, but combining struct and array syntax in that way seems a tad awkward. Either way, this would combine well with auto types: implicit s = parseCommandLine(cmdline); (I used "implicit" because I couldn't remember the keyword suggested for this particular feature) Sean
Apr 01 2005
prev sibling next sibling parent Georg Wrede <georg.wrede nospam.org> writes:
John C wrote:
 Python has the concept of a tuple to pack a set of values into a single, 
 unnamed type. These would be useful in situations when, for example, a 
 function needs to return more than one variable, say to indicate whether an 
 operation was successful, but you don't want to define a specific type.
 
 Currently we'd do something like this:
 
     bool parseCommandLine(char[] cmdline, out bool showHelp) { ... }
 
 Which is fine, but I think tuples might be a more elegant way of doing this.

For this to be useful, the language should be changed so that in principle any function can return tuples. (Examples: APL, Euphoria, etc.) Also, function calls should then implicitly handle the situations where too many or too few "items" are returned. And, if we go that way, then the usefulness would be multiplied by teaching people to make every function accept an (in principle) unlimited number of parameters, and to also return an (in principle) unlimited number of "items". But as an isolated feature, I think the usefulness is questionable. We can return references to arrays or structures, etc., when we really need to "return tuples". And we do already have out parameters. This is a big issue, and goes to the fundamentals of a language. D being "C family", it sits uneasily in D. Also, the current restrictions on what you can return, make the compiler and language more consistent. But, implemented in some library, this could be nice. Hey, we need a CDAN -- The Comprehensive D Archive Network ! :-)
Apr 02 2005
prev sibling parent reply "John C" <johnch_atms hotmail.com> writes:
After trying various ways of implementing a tuple type for multiple return 
values, I'm not terribly happy with the result. The lack of implicit 
template instantiation forced me to dump my preferred approach (which was 
based on Boost's tuple). The code required to access elements would have 
been too unwieldy.

Also, allowing templated classes with the same name to inherit from one 
another would have made the implementation simpler and smaller.

Anyway, I've attached a proof-of-concept version. I'm prepared for any 
criticism, but equally invite ideas for improvement. It's basically a set of 
template classes that work the same as your standard Pair<A, B> class, 
except you can have up to 15 elements.

Here's how to use it:

    Tuple!(float, float) getCoordinates() {
        return new Tuple!(float, float)(x, y);
    }

    Tuple!(float, float) coord = getCoordinates();

John. 
Apr 02 2005
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
I like the concept, but have a couple of comments:

1) Perhaps this should be a struct with an opCall rather than a class? 
My impression is that these sorts of Tuples are likely to be used 
by-value, and taht users will want it to be lightweight (otherwise, 
they'll just bite the bullet and use out parameters).

2) I know that it's sort of killing a fly with a sledgehammer, but you 
can simulate implicit template instantiation by overloading a function a 
gazillion times:

Tuple!(float, foat) TupleX(float a,float b)
   { return new Tuple!(float,float)(a,b); }

Obviously, it would only support standard types (plus any number of user 
types that you add), and would get absolutely massive as the tuples get 
to have lots of arguments, but it is technically possible.   Build it 
with a script. :)  Maybe if we have enough pain doing stuff like this, 
it will induce Walter to implement implicit instantiation.
Apr 02 2005
parent "John C" <johnch_atms hotmail.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message 
news:d2msva$svr$1 digitaldaemon.com...
I like the concept, but have a couple of comments:

 1) Perhaps this should be a struct with an opCall rather than a class? My 
 impression is that these sorts of Tuples are likely to be used by-value, 
 and taht users will want it to be lightweight (otherwise, they'll just 
 bite the bullet and use out parameters).

Yes, that's more in line with my original idea. I'll do that.
 2) I know that it's sort of killing a fly with a sledgehammer, but you can 
 simulate implicit template instantiation by overloading a function a 
 gazillion times:

 Tuple!(float, foat) TupleX(float a,float b)
   { return new Tuple!(float,float)(a,b); }

 Obviously, it would only support standard types (plus any number of user 
 types that you add), and would get absolutely massive as the tuples get to 
 have lots of arguments, but it is technically possible.   Build it with a 
 script. :)  Maybe if we have enough pain doing stuff like this, it will 
 induce Walter to implement implicit instantiation.

Ah! If I can get my head around how to do that...
Apr 02 2005