www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Rather neat way of doing multiple return values

reply Downs <default_357-line yahoo.de> writes:
Here's a (imnsho) rather neat implementation of multiple return values from
functions.


import std.stdio;

template tuple(T...) { alias T tuple; } // basics

template ptr(T...) { // the typetuple ptr!(T) consists of pointers to the types
in T
   static if (T.length>1) alias tuple!(T[0]*, ptr!(T[1..$])) ptr;
   else alias T[0]* ptr;
}

struct multival(T...) { /// Simple holder for multiple values
   tuple!(T) v=void;
   static multival!(T) opCall(T t) { multival!(T) res=void; foreach (i, e; t)
res.v[i]=e; return res; }
}

struct ptrlist(T...) { /// List of pointers to variables
   tuple!(ptr!(T)) v=void;
   static ptrlist!(T) opCall(inout T t) {
     ptrlist!(T) res=void;
     foreach (i, e; t) res.v[i]=&t[i]; // Ignore e because I can't make it
inout anyway.
     return res;
   }
   void opAssign(multival!(T) res) {
     foreach (i, e; res.v) *v[i]=e;
   }
}

multival!(int, float) test() { return typeof(test())(2, 3.0); }

ptrlist!(T) list(T...)(inout T v) { return ptrlist!(T)(v); }

void main() {
   int e=4;
   float f=5;
   list(e, f)=test;
   writefln(e, ", ", f); // 2, 3
}

Have fun! :D
Mar 17 2007
next sibling parent reply Davidl 126.com writes:
Nice implementation!!!
i am thinking about how to get rid of those temp object pointers.

 Here's a (imnsho) rather neat implementation of multiple return values=

 from functions.


 import std.stdio;

 template tuple(T...) { alias T tuple; } // basics

 template ptr(T...) { // the typetuple ptr!(T) consists of pointers to =

 the types in T
    static if (T.length>1) alias tuple!(T[0]*, ptr!(T[1..$])) ptr;
    else alias T[0]* ptr;
 }

 struct multival(T...) { /// Simple holder for multiple values
    tuple!(T) v=3Dvoid;
    static multival!(T) opCall(T t) { multival!(T) res=3Dvoid; foreach =

 e; t) res.v[i]=3De; return res; }
 }

 struct ptrlist(T...) { /// List of pointers to variables
    tuple!(ptr!(T)) v=3Dvoid;
    static ptrlist!(T) opCall(inout T t) {
      ptrlist!(T) res=3Dvoid;
      foreach (i, e; t) res.v[i]=3D&t[i]; // Ignore e because I can't m=

 it inout anyway.
      return res;
    }
    void opAssign(multival!(T) res) {
      foreach (i, e; res.v) *v[i]=3De;
    }
 }

 multival!(int, float) test() { return typeof(test())(2, 3.0); }

 ptrlist!(T) list(T...)(inout T v) { return ptrlist!(T)(v); }

 void main() {
    int e=3D4;
    float f=3D5;
    list(e, f)=3Dtest;
    writefln(e, ", ", f); // 2, 3
 }

 Have fun! :D

Mar 17 2007
parent BCS <ao pathlink.com> writes:
Reply to davidl,

 Nice implementation!!!
 i am thinking about how to get rid of those temp object pointers.

