www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - returning different types via function

reply "seany" <seany uni-bonn.de> writes:
Consider this:

I have a function FUNC, it takes a string array, and does 
something with it, and retruns the same. Implemented based on a 
previous thread, here is what i have

string[] FUNC (ref string[] ZZ)
{
/*
do something
*/
}

and the calling is, ZZ = FUNC(ZZ)

Now, I want, should the function be not successful in doing what 
it intends to do, to return a boolean value of false, to ZZ, un 
fortunately ZZ is already a string[] (so i want liek a C style 
fopen -like function, that , although called with the syntax: 
file *f = fopen(balh, "bla"); can set f to be false)

Is this possible in D?
Nov 19 2013
next sibling parent "seany" <seany uni-bonn.de> writes:
Uh I forgot to mention that it should do this without global 
variables, and without try / catch
Nov 19 2013
prev sibling next sibling parent "Brad Anderson" <eco gnuk.net> writes:
On Tuesday, 19 November 2013 at 19:15:10 UTC, seany wrote:
 Consider this:

 I have a function FUNC, it takes a string array, and does 
 something with it, and retruns the same. Implemented based on a 
 previous thread, here is what i have

 string[] FUNC (ref string[] ZZ)
 {
 /*
 do something
 */
 }

 and the calling is, ZZ = FUNC(ZZ)

 Now, I want, should the function be not successful in doing 
 what it intends to do, to return a boolean value of false, to 
 ZZ, un fortunately ZZ is already a string[] (so i want liek a C 
 style fopen -like function, that , although called with the 
 syntax: file *f = fopen(balh, "bla"); can set f to be false)

 Is this possible in D?
You could use std.typecons.Nullable, std.variant.Variant, or switch to using exceptions for error reporting.
Nov 19 2013
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 19 November 2013 at 19:15:10 UTC, seany wrote:
 Now, I want, should the function be not successful in doing 
 what it intends to do, to return a boolean value of false, to 
 ZZ, un fortunately ZZ is already a string[] (so i want liek a C 
 style fopen -like function, that , although called with the 
 syntax: file *f = fopen(balh, "bla"); can set f to be false)

 Is this possible in D?
You can wrap return type in Variant (http://dlang.org/phobos/std_variant.html) but it is inefficient, weakens typing and considered a bad approach in natively compiled language. Better approach probably is to use null as an indicator (as string[] is a reference type) or throw an exception.
Nov 19 2013
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/19/2013 11:15 AM, seany wrote:

 Consider this:

 I have a function FUNC, it takes a string array, and does something with
 it, and retruns the same. Implemented based on a previous thread, here
 is what i have

 string[] FUNC (ref string[] ZZ)
 {
 /*
 do something
 */
 }

 and the calling is, ZZ = FUNC(ZZ)
In addition to what the others said, I see two more options: a) Instead of returning the same slice return a flag. (The slice is available through the out parameter anyway.) b) Return a struct (or Tuple) with two members. Ali
Nov 19 2013
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
seany:

 I have a function FUNC, it takes a string array, and does 
 something with it, and retruns the same. Implemented based on a 
 previous thread, here is what i have

 string[] FUNC (ref string[] ZZ)
I told you to use ref if you want to modify in-place the length of the array, as in the exaple you have shown. In general you don't need the ref.
 Now, I want, should the function be not successful in doing 
 what it intends to do, to return a boolean value of false, to 
 ZZ, un fortunately ZZ is already a string[] (so i want liek a C 
 style fopen -like function, that , although called with the 
 syntax: file *f = fopen(balh, "bla"); can set f to be false)

 Is this possible in D?
