www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - the Result Type

reply "seany" <seany uni-bonn.de> writes:
std.algorithm.splitter seems to return all its return values as a 
type "Result", without quotes, and i dont not seem to be able to 
cast it to string[] or int[]  with cast(string[]) ( or even cast 
(string) - i tried that too).

I tried to use a function

void function(T, R)(T arr, out R output)
{

foreach(elem; arr)
{
     output ~= elemM
}
}

i have an occasion where R is int[], and one where it is 
string[]; and
but it says, that int can not be appended to string[], and string 
can not be appended to int[], and compilation fails.

Nonetheless removing either of the occasions, solves it.

how to deal with  this Result type?
Dec 08 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/08/2013 12:24 AM, seany wrote:

 std.algorithm.splitter seems to return all its return values as a type
 "Result", without quotes, and i dont not seem to be able to cast it to
 string[] or int[]  with cast(string[]) ( or even cast (string) - i tried
 that too).

 I tried to use a function

 void function(T, R)(T arr, out R output)
 {

 foreach(elem; arr)
 {
      output ~= elemM
 }
 }

 i have an occasion where R is int[], and one where it is string[]; and
 but it says, that int can not be appended to string[], and string can
 not be appended to int[], and compilation fails.

 Nonetheless removing either of the occasions, solves it.

 how to deal with  this Result type?
Many other algorithms return Result, which are independent from each other. :) (Lookup "Voldemort types".) Such types are just lazy ranges. When you eagerly need an actual array of the elements, call std.array.array on Result: import std.array; import std.algorithm; void main() { auto input = "hello world"; auto splittedWords = input.splitter(' ').array; static assert(is (typeof(splittedWords) == string[])); } Ali
Dec 08 2013
next sibling parent reply "seany" <seany uni-bonn.de> writes:
O_O

with that knowledge, would also be possible to define new types 
(not aliases, but new encapsulated types) representing things 
such as Graph, Ring, Topology, surreal number, etc?

I dont find this in your book, would you consider either adding 
this Volodemrot types, or in case they already are there, give me 
a link (both the introductions in d wiki and dr. doobs blog was 
very short)
Dec 08 2013
next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Sun, 08 Dec 2013 09:59:55 +0100
schrieb "seany" <seany uni-bonn.de>:

 O_O
 
 with that knowledge, would also be possible to define new types 
 (not aliases, but new encapsulated types) representing things 
 such as Graph, Ring, Topology, surreal number, etc?
All these Result types are simply structs. Structs with template parameters. Your question is a bit vague. You will not be able to use D algorithms on anything but "consecutive items of the same type" as I worte in my other post, if that is the question. Other than that the Result types are just: struct Result(T) { ... } You can call them "templated struct" or "generic type". Many languages offer this in some way including C++, Java, Delphi before you are probably already familiar with the concept. In the most simple form you can use them to create type specialized containers, graphs or this: struct Matrix(T, size_t width, size_t height) if (isNumeric!T) { ... } (A matrix with a fixed width and height that can be used if T is a built-in integer or floating point type.) -- Marco
Dec 08 2013
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/08/2013 12:59 AM, seany wrote:

 I dont find this in your book, would you consider either adding this
 Volodemrot types,
I think at least a short mention is in order. :) There are two reasons why they don't appear in the book (yet): 1) They are not a proper language feature, rather a happy discovery. (I remember Andrei's original newsgroup post about this discovery but I cannot find it at this time.) 2) They were discovered after I started writing the book. Ali
Dec 08 2013
parent reply "seany" <seany uni-bonn.de> writes:
On Sunday, 8 December 2013 at 11:02:40 UTC, Ali Çehreli wrote:
 (I remember Andrei's original newsgroup post about this 
 discovery but I cannot find it at this time.)