It's all structs and pass by value. It's a little more verbose than a solution I played with, but I like the result better in other regards (mine had a left to right assignment thing going).
 Here's a (imnsho) rather neat implementation of multiple return
 values  from functions.
 
 import std.stdio;
 
 template tuple(T...) { alias T tuple; } // basics

 template ptr(T...) { // the typetuple ptr!(T) consists of pointers to
 the types in T
 static if (T.length>1) alias tuple!(T[0]*, ptr!(T[1..$])) ptr;
 else alias T[0]* ptr;
 }
 struct multival(T...) { /// Simple holder for multiple values
 tuple!(T) v=void;
 static multival!(T) opCall(T t) { multival!(T) res=void; foreach (i,
 e; t) res.v[i]=e; return res; }
 }
 struct ptrlist(T...) { /// List of pointers to variables
 tuple!(ptr!(T)) v=void;
 static ptrlist!(T) opCall(inout T t) {
 ptrlist!(T) res=void;
 foreach (i, e; t) res.v[i]=&t[i]; // Ignore e because I can't make
 it inout anyway.
 return res;
 }
 void opAssign(multival!(T) res) {
 foreach (i, e; res.v) *v[i]=e;
 }
 }
 multival!(int, float) test() { return typeof(test())(2, 3.0); }
 
 ptrlist!(T) list(T...)(inout T v) { return ptrlist!(T)(v); }
 
 void main() {
 int e=4;
 float f=5;
 list(e, f)=test;
 writefln(e, ", ", f); // 2, 3
 }
 Have fun! :D
 


Mar 17 2007
prev sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Downs wrote:
 Here's a (imnsho) rather neat implementation of multiple return values 
 from functions.
 
 (...)
 Have fun! :D

Hehehe nice :) Here's my version: --- import std.stdio; import std.bind; struct PtrTuple(P, V) { P ptrs; void opAssign(V v) { foreach (i, x; v.value) { *ptrs.value[i] = x; } } } PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) tup(T ...)(inout T t) { PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) ptrs; foreach (i, dummy_; t) { ptrs.ptrs.value[i] = &t[i]; } return ptrs; } Tuple!(int, float, char) someFunc(int i) { return tuple(i, 0.1f * i, cast(char)i); } void main() { int a; float b; char c; tup(a, b, c) = someFunc(55); writefln("a = %s", a); writefln("b = %s", b); writefln("c = %s", c); } --- Maybe Phobos could use such a utility, as it (apparently) gets reimplemented numerous times ? -- Tomasz Stachowiak
Mar 17 2007
next sibling parent reply kris <foo bar.com> writes:
Tom S wrote:
 Downs wrote:
 
 Here's a (imnsho) rather neat implementation of multiple return values 
 from functions.

 (...)
 Have fun! :D

Hehehe nice :) Here's my version: --- import std.stdio; import std.bind; struct PtrTuple(P, V) { P ptrs; void opAssign(V v) { foreach (i, x; v.value) { *ptrs.value[i] = x; } } } PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) tup(T ...)(inout T t) { PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) ptrs; foreach (i, dummy_; t) { ptrs.ptrs.value[i] = &t[i]; } return ptrs; } Tuple!(int, float, char) someFunc(int i) { return tuple(i, 0.1f * i, cast(char)i); } void main() { int a; float b; char c; tup(a, b, c) = someFunc(55); writefln("a = %s", a); writefln("b = %s", b); writefln("c = %s", c); } --- Maybe Phobos could use such a utility, as it (apparently) gets reimplemented numerous times ? -- Tomasz Stachowiak

Cool, but it's worth pointing out that this is probably Latin to most people :)
Mar 17 2007
next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
kris wrote:
 Tom S wrote:
 Downs wrote:

 Here's a (imnsho) rather neat implementation of multiple return 
 values from functions.

 (...)
 Have fun! :D

Hehehe nice :) Here's my version: --- import std.stdio; import std.bind; struct PtrTuple(P, V) { P ptrs; void opAssign(V v) { foreach (i, x; v.value) { *ptrs.value[i] = x; } } } PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) tup(T ...)(inout T t) { PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) ptrs; foreach (i, dummy_; t) { ptrs.ptrs.value[i] = &t[i]; } return ptrs; } Tuple!(int, float, char) someFunc(int i) { return tuple(i, 0.1f * i, cast(char)i); } void main() { int a; float b; char c; tup(a, b, c) = someFunc(55); writefln("a = %s", a); writefln("b = %s", b); writefln("c = %s", c); } --- Maybe Phobos could use such a utility, as it (apparently) gets reimplemented numerous times ? -- Tomasz Stachowiak