The clean design is to use std.typecons.Nullable: Nullable!(string[]) func(string[] zz) { Also consider making zz const (with "in"), and creating a pure/nothrow function: Nullable!(string[]) func(in string[] zz) pure nothrow { A less clean but sometimes acceptable design is to use a "out" variable in func, and return a boolean: bool func(string[] zz, out string[] result) { -------------------- Dicebot:
 You can wrap return type in Variant 
 (http://dlang.org/phobos/std_variant.html) but it is 
 inefficient, weakens typing and considered a bad approach in 
 natively compiled language. Better approach probably is to use 
 null as an indicator (as string[] is a reference type) or throw 
 an exception.
A Nullable in usually efficient enough (there is even an alternative Nullable that doesn't increase the data size), it makes typing stronger, and it should become more common in system languages (and indeed it's commonly used in Rust, where the pattern matching makes its usage nicer). [] is a bad indicator because perhaps ZZ could be empty, so you are mixing signals. Bye, bearophile
Nov 19 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 19 November 2013 at 19:31:41 UTC, bearophile wrote:
 A Nullable in usually efficient enough (there is even an 
 alternative Nullable that doesn't increase the data size), it 
 makes typing stronger, and it should become more common in 
 system languages (and indeed it's commonly used in Rust, where 
 the pattern matching makes its usage nicer). [] is a bad 
 indicator because perhaps ZZ could be empty, so you are mixing 
 signals.
I don't want to argue this in details right now but I think that simply banning null references as valid arrays in program as a whole via contracts is better approach than adding extra level of indirection via Nullable ;)
Nov 19 2013
parent "bearophile" <bearophileHUGS lycos.com> writes:
Dicebot:

 I don't want to argue this in details right now but I think 
 that simply banning null references as valid arrays in program 
 as a whole via contracts is better approach than adding extra 
 level of indirection via Nullable ;)
Nullable is a struct, it doesn't introduce a new leavel of indirection (sometimes it doesn't even add new data). And in the specific situation what's better could only be judged by the OP, because he/she has not shown the code. Bye, bearophile
Nov 19 2013
prev sibling parent reply "Meta" <jared771 gmail.com> writes:
On Tuesday, 19 November 2013 at 19:31:41 UTC, bearophile wrote:
 The clean design is to use std.typecons.Nullable:

 Nullable!(string[]) func(string[] zz) {
I have found that Nullable is pretty much useless for this type of usage, because it aliases itself to the underlying value, and then any safety it would provide is lost. See the following: import std.typecons; Nullable!(string[]) func(string[] zz) pure nothrow { return Nullable!(string[])(); } void main() { //AssertError thrown for trying to get //a value that is null. Might as well //return null at this point auto x = func(["test"]) ~ ["test"]; } Nullable either needs to be changed, or a new type that doesn't alias itself to the underlying value needs to be added to std.typecons.
Nov 19 2013
parent "bearophile" <bearophileHUGS lycos.com> writes:
Meta:

 import std.typecons;

 Nullable!(string[]) func(string[] zz) pure nothrow
 {
 	return Nullable!(string[])();
 }

 void main()
 {
         //AssertError thrown for trying to get
         //a value that is null. Might as well
         //return null at this point
 	auto x = func(["test"]) ~ ["test"];
 }
This code doesn't throw, so the behavour is different: string[] func(string[] zz) pure nothrow { return []; // This calls the runtime! } void main() { auto x = func(["test"]) ~ ["test"]; } In this case you are saying that an empty string[] is a correct output for func, while in the case with Nullable you are saying that it can't return an empty result. But I agree that the design of a language like Whiley is better, with its Flow Typing: http://whiley.org/guide/typing/flow-typing/ In such case Whiley forces you to analyse the return of func(), and after the analysis the type of such return value changes according to if the branch you are seeing. So exceptions happen, and less programmer mistakes. Bye, bearophile
Nov 20 2013
prev sibling parent "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Tuesday, 19 November 2013 at 19:15:10 UTC, seany wrote:
 (so i want liek a C style fopen -like function, that , although 
 called with the syntax: file *f = fopen(balh, "bla"); can set f 
 to be false)
I think you have a misunderstanding here. C does not allow you to return "false." Instead C states that 0/NULL is false. Similarly D also considers null and 0 to be false inside a conditional (where in D's case those are two different values). So yes, you can do the same in D, but since false, null, and 0 are actually all different types and will not implicitly cast to the other.
Nov 19 2013