December 30, 2003
You are comparing apples to oranges the mathematical definition of a function allows for multiple inputs and a single output. (Note: that output can be a complex number, a vector or matrix, etc...) The idea of multiple return types goes against that. It also makes for some very ugly and difficult to debug code. I've been there and done that and most of the time there is no need for it and the few times that it is required struts work just fine and are easy enough to code. Should the language have a means to automatically  and efficiently handle the return of a strict so there isn't a copy involve - sure. But that's a compiler implementation detail not a language definition one.

-- 
Steve Maillet (eMVP)
Entelechy Consulting
smaillet_AT_EntelechyConsulting_DOT_com


December 30, 2003
"(x, y) = (y, x) ;  /* simple, clear, concise */"

That is NOT simple, clear nor concise. But then again neither is the traditional 3 assignments with a temp variable. In languages with templates a template library can help with a swap template. However, a built in swap/exchange statement/operator of some sort as part of the language proper is a far better answer to a common  pattern such as this.



-- 
Steve Maillet (eMVP)
Entelechy Consulting
smaillet_AT_EntelechyConsulting_DOT_com


December 31, 2003
In article <bst09c$1le5$1@digitaldaemon.com>, Steve Maillet says...
>
>You are comparing apples to oranges the mathematical definition of a function allows for multiple inputs and a single output. (Note: that output can be a complex number, a vector or matrix, etc...) The idea of multiple return types goes against that. It also makes for some very ugly and difficult to debug code.

Why would
x, y = func(a, b)

be any harder to debug than
func(a, b, &x, &y)
???

To me, the 1st form is better because you see what are the inputs and outputs. In the second form, you could be passing pointers for efficiency, to for "out" parameters. Worse, in C++, the 2nd form could be:

func(a, b, x, y) // declaration: void func(T a, T b, T& x, T& y)

It's much harder to tell what are the inputs and what are the outputs...

You could think of multiple return as returning a composite object (tuple) and
decomposing it at the assignment. So, it doesn't go against your beloved math.
(i don't think programming is math, but...)


December 31, 2003
"Steve Maillet" <nospam1@EntelechyConsulting.com> wrote in message news:bst0ks$1m14$1@digitaldaemon.com...
> "(x, y) = (y, x) ;  /* simple, clear, concise */"
>
> That is NOT simple, clear nor concise. But then again neither is the traditional 3 assignments with a temp variable. In languages with
templates
> a template library can help with a swap template. However, a built in swap/exchange statement/operator of some sort as part of the language
proper
> is a far better answer to a common  pattern such as this.

I only half-heartedly agree with your analysis, but I do agree that an inbuilt swap would be a very good thing.

I'd even go so far as to suggest we have an operator for the purpose.

Walter, shoot me down with your compiler-waltering lore, but how about

  x <> y

or

  x >< y

or

  x >=< y

?

:)

Dr Proctor



December 31, 2003
>>Why would
>> x, y = func(a, b)
>> be any harder to debug than
>>func(a, b, &x, &y)

It wouldn't - both versions of the syntax, quite frankly, suck.

instead it should be:

Point pos = func(a,b);

or perhaps

Point input;
Point Output;

Output = func(Input);

depending on exactly what it is that func is doing.


-- 
Steve Maillet (eMVP)
Entelechy Consulting
smaillet_AT_EntelechyConsulting_DOT_com


December 31, 2003
"You could think of multiple return as returning a composite object (tuple)"

