digitalmars.D - Partial return type specification
- bearophile (30/30) Oct 03 2010 This post is probably silly, so feel free to ignore it :-)
- bearophile (3/4) Oct 03 2010 That's just a static iterable interface, I guess. It was discussed here ...
- Daniel Murphy (7/7) Oct 03 2010 Maybe typeof(return) is what you're looking for? *
- bearophile (4/13) Oct 04 2010 That works, thank you. Yes, I am looking for syntax sugar for that code.
- Pelle (12/25) Oct 04 2010 You can hack it with a string mixin :-)
- bearophile (18/20) Oct 04 2010 Your solution looks cute enough, I may even try to use it. But a templat...
- bearophile (8/20) Oct 11 2010 Ideally the partial specification syntax for ranges may work at the call...
- Pelle (4/24) Oct 11 2010 This I would very much like. Also, being able to specify that you return...
- Peter Alexander (10/28) Oct 12 2010 So basically these 'partial types' are like implicit static-polymorphism...
This post is probably silly, so feel free to ignore it :-) As function return type I am able to use the correct type, as in the bar() function below, or 'auto' that's a Jolly that works for any type, and is useful when the type is very complex: import std.algorithm: map, equal; /* Range!int */ auto foo() { return map!("a * a")([1, 2, 3, 4]); } /* Range!int */ int[] bar() { return [1, 2, 3, 4]; } void main() { assert(equal(foo(), [1, 4, 9, 16])); assert(equal(bar(), [1, 2, 3, 4])); } But in some situations I've felt the need of something intermediate, like a way to say that the output of the function is an iterable of int values (instead of strings or floats), like a Range!int. Even using this annotation, the actual return type of the function foo() doesn't change, it's still a map!(), so the Range!int acts just like the generic "auto", the difference is that the compiler gives a compile error if the result isn't an iterable of ints. So I am talking about something like (this doesn't compile because I think you can't use 'auto' with functions with a out() contract): import std.algorithm: map, equal; import std.traits: ForeachType, Unqual; auto foo() out(result) { static assert(is(Unqual!(ForeachType!(typeof(result))) == int)); } body { return map!("a * a")([1, 2, 3, 4]); } void main() { assert(equal(foo(), [1, 4, 9, 16])); } Bye, bearophile
Oct 03 2010
But in some situations I've felt the need of something intermediate, like a way to say that the output of the function is an iterable of int values (instead of strings or floats), like a Range!int.That's just a static iterable interface, I guess. It was discussed here in past. Bye, bearophile
Oct 03 2010
Maybe typeof(return) is what you're looking for? * auto foo() { return map!("a * a")([1, 2, 3, 4]); static assert(is(Unqual!(ForeachType!(typeof(return))) == int)); } * Not tested, I don't know if it works like this at all.
Oct 03 2010
Daniel Murphy:Maybe typeof(return) is what you're looking for? * auto foo() { return map!("a * a")([1, 2, 3, 4]); static assert(is(Unqual!(ForeachType!(typeof(return))) == int)); } * Not tested, I don't know if it works like this at all.That works, thank you. Yes, I am looking for syntax sugar for that code. Bye, bearophile
Oct 04 2010
On 10/04/2010 01:33 PM, bearophile wrote:Daniel Murphy:You can hack it with a string mixin :-) string assertReturnsRangeOf(T)() { return "static assert (is(Unqual!(ForeachType!(typeof(return))) == " ~ T.stringof ~ "));"; } auto foo() { return map!q{a*a}([1,2,3,4,5]); mixin (assertReturnsRangeOf!int); } You were probably looking for a more general and, well, good, solution. This does however convey some intent, and kind of works.Maybe typeof(return) is what you're looking for? * auto foo() { return map!("a * a")([1, 2, 3, 4]); static assert(is(Unqual!(ForeachType!(typeof(return))) == int)); } * Not tested, I don't know if it works like this at all.That works, thank you. Yes, I am looking for syntax sugar for that code. Bye, bearophile
Oct 04 2010
Pelle:You were probably looking for a more general and, well, good, solution. This does however convey some intent, and kind of works.Your solution looks cute enough, I may even try to use it. But a template seems better than a function template (because eventually functions are supposed to require the () to be called): import std.algorithm: map, equal; import std.traits: ForeachType, Unqual; template AssertReturnsRangeOf(T) { enum string AssertReturnsRangeOf = "static assert (is(Unqual!(ForeachType!(typeof(return))) == " ~ T.stringof ~ "));"; } auto foo() { return map!q{a*a}([1,2,3,4]); mixin(AssertReturnsRangeOf!int); } void main() { assert(equal(foo(), [1, 4, 9, 16])); } Bye, bearophile
Oct 04 2010
Pelle:string assertReturnsRangeOf(T)() { return "static assert (is(Unqual!(ForeachType!(typeof(return))) == " ~ T.stringof ~ "));"; } auto foo() { return map!q{a*a}([1,2,3,4,5]); mixin (assertReturnsRangeOf!int); } You were probably looking for a more general and, well, good, solution. This does however convey some intent, and kind of works.Ideally the partial specification syntax for ranges may work at the calling point too: void main() { Range!int results = foo(); } Here results is of its specific type, it's not a "Range!int", so Range!int works as "auto". The difference is that the compiler makes sure that's an iterable of ints, and not an iterable of floats or a not iterable, etc. Bye, bearophile
Oct 11 2010
On 10/11/2010 10:56 PM, bearophile wrote:Pelle:This I would very much like. Also, being able to specify that you return a Range!int or ForwardRange!int would be very useful. Without losing the value types, of course. :-)string assertReturnsRangeOf(T)() { return "static assert (is(Unqual!(ForeachType!(typeof(return))) == " ~ T.stringof ~ "));"; } auto foo() { return map!q{a*a}([1,2,3,4,5]); mixin (assertReturnsRangeOf!int); } You were probably looking for a more general and, well, good, solution. This does however convey some intent, and kind of works.Ideally the partial specification syntax for ranges may work at the calling point too: void main() { Range!int results = foo(); } Here results is of its specific type, it's not a "Range!int", so Range!int works as "auto". The difference is that the compiler makes sure that's an iterable of ints, and not an iterable of floats or a not iterable, etc. Bye, bearophile
Oct 11 2010
On 12/10/10 7:28 AM, Pelle wrote:On 10/11/2010 10:56 PM, bearophile wrote:So basically these 'partial types' are like implicit static-polymorphism interfaces? i.e. they make guarantees about the interface, but don't require that the types explicitly derive from them? Presumably you could use these to specify template constraints as well? e.g. int gcd(InputRange!int Range)(Range r) { ... } which would be equivalent to: int gcd(Range)(Range r) if (isInputRange!Range) { ... } Seems like the logical thing to do.Ideally the partial specification syntax for ranges may work at the calling point too: void main() { Range!int results = foo(); } Here results is of its specific type, it's not a "Range!int", so Range!int works as "auto". The difference is that the compiler makes sure that's an iterable of ints, and not an iterable of floats or a not iterable, etc. Bye, bearophileThis I would very much like. Also, being able to specify that you return a Range!int or ForwardRange!int would be very useful. Without losing the value types, of course. :-)
Oct 12 2010