http://www.digitalmars.com/d/archives/digitalmars/D/announce/Voldemort_Types_in_D_23511.html this?
Dec 08 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/08/2013 03:41 AM, seany wrote:
 On Sunday, 8 December 2013 at 11:02:40 UTC, Ali Çehreli wrote:
 (I remember Andrei's original newsgroup post about this discovery but
 I cannot find it at this time.)
http://www.digitalmars.com/d/archives/digitalmars/D/announce/Voldemort_Types_in_D_23511.html this?
There was an earlier newsgroup post like "look what I've just discovered". Ali
Dec 08 2013
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Dec 8, 2013 at 9:59 AM, seany <seany uni-bonn.de> wrote:
 O_O

 with that knowledge, would also be possible to define new types (not
 aliases, but new encapsulated types) representing things such as Graph,
 Ring, Topology, surreal number, etc?
Other posters already answered your questions concerning ranges. In short, you can define internal structs (or classes, or functions) inside a function, another struct, a class, and return them. They can be parameterized on the host type template parameters, if any. All the different types in std.algorithm and std.range have *nothing* in common (no common base class, nor are they part of a common datatype), *except* they all respect the range 'concept'. As long as something (class or struct) has the three basic range methods (empty / front / popFront), it can be used with other functions in std.algorithm and std.range. Returning to you question, now. You can do exactly with other types what was done with ranges in the standard library. As long as you define the basic properties of a Graph / Ring / Whatever, and associate it with a guard template (see std.range.isInputRange), any type can be used as a Graph. Maybe you could give us more details on what you want to realize exactly?
Dec 08 2013
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Ali Çehreli:

 When you eagerly need an actual array of the elements, call 
 std.array.array on Result:

 import std.array;
 import std.algorithm;

 void main()
 {
     auto input = "hello world";
     auto splittedWords = input.splitter(' ').array;
Or just use the eager split() function. Bye, bearophile
Dec 08 2013
prev sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Sun, 08 Dec 2013 09:24:53 +0100
schrieb "seany" <seany uni-bonn.de>:

 std.algorithm.splitter seems to return all its return values as a 
 type "Result", without quotes, and i dont not seem to be able to 
 cast it to string[] or int[]  with cast(string[]) ( or even cast 
 (string) - i tried that too).
 
 I tried to use a function
 
 void function(T, R)(T arr, out R output)
 {
 
 foreach(elem; arr)
 {
      output ~= elemM
 }
 }
 
 i have an occasion where R is int[], and one where it is 
 string[]; and
 but it says, that int can not be appended to string[], and string 
 can not be appended to int[], and compilation fails.
 
 Nonetheless removing either of the occasions, solves it.
 
 how to deal with  this Result type?
That confused me as a beginner as well until I understood that these Result types are actually just structs. They are generated at compile-time and share commonly known methods like .front or .popFront() that identify them as "ranges". Arrays are a sub-set of ranges. The algorithms in D typically take a range as input and a range as output. Where possible they try not to go over the whole input at once, but only as needed. This is called lazy evaluation and is one reason you don't get returned a complete array. In some cases the input might even be infinite: Try returning an array for splitter over a random number generator as input range! So what do you do with a Range struct? There are 3 options: * If you really want an array you can call the function array() on the Result: * If you want to further process your Result with other algorithms, just chain them together. E.g.: arr.splitter("abc").sort.uniq(); * If you want to iterate over the Result, foreach works on those Result ranges: foreach (elem; arr.splitter("abc")) {...} The range concept makes it easy to apply any kind of algorithm on stuff that can be represented as a consecutive items of the same type. And it allows those algorithms to only do as much work as needed to get the result. A good example is http://dlang.org/phobos/std_range.html#take , which sets a limit to the number of items to be used from the input. So you can have an infinite random number generator, but only take the first 50 numbers like so: randomGen.take(50); By the way File("myfile").byLine() gives you a range over the lines of text of "myfile". That's quite handy if you have an array of strings like a dictionary in a text file. -- Marco
Dec 08 2013