D - Miscellaneous comments on D
- psheer AT icon DOT co DOT za (42/42) Aug 18 2001 I hope some of these are useful:::
- kaffiene (12/34) Aug 18 2001 Agreed. I think this is a much better idea than in, out and inout
- Grobbins (9/14) Aug 18 2001 While multiple return parameters seem elegant, you end up with code that...
- Russ Lewis (10/18) Aug 18 2001 Right. It is possible (though ugly) to return structures or classes whi...
- Walter (5/13) Aug 18 2001 Yes.
- Bradeeoh (18/22) Aug 18 2001 This one doesn't seem reasonable to me. Maybe it's just how I'm looking...
- Russ Lewis (9/19) Aug 18 2001 In my view, it's a design distinction between "return an array of values...
- Bradeeoh (28/36) Aug 18 2001 return[1]
- jacob navia (19/27) Aug 20 2001 values"
- Brent Schartung (4/8) Aug 19 2001 Just use contracts; that's what they're there for. The contract will
- Charles Hixson (14/18) Aug 21 2001 Contracts would handle it, but an exception might be easier to recover
- kaffiene (19/32) Aug 18 2001 Okay, that's a fair point. I can think of a couple of declaration format...
- Bradeeoh (18/23) Aug 18 2001 That is intriguing. Definately clear, and it could be reasonably useful...
- kaffiene (18/42) Aug 19 2001 I
- psheer AT icon DOT co DOT za (24/35) Aug 19 2001 i also don't see the problem. this is easy even to translate into C:
- Bradeeoh (14/21) Aug 19 2001 I guess the problem I'm seeing, especially as I'm not able to describe i...
- psheer AT icon DOT co DOT za (27/42) Aug 19 2001 yeah, i understand exactly.
- Russell Bornschlegel (26/36) Aug 20 2001 Well, back when I still cared what the code coming out of a
- Richard Krehbiel (22/27) Aug 21 2001 I just tested this, and it compiled and worked.
- Russell Bornschlegel (8/18) Aug 21 2001 In C, no less! Will wonders never cease. (What compiler was that,
- kaffiene (9/26) Aug 21 2001 You cannot guarantee that all fields of a struct are populated.
- Russell Bornschlegel (18/33) Aug 21 2001 Give it a constructor.
- Sheldon Simms (8/47) Aug 21 2001 I dunno. In the following:
- Russ Lewis (4/16) Aug 21 2001 Remember that in D structs are NOT classes, so they don't have construct...
- Russell Bornschlegel (4/24) Aug 21 2001 /me rolls eyes
- kaffiene (6/29) Aug 21 2001 constructors or
- kaffiene (13/43) Aug 21 2001 You can guarantee the struct has initialisers (or constructors if D had ...
- Russ Lewis (5/54) Aug 21 2001 Actually, the compiler will mis-recognize that as a compound statement:
- kaffiene (7/65) Aug 21 2001 them
- Russ Lewis (4/72) Aug 21 2001 No, I haven't used either, though from what I've heard they're very good...
- kaffiene (5/17) Aug 21 2001 oops! that should have been "... cannot guarantree the struct has
- Teemu Hirsimaki (9/12) Aug 22 2001 For example, if we are calling CountAnimals inside a member function,
- Dan Hursh (7/25) Aug 25 2001 It's also nicer when you want the returned data in certain variables
- Florian Weimer (13/20) Aug 25 2001 The problem with the first approach is the following: It is not clear
- Dan Hursh (20/43) Aug 25 2001 And it's clearer when it's:
- Florian Weimer (10/20) Aug 27 2001 Some people prefer:
- Christophe de Dinechin (7/25) Aug 22 2001 It's not ugly, but it's infrequent enough that most compilers generate
- Richard Krehbiel (21/31) Aug 23 2001 GCC also offers that extension.
- Walter (2/30) Oct 10 2001
- Christophe de Dinechin (5/30) Aug 20 2001 Another issue with that is: what happens if you use it as a function arg...
- kaffiene (15/49) Aug 20 2001 argument
- Angus Graham (19/32) Aug 20 2001 Then why not
- Charles Hixson (8/13) Aug 21 2001 It's not difficult. It's not obscure. It's not uncommon.
- Angus Graham (22/35) Aug 21 2001 Which suffer from the problem stated above - you can't tell from looking...
I hope some of these are useful::: 1. A major limitation of C code is not being able to return more than one argument from a function. For instance, the stack would easily be able to handle functions like: int, float, char* foo () { return 1, 3.1416, "pi"; } which is preferable to int foo (float *result1, char **reault2) { *result1 = 3.1416; *result2 = "pi"; return 1; } (or evan preferable to declaring an intermediate struct) This notation reduces code size enormously. Then (like python): int r; float val; char *descr: r, val, descr = foo (); 2. "there appears to be practically no other use for __FILE__ and __LINE__" These can be passed to functions to get tracebacks. I hope D is not considering dropping them as they are essential IMO. 3. I think that source files should be only UTF8 because: - UTF8 supports 20 bit characters. - UTF8 is exactly ASCII when there are no international characters (the usual case). - Its better to have only one format 4. A D to C translator? 5. "if a new errno value is added to the runtime system, the old code can not properly display a meaningful error message" This is scarcely true: strerror() ??? -paul -- Paul Sheer Consulting IT Services . . . Tel . . . +27 21 761 7224 Linux development, cryptography, recuitment, support, training http://www.icon.co.za/~psheer . . . . http://rute.sourceforge.net L I N U X . . . . . . . . . . . . The Choice of a GNU Generation
Aug 18 2001
"psheer AT icon DOT co DOT za" <nospam nospam.com> wrote in message news:9llhvs$d42$1 digitaldaemon.com...I hope some of these are useful::: 1. A major limitation of C code is not being able to return more than one argument from a function. For instance, the stack would easily be able to handle functions like: int, float, char* foo () { return 1, 3.1416, "pi"; } which is preferable to int foo (float *result1, char **reault2) { *result1 = 3.1416; *result2 = "pi"; return 1; } (or evan preferable to declaring an intermediate struct) This notation reduces code size enormously. Then (like python): int r; float val; char *descr: r, val, descr = foo ();Agreed. I think this is a much better idea than in, out and inout parameters. Given something like this: int a,b,x; a,b = myfunc(x); it's obvious the role that a,b and x play, whereas with in, out & inout the call looks like: int a,b,x; myfunc(a,b,x); // or a = myfunc(b,x); This is definitely an improvement over the current D spec. Peter.
Aug 18 2001
I think this is a much better idea than in, out and inout parameters. Given something like this: int a,b,x; a,b = myfunc(x); it's obvious the role that a,b and x playWhile multiple return parameters seem elegant, you end up with code that is harder to read and maintain. Consider int,int,int,int CountAnimals(); which is called numCats,numDogs,numFerrets,numGoats = CountAnimals(); Without parameter names attached to the output values in the declaration, it's hard to know if I've picked up the return values correctly. Greg Robbins
Aug 18 2001
Grobbins wrote:While multiple return parameters seem elegant, you end up with code that is harder to read and maintain. Consider int,int,int,int CountAnimals(); which is called numCats,numDogs,numFerrets,numGoats = CountAnimals(); Without parameter names attached to the output values in the declaration, it's hard to know if I've picked up the return values correctly.Right. It is possible (though ugly) to return structures or classes which are aggregates of your various return types. I do hope that D (unlike C) will allow you to return an array (don't see in the spec if it defines if you can or not). This would make a lot of sense with the self-awareness that D arrays have. Consider these possible declarations: int[] foo(); // returns an array of ints, unknown size int[3] foo(); // returns an array of ints, guaranteed to be 3 long. might throw an exception if function tried to return something else
Aug 18 2001
Russ Lewis wrote in message <3B7EE227.D011607E deming-os.org>...I do hope that D (unlike C) will allow you to return an array (don't see in the spec if it defines if you can or not). This would make a lot of sense with the self-awareness that D arrays have.Yes, it works in D.Consider these possible declarations: int[] foo(); // returns an array of ints, unknown sizeYes.int[3] foo(); // returns an array of ints, guaranteed to be 3 long.mightthrow an exception if function tried to return something elseI hadn't thought of that case.
Aug 18 2001
This one doesn't seem reasonable to me. Maybe it's just how I'm looking at it, but it seems to me if a function returns an integer, you should place a restriction on what range of integer it returns. If it returns a unicode character, you shouldn't limit it to ascii characters. If it returns a "fooObject", you shouldn't limit it to a "fooObject" with various data members. If it returns an integer array, you shouldn't limit the parameters of the array you get back. Especially since D's arrays have that WONDERFULLY useful extra information coded in such as array length, I say return a generic integer array, and if the function caller needs it to be of length 3, it's easy enough for them to check it via int[].length. I don't know what specifically about this bothers me, but for some reason I shudder whenever I think about it. Almost like "boolean foo(){ return true; }" being declared as "true foo(){ return; }" or "true foo(){ return true; }" That's just my two cents. Any other thoughts? -Bradyint[3] foo(); // returns an array of ints, guaranteed to be 3 long.mightthrow an exception if function tried to return something elseI hadn't thought of that case.
Aug 18 2001
Bradeeoh wrote:If it returns an integer array, you shouldn't limit the parameters of the array you get back. Especially since D's arrays have that WONDERFULLY useful extra information coded in such as array length, I say return a generic integer array, and if the function caller needs it to be of length 3, it's easy enough for them to check it via int[].length. I don't know what specifically about this bothers me, but for some reason I shudder whenever I think about it. Almost like "boolean foo(){ return true; }" being declared as "true foo(){ return; }" or "true foo(){ return true; }"In my view, it's a design distinction between "return an array of values" (that might have any number of values) and "return three integers". Consider a new strtoul(): int[2] strtoul(char *str,int base) In this D implementation, return[0] returns the value you wanted, and return[1] is analogous to the endPtr parameter of C's strtoul. In this case, return[1] will return how many characters were consumed. It would not make any sense, in this function, to return any more or less than 2 values.
Aug 18 2001
In my view, it's a design distinction between "return an array of values"(thatmight have any number of values) and "return three integers". Consider anewstrtoul(): int[2] strtoul(char *str,int base) In this D implementation, return[0] returns the value you wanted, andreturn[1]is analogous to the endPtr parameter of C's strtoul. In this case,return[1]will return how many characters were consumed. It would not make anysense, inthis function, to return any more or less than 2 values.Point taken, however, I'm still not convinced that an array of length 2 of integers should be treated any differently than a general array of integers. Another way of describing my problem with it is this - if you're going to allow functions to return int[2], then are you also going to allow these returned values to be stored in a var referencing a dynamic array? A few problems possibly come to mind. ie - int[2] a; // creates a static array analogous to c arrays a = strtoul( char *str, int base ); // valid, since we're storing an int[2] in an int[2].....? int[] b; // creates a dynamic array, with length data and is garbage collectable b = strtoul( char *str, int base ); // valid? b is an int[], not an int[2] - is this okay? int[4] c; c = strtoul( char *str, int base ); // error? or no? whose to say? I guess, what I'm trying to say, is that this type of return value would, in effect, be introducing a (near) infinite number of array types that may or may not have to be type checked to keep in the spirit of the language. Seems like implementing this would either cause us to A - require an extended, rigid semantic definition of how all this works and B - extra work in the compiler dealing with the basic possibilities. -Brady
Aug 18 2001
"Bradeeoh" <bradeeoh crosswinds.net> wrote in message news:9lnene$1flr$1 digitaldaemon.com...values"In my view, it's a design distinction between "return an array of(thatamight have any number of values) and "return three integers". ConsidernewThis can be easily written as typedef struct _strtoulReturnValue { long result; int CharactresUsed; } StrToUlReturn; Then you access the result with r = strtoul("978"...); r.CharactersUsed what is clearer than int r[2]= strtoul("123"...); r[1] Those absolute indexes, so necessary sometimes aren't in this example well choosen. Arrays haven't got named fields, more appropiate for a function result. Of course int r[1024*768] = CopyScreen(); is a better example for an application of arrays being returned from functions.strtoul(): int[2] strtoul(char *str,int base)
Aug 20 2001
Just use contracts; that's what they're there for. The contract will specify that the returned array should have three elements, and the code will (!)be commented to describe the returned contents. Keep it simple!Consider these possible declarations: int[] foo(); // returns an array of ints, unknown size int[3] foo(); // returns an array of ints, guaranteed to be 3 long.mightthrow an exception if function tried to return something else
Aug 19 2001
Brent Schartung wrote:Just use contracts; that's what they're there for. The contract will specify that the returned array should have three elements, and the code will (!)be commented to describe the returned contents. Keep it simple!Contracts would handle it, but an exception might be easier to recover from. Also, if one is going to assign the return value of a function to an array, it might be just as well if one could be sure that it wouldn't overfill the array. Ships docked[5]; -- only room to tie up 5 ships try { docked = pilot_log(today); ... } catch trafficJam (msg) { ... }
Aug 21 2001
"Grobbins" <grobbins badaddress.znet.com> wrote in message news:grobbins-2176AA.11503918082001 news.digitalmars.com...Okay, that's a fair point. I can think of a couple of declaration formats that might fix that issue: (int cats, int dogs, int ferrets, int goats) countAnimals() { ... } or countAnimals() returns (int cats, int dogs, int ferrets, int goats) { .... } I prefer the latter. Anyone else really like it? Hate it? I still think that in: a,b = myfunc(x); It is much clearer what role the variables are taking as input or results from the function as compared to the in, out, inout approach. Peter.I think this is a much better idea than in, out and inout parameters. Given something like this: int a,b,x; a,b = myfunc(x); it's obvious the role that a,b and x playWhile multiple return parameters seem elegant, you end up with code that is harder to read and maintain. Consider int,int,int,int CountAnimals(); which is called numCats,numDogs,numFerrets,numGoats = CountAnimals(); Without parameter names attached to the output values in the declaration, it's hard to know if I've picked up the return values correctly.
Aug 18 2001
countAnimals() returns (int cats, int dogs, int ferrets, int goats) { .... } I prefer the latter. Anyone else really like it? Hate it?That is intriguing. Definately clear, and it could be reasonably useful. I have a couple of nitpicks, one major and one minor. Major - what is the formal return type of this function? I notice you just wrote - countAnimals() returns (int.......goats) there is nothing before the function name. Granted, the return type is implicitly 4 integers, but I think one of the things (possibly) holding this feature back is that 4 integers is neither a primitive data type, nor a class/struct/union type. It's just.... 4... different primitive data types. If you can give a formal, simple definition as to the return type of the function, it may be worth looking into and could end up being something incredibly useful. ;) The minor nitpick - A number of ways to do this just ran through my head, but I noticed you haven't touched on the point at all - what is the syntax of return the values within the function? I'm sure you're thinking something as simple as "return (cats,dogs,ferrets,goats);" but, of course, that may also not be as simple as it seems.... ;) -Brady
Aug 18 2001
"Bradeeoh" <bradeeoh crosswinds.net> wrote in message news:9lnd7k$1eh8$1 digitaldaemon.com...IcountAnimals() returns (int cats, int dogs, int ferrets, int goats) { .... } I prefer the latter. Anyone else really like it? Hate it?That is intriguing. Definately clear, and it could be reasonably useful.have a couple of nitpicks, one major and one minor. Major - what is the formal return type of this function? I notice you just wrote - countAnimals() returns (int.......goats) there is nothing before the function name. Granted, the return type is implicitly 4 integers, but I think one of the things (possibly) holdingthisfeature back is that 4 integers is neither a primitive data type, nor a class/struct/union type. It's just.... 4... different primitive datatypes.If you can give a formal, simple definition as to the return type of the function, it may be worth looking into and could end up being something incredibly useful. ;)Hi There Bradeeoh (wassat then? :-) ). I'm not too sure what the problem is. I do see that 4 ints is not a primitve data type (or struct) but I don't see why that should be an issue. Are you thinking that this might provide a problem for the stack frame? I don't see why - we have lists of parameters, lists of return types should be too hard. Have I misunderstood your point?The minor nitpick - A number of ways to do this just ran through my head, but I noticed you haven't touched on the point at all - what is the syntax of return the values within the function? I'm sure you're thinking something as simple as "return (cats,dogs,ferrets,goats);" but, of course, that may also not be as simple as it seems.... ;)Hey, I'm keen on being enlightened - what are the problems you see? I *was* thinking "return(cats,dogs,ferrets,goats);" for the return syntax - it would be illegal to return more or less than the stated number of values just as it is illegal to call a function w/o the correct number of parameters. Feel free to expand on the idea / issues. Peter.
Aug 19 2001
In article <9lo1e0$1r4e$1 digitaldaemon.com>, "kaffiene" <kaffiene xtra.co.nz> wrote:"Bradeeoh" <bradeeoh crosswinds.net> wrote in message news:9lnd7k$1eh8$1 digitaldaemon.com...have a couple of nitpicks, one major and one minor. Major - what is the formal return type of this function? I notice you just wrote - countAnimals() returns (int.......goats)I'm not too sure what the problem is. I do see that 4 ints is not a primitve data type (or struct) but I don't see why that should be an issue. Are you thinking that this might provide a problem for the stack frame? I don't see why - we have lists of parameters, lists of return types should be too hard.i also don't see the problem. this is easy even to translate into C: you just create a temporary structure with four members in it. In fact, its precisely because one has to do this so often, that it should be part of the language in the first place: ala Python. I do agree that the names of the return values should be part of the declaration. We can extend this further. The C declaration for read(), int read (int fd, char *buf, int size); should REALLY be: (bytes_done_or_error int) read (int fd, char *buf, int size); /* (pick a notation you like) */ if you think about it, its ridiculous that, in C, the function declaration should describe everything that the function is passed, but not what it returns!!! Imagine the other extreme: header files containing: int read (int, char *, int); which is legal ANSI C (sic). -paul -- Paul Sheer Consulting IT Services . . . Tel . . . +27 21 761 7224 Linux development, cryptography, recuitment, support, training http://www.icon.co.za/~psheer . . . . http://rute.sourceforge.net L I N U X . . . . . . . . . . . . The Choice of a GNU Generation
Aug 19 2001
Hi There Bradeeoh (wassat then? :-) ). I'm not too sure what the problem is. I do see that 4 ints is not a primitve data type (or struct) but I don't see why that should be anissue.Are you thinking that this might provide a problem for the stack frame? I don't see why - we have lists of parameters, lists of return types shouldbetoo hard. Have I misunderstood your point?I guess the problem I'm seeing, especially as I'm not able to describe it well, is just a matter of how I "feel" about it. I just cringe when I see it, but I cannot explain why. The points you and others makes about it's ease of implementation, etc, are well taken. So, to just say what Walter has said about a few other features that are up for debate, it just doesn't "feel right". :) I will gracefully bow out in my debate on this topic. :) I can make one solid point on the subject, however - I don't deny for a second this feature could be useful, but if it's chosen to be implemented, be very careful on the syntax chosen, as it could potentially turn out looking quite messy. :) -Brady
Aug 19 2001
I guess the problem I'm seeing, especially as I'm not able to describe it well, is just a matter of how I "feel" about it. I just cringe when I see it, but I cannot explain why. The points you and others makes about it's ease of implementation, etc, are well taken. So, to just say what Walter has said about a few other features that are up for debate, it just doesn't "feel right". :) I will gracefully bow out in my debate on this topic. :) I can make one solid point on the subject, however - I don't deny for a second this feature could be useful, but if it's chosen to be implemented, be very careful on the syntax chosen, as it could potentially turn out looking quite messy. :)yeah, i understand exactly. none-the-less, the uglyness of trying to return multiple values has crudded up C for long enough. So this is a problem that REALLY needs fixing. Another reason for multiple return values is simply this: in assembler, the compiler pushes multiple arguments onto the stack whenever it does a function call. The return value is pushed onto the stack at the end of the function call. C arbitrarily chose to limit the number of return pushes to 1, even though the number of calling pushes could be many. (Am i correct here?). This limitation has infected all development to date. The read() function call CLEARLY returns two values: an error code, and the number of bytes. These are two conceptually different things. To roll them into one value is the ugliest thing i can think of. And yet every API tries to work around this limitation instead of extending the language in a very simple way. Imagine the elegance of being able to trust the return value of a read() call without having to check if it is -1 before-hand ?! Instead, we create extra conditionals in the calling code AND extra conditionals in the function code. All because we are trying to squeeze into the limitation of single return values. -paul -- Paul Sheer Consulting IT Services . . . Tel . . . +27 21 761 7224 Linux development, cryptography, recuitment, support, training http://www.icon.co.za/~psheer . . . . http://rute.sourceforge.net L I N U X . . . . . . . . . . . . The Choice of a GNU Generation
Aug 19 2001
psheer AT icon DOT co DOT za wrote:none-the-less, the uglyness of trying to return multiple values has crudded up C for long enough. So this is a problem that REALLY needs fixing. Another reason for multiple return values is simply this: in assembler, the compiler pushes multiple arguments onto the stack whenever it does a function call. The return value is pushed onto the stack at the end of the function call. C arbitrarily chose to limit the number of return pushes to 1, even though the number of calling pushes could be many. (Am i correct here?).Well, back when I still cared what the code coming out of a compiler looked like (1987-1992?), most compilers I was familiar with returned values in the "most temporary" register: (E)AX on x86, D0 on 68K, etc. -- not on the stack. Is returning a struct really so ugly? struct ReturnValue { bool success; int errno; // or perhaps "enum EErrno errno" int value; }; ReturnValue read( int fd, char* buf, size_t size ); // hmm, can you access a member of the result of a function call? if (!read( filedesc, buffer, size ).success) { printf("read failed, sucks to be you...\n" ); } This assumes that a lot of functions can use this common return value structure, but I think that's reasonable: it tells whether or not the function succeeded, why it failed if it failed, and what/how much it accomplished if it succeeded. You could roll the bool and the errno together, or make the bool a method instead of a datum: bool success( void ) { errno == EErrno_NoError; } -RB
Aug 20 2001
"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B81DC85.7321FD3E estarcion.com...// hmm, can you access a member of the result of a function call? if (!read( filedesc, buffer, size ).success) { printf("read failed, sucks to be you...\n" ); }I just tested this, and it compiled and worked. typedef struct multi { int a, b, c; } M; M sub(void) { M a; a.a = 1; a.b = 2; a.c = 3; return a; } int main(int argc, char *argv[]) { M res; if((res = sub()).a == 1) printf("OK, %d, %d, %d\n", res.a, res.b, res.c); return 0; }
Aug 21 2001
Richard Krehbiel wrote:"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B81DC85.7321FD3E estarcion.com...In C, no less! Will wonders never cease. (What compiler was that, by the way?) So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function? -RB// hmm, can you access a member of the result of a function call? if (!read( filedesc, buffer, size ).success) { printf("read failed, sucks to be you...\n" ); }I just tested this, and it compiled and worked. [snip example]
Aug 21 2001
"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Richard Krehbiel wrote:You cannot guarantee that all fields of a struct are populated. You have to have different structs for different kinds of functions, making the number of types you have to learn to use system functions much larger (plus this multiplies per user function which has a different struct return type) And YES it is *UGLY* =) Peter."Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B81DC85.7321FD3E estarcion.com...In C, no less! Will wonders never cease. (What compiler was that, by the way?) So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?// hmm, can you access a member of the result of a function call? if (!read( filedesc, buffer, size ).success) { printf("read failed, sucks to be you...\n" ); }I just tested this, and it compiled and worked. [snip example]
Aug 21 2001
kaffiene wrote:"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.You have to have different structs for different kinds of functions, making the number of types you have to learn to use system functions much larger (plus this multiplies per user function which has a different struct return type)This point is granted; you can define your APIs in such a way that the number of return-struct types is minimized, however.And YES it is *UGLY* =)Well, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals(); ...either. I think the parser would want at least some sort of marker around the return list, also, something like: [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); {numCats, numDogs, numFerrets, numGoats} = CountAnimals(); (numCats, numDogs, numFerrets, numGoats) = CountAnimals(); <numCats, numDogs, numFerrets, numGoats> = CountAnimals(); [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); `numCats, numDogs, numFerrets, numGoats` = CountAnimals(); \numCats, numDogs, numFerrets, numGoats\ = CountAnimals(); Eeech. -RB
Aug 21 2001
Im Artikel <3B82E1F6.851406A estarcion.com> schrieb "Russell Bornschlegel" <kaleja estarcion.com>:kaffiene wrote:I dunno. In the following: (cats, dogs, ferrets, goats) = CountAnimals(zoo, pound, farm, petshop); Why is the parenthesis-bounded list of returned variables uglier than the parenthesis-bounded list of function arguments? -- Sheldon Simms / sheldon semanticedge.com"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.You have to have different structs for different kinds of functions, making the number of types you have to learn to use system functions much larger (plus this multiplies per user function which has a different struct return type)This point is granted; you can define your APIs in such a way that the number of return-struct types is minimized, however.And YES it is *UGLY* =)Well, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals(); ...either. I think the parser would want at least some sort of marker around the return list, also, something like: [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); {numCats, numDogs, numFerrets, numGoats} = CountAnimals(); (numCats, numDogs, numFerrets, numGoats) = CountAnimals(); <numCats, numDogs, numFerrets, numGoats> = CountAnimals(); [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); `numCats, numDogs, numFerrets, numGoats` = CountAnimals(); \numCats, numDogs, numFerrets, numGoats\ = CountAnimals(); Eeech.
Aug 21 2001
Russell Bornschlegel wrote:kaffiene wrote:Remember that in D structs are NOT classes, so they don't have constructors or other member functions. You can define default initializers for all of the members, though."Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.
Aug 21 2001
Russ Lewis wrote:Russell Bornschlegel wrote:/me rolls eyes Sorry. Make the return type a class. -RBkaffiene wrote:Remember that in D structs are NOT classes, so they don't have constructors or other member functions. You can define default initializers for all of the members, though."Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.
Aug 21 2001
"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82FFBA.BB5CB70D estarcion.com...Russ Lewis wrote:constructors orRussell Bornschlegel wrote:kaffiene wrote:Remember that in D structs are NOT classes, so they don't have"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.theother member functions. You can define default initializers for all ofthen you can't guarantee that the class has a constructor for user functions which implement this patternmembers, though./me rolls eyes Sorry. Make the return type a class.
Aug 21 2001
"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82E1F6.851406A estarcion.com...kaffiene wrote:You can guarantee the struct has initialisers (or constructors if D had them for structs) on user functions. The compiler can guarantee a binding for returned values from *all* functions."Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.makingYou have to have different structs for different kinds of functions,largerthe number of types you have to learn to use system functions muchreturn(plus this multiplies per user function which has a different structNo - a compiler can do: a,b = myfunc(x); No problem at all - there is no reason you have have markers around the return list. Peter.type)This point is granted; you can define your APIs in such a way that the number of return-struct types is minimized, however.And YES it is *UGLY* =)Well, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals(); ...either. I think the parser would want at least some sort of marker around the return list, also, something like: [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); {numCats, numDogs, numFerrets, numGoats} = CountAnimals(); (numCats, numDogs, numFerrets, numGoats) = CountAnimals(); <numCats, numDogs, numFerrets, numGoats> = CountAnimals(); [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); `numCats, numDogs, numFerrets, numGoats` = CountAnimals(); \numCats, numDogs, numFerrets, numGoats\ = CountAnimals();
Aug 21 2001
kaffiene wrote:"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82E1F6.851406A estarcion.com...Actually, the compiler will mis-recognize that as a compound statement: a , b = myfunc(x);kaffiene wrote:You can guarantee the struct has initialisers (or constructors if D had them for structs) on user functions. The compiler can guarantee a binding for returned values from *all* functions."Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.makingYou have to have different structs for different kinds of functions,largerthe number of types you have to learn to use system functions muchreturn(plus this multiplies per user function which has a different structNo - a compiler can do: a,b = myfunc(x);type)This point is granted; you can define your APIs in such a way that the number of return-struct types is minimized, however.And YES it is *UGLY* =)Well, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals(); ...either. I think the parser would want at least some sort of marker around the return list, also, something like: [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); {numCats, numDogs, numFerrets, numGoats} = CountAnimals(); (numCats, numDogs, numFerrets, numGoats) = CountAnimals(); <numCats, numDogs, numFerrets, numGoats> = CountAnimals(); [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); `numCats, numDogs, numFerrets, numGoats` = CountAnimals(); \numCats, numDogs, numFerrets, numGoats\ = CountAnimals();
Aug 21 2001
"Russ Lewis" <russ deming-os.org> wrote in message news:3B82EEBD.BAB2CA67 deming-os.org...kaffiene wrote:them"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82E1F6.851406A estarcion.com...kaffiene wrote:You can guarantee the struct has initialisers (or constructors if D had"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.forfor structs) on user functions. The compiler can guarantee a bindingWhat I am saying is that you can write a compiler to recognise that - have you ever used yacc or bison? Peter.returned values from *all* functions.Actually, the compiler will mis-recognize that as a compound statement: a , b = myfunc(x);makingYou have to have different structs for different kinds of functions,largerthe number of types you have to learn to use system functions muchreturn(plus this multiplies per user function which has a different structNo - a compiler can do: a,b = myfunc(x);type)This point is granted; you can define your APIs in such a way that the number of return-struct types is minimized, however.And YES it is *UGLY* =)Well, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals(); ...either. I think the parser would want at least some sort of marker around the return list, also, something like: [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); {numCats, numDogs, numFerrets, numGoats} = CountAnimals(); (numCats, numDogs, numFerrets, numGoats) = CountAnimals(); <numCats, numDogs, numFerrets, numGoats> = CountAnimals(); [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); `numCats, numDogs, numFerrets, numGoats` = CountAnimals(); \numCats, numDogs, numFerrets, numGoats\ = CountAnimals();
Aug 21 2001
kaffiene wrote:"Russ Lewis" <russ deming-os.org> wrote in message news:3B82EEBD.BAB2CA67 deming-os.org...No, I haven't used either, though from what I've heard they're very good. Sorry to misunderstand - I thought that you meant that it would be an easy addition to the language as-is.kaffiene wrote:them"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82E1F6.851406A estarcion.com...kaffiene wrote:You can guarantee the struct has initialisers (or constructors if D had"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B82917B.FB34BD40 estarcion.com...Give it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.forfor structs) on user functions. The compiler can guarantee a bindingWhat I am saying is that you can write a compiler to recognise that - have you ever used yacc or bison? Peter.returned values from *all* functions.Actually, the compiler will mis-recognize that as a compound statement: a , b = myfunc(x);makingYou have to have different structs for different kinds of functions,largerthe number of types you have to learn to use system functions muchreturn(plus this multiplies per user function which has a different structNo - a compiler can do: a,b = myfunc(x);type)This point is granted; you can define your APIs in such a way that the number of return-struct types is minimized, however.And YES it is *UGLY* =)Well, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals(); ...either. I think the parser would want at least some sort of marker around the return list, also, something like: [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); {numCats, numDogs, numFerrets, numGoats} = CountAnimals(); (numCats, numDogs, numFerrets, numGoats) = CountAnimals(); <numCats, numDogs, numFerrets, numGoats> = CountAnimals(); [numCats, numDogs, numFerrets, numGoats] = CountAnimals(); `numCats, numDogs, numFerrets, numGoats` = CountAnimals(); \numCats, numDogs, numFerrets, numGoats\ = CountAnimals();
Aug 21 2001
themYou can guarantee the struct has initialisers (or constructors if D hadGive it a constructor.So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?You cannot guarantee that all fields of a struct are populated.for structs) on user functions. The compiler can guarantee a binding for returned values from *all* functions.oops! that should have been "... cannot guarantree the struct has initialisers..." sorry =) Peter.
Aug 21 2001
Russell Bornschlegel <kaleja estarcion.com> writes:Well, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals();For example, if we are calling CountAnimals inside a member function, and want to set the return values in miscellanous member variables, it will be quite clumsy to make a seperate class the return values. I like the Perl way: (foo, bar) = func(); This would be very useful. -- Teemu Hirsimäki
Aug 22 2001
Teemu Hirsimaki wrote:Russell Bornschlegel <kaleja estarcion.com> writes:It's also nicer when you want the returned data in certain variables ratherthan a struct. Less copying than. ret_t ret = func(); foo = ret.f; bar = ret.b; DanWell, I'm not thrilled with: numCats,numDogs,numFerrets,numGoats = CountAnimals();For example, if we are calling CountAnimals inside a member function, and want to set the return values in miscellanous member variables, it will be quite clumsy to make a seperate class the return values. I like the Perl way: (foo, bar) = func(); This would be very useful. -- Teemu Hirsimäki
Aug 25 2001
Dan Hursh <hursh infonet.isl.net> writes:(foo, bar) = func();It's also nicer when you want the returned data in certain variables ratherthan a struct. Less copying than. ret_t ret = func(); foo = ret.f; bar = ret.b;The problem with the first approach is the following: It is not clear if you have to write: (write_end, read_end) = Create_Pipe(); Or: (read_end, write_end) = Create_Pipe(); In general, I don't think it's a good idea to trade readability for terseness. -- Florian Weimer Florian.Weimer RUS.Uni-Stuttgart.DE University of Stuttgart http://cert.uni-stuttgart.de/ RUS-CERT +49-711-685-5973/fax +49-711-685-5898
Aug 25 2001
Florian Weimer wrote:Dan Hursh <hursh infonet.isl.net> writes:And it's clearer when it's: Create_Pipe(write_end, read_end); Or: Create_Pipe(read_end, write_end); I guess I'd really like the ability to choose between returning a list of values to a set of variables, an array, or a struct with the correct members. They are all useful sometimes, but not of them feel right in all cases. This is mostly aesthetics though. Weather it's function return values though or function parameters you still have to know what order they are. (Unless we use named parameters. That doesn't look likely.) At least with you two examples it would be easier to tell what is input and what is output. The function name just becomes a glorified infix operator between a list of input values (on the right) and output locations (on the left). Of course, as soon as you do this sort of syntax, someone will ask for the ability to overload based on return list types. Suddenly you would have to keep track of calling context or some such thing. I would be nice, but against the D way of doing things. Dan(foo, bar) = func();It's also nicer when you want the returned data in certain variables ratherthan a struct. Less copying than. ret_t ret = func(); foo = ret.f; bar = ret.b;The problem with the first approach is the following: It is not clear if you have to write: (write_end, read_end) = Create_Pipe(); Or: (read_end, write_end) = Create_Pipe(); In general, I don't think it's a good idea to trade readability for terseness.
Aug 25 2001
Dan Hursh <hursh infonet.isl.net> writes:Some people prefer: Create_Pipe (Write_End => Write_End_Var, Read_End => Read_End_Var); (Named parameter associations, 'Write_End' is the name of the formal parameter in the declaration of 'Create_Pipe'). ;-) -- Florian Weimer Florian.Weimer RUS.Uni-Stuttgart.DE University of Stuttgart http://cert.uni-stuttgart.de/ RUS-CERT +49-711-685-5973/fax +49-711-685-5898In general, I don't think it's a good idea to trade readability for terseness.And it's clearer when it's: Create_Pipe(write_end, read_end); Or: Create_Pipe(read_end, write_end);
Aug 27 2001
It's not ugly, but it's infrequent enough that most compilers generate inefficient code for that. Hence people don't use it. Catch 22. Typically, you get a lot of extra copies while returning a struct (at least one, sometimes 2). LX tries to solve that with the "result" pseudo-variable. Christophe Russell Bornschlegel wrote:Richard Krehbiel wrote:"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B81DC85.7321FD3E estarcion.com...In C, no less! Will wonders never cease. (What compiler was that, by the way?) So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function? -RB// hmm, can you access a member of the result of a function call? if (!read( filedesc, buffer, size ).success) { printf("read failed, sucks to be you...\n" ); }I just tested this, and it compiled and worked. [snip example]
Aug 22 2001
"Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B841E54.D4D364A9 earthlink.net...Russell Bornschlegel wrote:GCC also offers that extension. struct bigstruct func(void) return bs { bs.a = 0; // ... whatever... return; } When I first saw that, I wondered if the compiler could optimize-away the extra copying away. I recall that Lattice C for the Amiga ASM calling conventions specified that to call a function which returns a struct, the caller passes in the address where the function should place the struct. The called function could build the return value right there (using the "result" spec, or by compiler optimization). And in fact, the compiler may have optimized "struct T a; a = func();" by calling func() giving a pointer to a, resulting in *no* struct copying. -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 home.com (personal)So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function?It's not ugly, but it's infrequent enough that most compilers generate inefficient code for that. Hence people don't use it. Catch 22. Typically, you get a lot of extra copies while returning a struct (at least one, sometimes 2). LX tries to solve that with the "result" pseudo-variable.
Aug 23 2001
The DM compiler doesn't do extra copies. Christophe de Dinechin wrote in message <3B841E54.D4D364A9 earthlink.net>...It's not ugly, but it's infrequent enough that most compilers generate inefficient code for that. Hence people don't use it. Catch 22. Typically, you get a lot of extra copies while returning a struct (at least one, sometimes 2). LX tries to solve that with the "result" pseudo-variable. Christophe Russell Bornschlegel wrote:Richard Krehbiel wrote:"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B81DC85.7321FD3E estarcion.com...In C, no less! Will wonders never cease. (What compiler was that, by the way?) So, I repeat the question: is returning a struct from a commonly used library routine such an ugly construct that we need to come up with a better way to handle the return of multiple values from a function? -RB// hmm, can you access a member of the result of a function call? if (!read( filedesc, buffer, size ).success) { printf("read failed, sucks to be you...\n" ); }I just tested this, and it compiled and worked. [snip example]
Oct 10 2001
Another issue with that is: what happens if you use it as a function argument (that is, f(g()), where g() return 4 things)? Does this give 4 arguments to f(), or is it simply forbidden? Christophe Bradeeoh wrote:countAnimals() returns (int cats, int dogs, int ferrets, int goats) { .... } I prefer the latter. Anyone else really like it? Hate it?That is intriguing. Definately clear, and it could be reasonably useful. I have a couple of nitpicks, one major and one minor. Major - what is the formal return type of this function? I notice you just wrote - countAnimals() returns (int.......goats) there is nothing before the function name. Granted, the return type is implicitly 4 integers, but I think one of the things (possibly) holding this feature back is that 4 integers is neither a primitive data type, nor a class/struct/union type. It's just.... 4... different primitive data types. If you can give a formal, simple definition as to the return type of the function, it may be worth looking into and could end up being something incredibly useful. ;) The minor nitpick - A number of ways to do this just ran through my head, but I noticed you haven't touched on the point at all - what is the syntax of return the values within the function? I'm sure you're thinking something as simple as "return (cats,dogs,ferrets,goats);" but, of course, that may also not be as simple as it seems.... ;) -Brady
Aug 20 2001
"Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B80D256.4DC6BEE8 earthlink.net...Another issue with that is: what happens if you use it as a functionargument(that is, f(g()), where g() return 4 things)? Does this give 4 argumentstof(), or is it simply forbidden?There are two obvious answers - either allow it only if the number of return values from g() matches the number of parameters to f() or disallow it on principle. You could argue that there are pros and cons each way. I don't think it matters much as long as the compiler knows which one it's doing ;-) Peter.Bradeeoh wrote:useful. IcountAnimals() returns (int cats, int dogs, int ferrets, int goats) { .... } I prefer the latter. Anyone else really like it? Hate it?That is intriguing. Definately clear, and it could be reasonablythishave a couple of nitpicks, one major and one minor. Major - what is the formal return type of this function? I notice you just wrote - countAnimals() returns (int.......goats) there is nothing before the function name. Granted, the return type is implicitly 4 integers, but I think one of the things (possibly) holdingtypes.feature back is that 4 integers is neither a primitive data type, nor a class/struct/union type. It's just.... 4... different primitive datahead,If you can give a formal, simple definition as to the return type of the function, it may be worth looking into and could end up being something incredibly useful. ;) The minor nitpick - A number of ways to do this just ran through mysyntaxbut I noticed you haven't touched on the point at all - what is thesimpleof return the values within the function? I'm sure you're thinking something as simple as "return (cats,dogs,ferrets,goats);" but, of course, that may also not be asas it seems.... ;) -Brady
Aug 20 2001
"Grobbins" <grobbins badaddress.znet.com> wrote:Then why not int numCats, int numDogs, int numFerrets, int numGoats CountAnimals() { if(m_ThisPlaceIsAPound) { numCats = 10; numDogs = 13; numFerrets = 1; numGoats = 0; return; } else if(m_ThisPlaceIsAPettingZoo) { numCats = 0; numDogs = 0; numFerrets = 1; numGoats = 3; return; } numCats = 0; numDogs = 0; numFerrets = 0; return; // compile time error: not all paths initialize 'numGoats' } What am I missing here? Angus GrahamI think this is a much better idea than in, out and inout parameters. Given something like this: int a,b,x; a,b = myfunc(x); it's obvious the role that a,b and x playWhile multiple return parameters seem elegant, you end up with code that is harder to read and maintain. Consider int,int,int,int CountAnimals(); which is called numCats,numDogs,numFerrets,numGoats = CountAnimals(); Without parameter names attached to the output values in the declaration, it's hard to know if I've picked up the return values correctly.
Aug 20 2001
Angus Graham wrote:... What am I missing here? Angus GrahamIt's not difficult. It's not obscure. It's not uncommon. But is it useful? In D there are in/out parameters to functions. It's useful for a function to return one value, so that it can be processed in a stream of arithmetic or inheritance. For multiple values? They would seem to clog up this process unless tuples are a part of the language. Use an array return value instead.
Aug 21 2001
"Charles Hixson" <charleshixsn earthlink.net> wroteAngus Graham wrote:Not less useful than i/o parameters... What am I missing here? Angus GrahamIt's not difficult. It's not obscure. It's not uncommon. But is it useful?In D there are in/out parameters to functions.Which suffer from the problem stated above - you can't tell from looking at a call which is which. I suggest not having both, but replacing i/o params with this system.It's useful for a function to return one value, so that it can be processed in a stream of arithmetic or inheritance. For multiple values? They would seem to clog up this process unless tuples are a part of the language. Use an array return value instead.I wouldn't be in favour of tuples, but you could still use one of the multiple return values in arithmetic operations: In c, the ',' operator evaluates its args left to right and takes on the value of the right operand. Multiple arguments returned from functions would be "comma'd" just as if you had written them out with the regular comma operator. Thus: ERROR e; int items; items = (e, items = row->get_items()) + 1; would add 1 to the int returned by row->get_items() and retrieve an error as a bonus. items = row->get_items() + 1; would do the same thing, except the error would be put a temporary, not assigned anywhere and lost. You could pass the result to a function that takes only one argument: row->set_items(row->get_items() + 1); Angus Graham
Aug 21 2001