Cool, but it's worth pointing out that this is probably Latin to most people :)

Not I; in fact, I'm loving it. (Although I liked the PHP'ish use of list() for assignment. I'm strange.) Maybe we could evolve this toward a LambdaMOO/ColdC style scatter assignment. Contrived ColdC example: protected method ._cmd_viewCacheInfo { var width, depth, map, row; [width, depth, map] = cache_info(); // <- scatter .tell("Cache Width = ", width); .tell("Cache Depth = ", depth); .tell("Map: (Legend: i/I = Inactive, a/A = Active, I/A = Dity)"); for row in (map) { .tell(" ", row); // <- list spice, also available in scatter } .tell(); } I can dream. And this comes right up against it, just need a way to specify a catch-all at the end for trailing elements. -- Chris Nicholson-Sauls
Mar 17 2007
prev sibling parent nobody <nobody nix.de> writes:
Jesse Phillips Wrote:

 On Sat, 17 Mar 2007 13:00:03 -0700, kris wrote:
 
 Tom S wrote:
 Downs wrote:
 
 Here's a (imnsho) rather neat implementation of multiple return values 
 from functions.

 (...)
 Have fun! :D

Hehehe nice :) Here's my version: --- import std.stdio; import std.bind; struct PtrTuple(P, V) { P ptrs; void opAssign(V v) { foreach (i, x; v.value) { *ptrs.value[i] = x; } } } PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) tup(T ...)(inout T t) { PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) ptrs; foreach (i, dummy_; t) { ptrs.ptrs.value[i] = &t[i]; } return ptrs; } Tuple!(int, float, char) someFunc(int i) { return tuple(i, 0.1f * i, cast(char)i); } void main() { int a; float b; char c; tup(a, b, c) = someFunc(55); writefln("a = %s", a); writefln("b = %s", b); writefln("c = %s", c); } --- Maybe Phobos could use such a utility, as it (apparently) gets reimplemented numerous times ? -- Tomasz Stachowiak

Cool, but it's worth pointing out that this is probably Latin to most people :)

I agree with you here, I tried to follow how it works but am so unfamiliar with the tools used I got lost and surprised by the result. :)

Very cool. I hope, some day we can do this, like perl ($one,$two) = (split (/,/,$line))[0,2];
Apr 04 2007
prev sibling parent Jesse Phillips <Jesse.K.Phillips+Digitalmars gmail.com> writes:
On Sat, 17 Mar 2007 13:00:03 -0700, kris wrote:

 Tom S wrote:
 Downs wrote:
 
 Here's a (imnsho) rather neat implementation of multiple return values 
 from functions.

 (...)
 Have fun! :D

Hehehe nice :) Here's my version: --- import std.stdio; import std.bind; struct PtrTuple(P, V) { P ptrs; void opAssign(V v) { foreach (i, x; v.value) { *ptrs.value[i] = x; } } } PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) tup(T ...)(inout T t) { PtrTuple!(PointerTuple!(Tuple!(T)), Tuple!(T)) ptrs; foreach (i, dummy_; t) { ptrs.ptrs.value[i] = &t[i]; } return ptrs; } Tuple!(int, float, char) someFunc(int i) { return tuple(i, 0.1f * i, cast(char)i); } void main() { int a; float b; char c; tup(a, b, c) = someFunc(55); writefln("a = %s", a); writefln("b = %s", b); writefln("c = %s", c); } --- Maybe Phobos could use such a utility, as it (apparently) gets reimplemented numerous times ? -- Tomasz Stachowiak

Cool, but it's worth pointing out that this is probably Latin to most people :)

I agree with you here, I tried to follow how it works but am so unfamiliar with the tools used I got lost and surprised by the result. :)
Apr 04 2007