Yes, you could and IMHO you SHOULD. The beauty of that is that __EXISTING__ language constructs allow you to do so already! Templates/generics allow you to create typesafe Tuple templates for any kind of paired return type; in fact STL already has the Pair template for C++ programmers to do just that. This is far more flexible and allows for compile time type checking without inventing or adding new concepts into the language. As I, and others, have mentioned the syntax of returning a struct or class is a bit clumsy in most "C" derivative languages and there is room to improve that in a new and emerging language such as "D". However, adding a completely new concept that is adequately supported with other existing constructs is a bad idea. (Especially when the only reason for not using a struct/class as a return type that has been offered thus far is the "clumsy" syntax of creating a temp in the actual method implementation. [Remember that even in the beloved multiple return values the compiler will have to do that underneath anyway.) So, I say lets' focus on ideas to improve that syntax without breaking the familiarity with C or compromising efficiency.

By way of some examples VB and Pascal use the function name as an implicit local for the return value so we could make a function like this:

Point Foo(float r, float theta)
{
    Foo.x = r*cos(theta) ;
    Foo.y = r*sin(theta) ;
}

The compiler is able to optimize that to the actual return type and eliminate any copy on return in many cases.  However, the existing return statement should be supported as well. This resolves the syntactical issues and provides for highly flexible tuples and other multiple return types using __EXISTING__ typesafe language constructs with minimal effort on the compiler creators and no further imposition on the programmer.

Furthermore, using the above syntax and structs allows for assignment of the members in any particular order without the need to create or store temps. Consider how the code would have to look if the resulting return type were implemented as proposed (e.g. "(x, y) = (r*cos(theta), r*sin(theta)) ") The language would HAVE to specifiy an order of execution for the sub expressions of the rvalue. And in the case where the actual functions needed to operate in a different order things get ugly with temps really fast. However, using structures or objects (with a minor syntactical cleanup) as shown above the issue simply doesn't exist.

-- 
Steve Maillet (eMVP)
Entelechy Consulting
smaillet_AT_EntelechyConsulting_DOT_com


January 01, 2004
Steve Maillet wrote:
>>>Why would
>>>x, y = func(a, b)
>>>be any harder to debug than
>>>func(a, b, &x, &y)
> 
> 
> It wouldn't - both versions of the syntax, quite frankly, suck.
> 
> instead it should be:
> 
> Point pos = func(a,b);
> 
> or perhaps
> 
> Point input;
> Point Output;
> 
> Output = func(Input);
> 
> depending on exactly what it is that func is doing.
> 
> 

that would be very nice, as thats whats im used to also. You should definetly be able to return a struct (if you cant) and a value from an non-anonymous enum, and a object.

in vb we can do something like this

Listview lv = new Listview;

//this dynamicly adds an item, returns a reference and you can inline add text to the subitem
lv.ListItems.Add("test","test").SubItems(1).Text = "test";

//or

struct Foo {
  int A;
  int B;
}

Foo InitStruct(int a,int b)  {
  Foo c;
   c.A = a;
   c.B = b;
   return c;
}

//which i think you can already do, but even better would be

Foo InitStruct(int a,int b)  {
   InitStruct.A = a;
   InitStruct.B = b;
   return;
}
January 01, 2004
Steve Maillet wrote:
> fact STL already has the Pair template for C++ programmers to do just that.

Yup. and there are tuples in boost.

The problem is, D templates lack of implicit instantiation, which makes them much less appropriate for this kind of stuff.

However, Walter promised some changes in templates. I wonder what those would be. I would prefer for templates to stay as they are, bacause they are great for many things and are nontheless simple to implement correctly. Also, they already open up another world on efficiency. In C++, templates are used to patch up the otherwise minimalistic language. That was not the original idea of D. That's why we have sliced and associative arrays directly in the langiage. And thus i would prefer that tuples (anonymous structs) also make it into the language.

-eye

January 02, 2004
"Steve Maillet" <nospam1@EntelechyConsulting.com> wrote in message news:bsurmr$19dt$1@digitaldaemon.com...
> "You could think of multiple return as returning a composite object
(tuple)"
>
> Yes, you could and IMHO you SHOULD. The beauty of that is that
__EXISTING__
> language constructs allow you to do so already! Templates/generics allow
you
> to create typesafe Tuple templates for any kind of paired return type; in fact STL already has the Pair template for C++ programmers to do just
that.

Defining a struct for the sole purpose of returning multiple values is the simplest way, defining a template to do this is just down right cumbersome and unnecessary.

> This is far more flexible and allows for compile time type checking
without
> inventing or adding new concepts into the language.

Tuples can be compile time checked, but at the element level.  In the truest sense there is no type associated with a tuple.  It is a collection of types which is implicitly defined by the types it contains.  These types must match across an assignment.

> As I, and others, have
> mentioned the syntax of returning a struct or class is a bit clumsy in
most
> "C" derivative languages and there is room to improve that in a new and emerging language such as "D". However, adding a completely new concept
that
> is adequately supported with other existing constructs is a bad idea.

Multiple returns and tuples are not new concepts.  Taking your point to the extremes, most of the features of D are not necessary.  They are there because they make frequently encountered patterns easier.  Why was array slicing introduced in D?  Because it makes frequent tasks easier to code. They do not add new ability to manipulate arrays, they just make it easier.

> (Especially when the only reason for not using a struct/class as a return type that has been offered thus far is the "clumsy" syntax of creating a temp in the actual method implementation. [Remember that even in the
beloved
> multiple return values the compiler will have to do that underneath
anyway.)

IMO the more the compiler does "underneath" the better.  That is the point of high-level programming languages.

> So, I say lets' focus on ideas to improve that syntax without breaking the familiarity with C or compromising efficiency.
>
D has broken with C/C++ in several areas, introducing new constructs where needed.  C is 30+ years old, C++ is 20+ years old.  New ideas have been introduced in newer languages.  I would be foolish to reject new constructs just to stay with C/C++ syntax.

> By way of some examples VB and Pascal use the function name as an implicit local for the return value so we could make a function like this:
>
> Point Foo(float r, float theta)
> {
>     Foo.x = r*cos(theta) ;
>     Foo.y = r*sin(theta) ;
> }
>
> The compiler is able to optimize that to the actual return type and eliminate any copy on return in many cases.  However, the existing return statement should be supported as well. This resolves the syntactical
issues
> and provides for highly flexible tuples and other multiple return types using __EXISTING__ typesafe language constructs with minimal effort on the compiler creators and no further imposition on the programmer.
>
> Furthermore, using the above syntax and structs allows for assignment of
the
> members in any particular order without the need to create or store temps.
> Consider how the code would have to look if the resulting return type were
> implemented as proposed (e.g. "(x, y) = (r*cos(theta), r*sin(theta)) ")

OK.

--- callee side ---
(float, float) Foo(float r, float theta)
{
    return ( r*cos(theta),  r*sin(theta) ) ;
}

--- caller side ---
(x, y) = Foo(r, theta) ;


> The
> language would HAVE to specifiy an order of execution for the sub
> expressions of the rvalue.

The D spec says that the order of execution within a statement is reserved for the compiler to determine.  Tuples would be the same way.

> And in the case where the actual functions needed
> to operate in a different order things get ugly with temps really fast.
> However, using structures or objects (with a minor syntactical cleanup) as
> shown above the issue simply doesn't exist.
>

In your way of thinking, you should always use a temporary structure to pass multiple parameters as well.  What is the difference between

a = func(b, c, d) ;

...and ...

(e, f, g) = func(h) ;

In your argument both cases are unnecessary and should be coded as.

struct Foo {
    type1 a ;
    type2 b ;
    type3 c ;
}
Foo foo  ;
foo.a = 1 ;
foo.b = 2 ;
foo.c = 3 ;
a = func(foo) ;

...and ...

struct Foo {
    type1 e ;
    type2 f ;
    type3 g ;
}

Foo foo  = func(h) ;
;
type1 e = foo.e ;
type2 f = foo.f ;
type3 g = foo.g ;

I do not see the efficiency in this.

Mark.

> -- 
> Steve Maillet (eMVP)
> Entelechy Consulting
> smaillet_AT_EntelechyConsulting_DOT_com
>
>


1 2 3 4 5
Next ›   Last »