tuple types on-the-fly
Feb. 5th, 2007 11:25 amPL people,
I'd like to have a language that allows a double assignment like this:
which assigns two local variables 'radius' and 'angle' to the (double) return value of convert.
The declaration for the 'convert' function is as follows:
(We need a better choice than '*', since that usually means multiplication)
You could also have call-dispatching on the output type, not just the input types. If you had two functions named 'convert' with the same input types, you would call the one that matches the type of the variable you're assigning to.
This would be a useful pattern, and if I had it, I would write fewer functions with side-effects (which in Java is often necessary for efficiency purposes).
* having small functions
* having no functions with side-effects
* efficiency
In Java, you have to pick 2.
I'd like to have a language that allows a double assignment like this:
radius * angle = convert (x,y);
which assigns two local variables 'radius' and 'angle' to the (double) return value of convert.
The declaration for the 'convert' function is as follows:
double * double convert (double x, double y){
return makeRadius(x,y) * makeAngle(x,y);
}
(We need a better choice than '*', since that usually means multiplication)
You could also have call-dispatching on the output type, not just the input types. If you had two functions named 'convert' with the same input types, you would call the one that matches the type of the variable you're assigning to.
This would be a useful pattern, and if I had it, I would write fewer functions with side-effects (which in Java is often necessary for efficiency purposes).
* having small functions
* having no functions with side-effects
* efficiency
In Java, you have to pick 2.
(no subject)
Date: 2007-02-05 04:32 pm (UTC)(no subject)
Date: 2007-02-05 04:40 pm (UTC)I often hack up a Pair class when I'm stuck in java. It's much less painful if you use java 1.5
class Pair
I often hack up a Pair class when I'm stuck in java. It's much less painful if you use java 1.5
class Pair<A, B>{
public Pair(A a, B b){
fst = a; snd = b;
}
A getFst(){return fst};
B getSnd(){return snd};
}
(no subject)
Date: 2007-02-05 04:42 pm (UTC)(no subject)
Date: 2007-02-05 04:48 pm (UTC)- fun convert p = let fun radius (x,y) = Math.sqrt(x * x + y * y) in (radius p, Math.atan2 p) end; val convert = fn : real * real -> real * real(no subject)
Date: 2007-02-05 05:01 pm (UTC)$ ruby -e 'def f; [1,2]; end; a, b = f(); p a, b'
1
2
(no subject)
Date: 2007-02-05 05:30 pm (UTC)sub convert { return makeRadius($_[0],$_[1]), makeAngle($_[0],$_[1]); }(Yes, Perl has an ugly syntax for retrieving function arguments.)
While Perl doesn't exactly do call-dispatching based on the return type of a function, you can find out from inside a function what sort of return value a given call is expecting and act appropriately:
sub convert { if (wantarray()) { # List expected return makeRadius($_[0],$_[1]), makeAngle($_[0],$_[1]); } else { # Single (scalar) value or no (void) value expected return somethingElse($_[0],$_[1]); } }You can also tell if you're being called in a scalar or void context, but I forget how ATM.
IIRC, Common Lisp is also set up to handle multiple return values, but accessing them was also kind of clunky.
(no subject)
Date: 2007-02-05 06:20 pm (UTC)(no subject)
Date: 2007-02-05 06:30 pm (UTC)(no subject)
Date: 2007-02-05 07:49 pm (UTC)(no subject)
Date: 2007-02-05 07:50 pm (UTC)(no subject)
Date: 2007-02-05 07:52 pm (UTC)(no subject)
Date: 2007-02-05 07:56 pm (UTC)Which one do you call?
void* foo();
bar* foo();
int main(){
void* baz = (void*)foo();
}
(no subject)
Date: 2007-02-05 07:58 pm (UTC)If you have
int foo(); //both of these have some crazy side effect
float foo(); //both of these have some crazy side effect
foo();
You can't tell what the programmer meant easily. Sure you could set up rules about which one it is, but that's another complication, and really an unecessary one.
And even if you actually use the return value, in the presence of C++'s multiple inheritance you really can't do much more than cry.
(no subject)
Date: 2007-02-05 08:04 pm (UTC)(no subject)
Date: 2007-02-05 08:10 pm (UTC)Both are fucking painful to use, sadly.
(no subject)
Date: 2007-02-05 08:12 pm (UTC)(no subject)
Date: 2007-02-05 08:14 pm (UTC)(no subject)
Date: 2007-02-05 08:18 pm (UTC)(no subject)
Date: 2007-02-05 08:19 pm (UTC)(no subject)
Date: 2007-02-05 08:21 pm (UTC)struct RadiusAngle {
double radius;
double angle;
};
RadiusAngle convert(double x, double y) {
RadiusAngle ra;
ra.radius = ...;
ra.angle = ...;
return ra;
}
In Java, you can do similar things, except you need to make a class.
Both methods are cumbersome in that you must explicitely define and name the type; as mentioned, there's the pair template idiom to get around it if you have just a pair (you can use recursive pairs to get triples etc, but eventually it all turns to rotted apples and you should have defined a type).
This is part of why these languages suck.
(no subject)
Date: 2007-02-05 08:54 pm (UTC)(no subject)
Date: 2007-02-05 10:58 pm (UTC)(no subject)
Date: 2007-02-06 12:21 am (UTC)But no, there's no dangling reference. I'm just returning a 128-bit object rather than a 64- or 32-bit one. The compiler may use any method it pleases to do this; typically, it'll be on the stack for x86, and through registers on basically all other machines.
(no subject)
Date: 2007-02-06 12:27 am (UTC)SML -
(radius p, Math.atan2 p)C++ -
make_pair(radius p, Math.atan2 p)Small difference.
Using the pair:
SML -
val (r, theta) = convert pC++ -
pair<double,double> rtheta = convert p; double r = rtheta.first; double theta = rtheta.second;Ugh.
Then, we could repeat the exercise for a triple for true ugliness.
(no subject)
Date: 2007-02-06 12:28 am (UTC)(no subject)
Date: 2007-02-06 05:37 am (UTC)(no subject)
Date: 2007-02-06 05:38 am (UTC)(no subject)
Date: 2007-02-06 06:16 am (UTC)($factor_A,$factor_B) = factor(largeprime1*largeprime2);
I think the same goes for Mathematica and Matlab, although sometimes I get them confused so maybe only one of them does this.
(no subject)
Date: 2007-02-06 03:20 pm (UTC)(no subject)
Date: 2007-02-06 03:28 pm (UTC)boost::tuple<float, double, int&rt;There are limits to how far you should push this "unnamed tuple" business though anyway as you are going to have to carefully document the order of the things that are returned and the consumer of the function is going to have to remember them. Do you really want to return a tuple of 10 floats? At some point, you just have to break down and define a struct with named fields, or else do the old C-style thing and take pointers to variables in the calling sequence.
(no subject)
Date: 2007-02-06 03:28 pm (UTC)(no subject)
Date: 2007-02-06 04:08 pm (UTC)The SML way of doing the record thing (which I often prefer to tuples, for the reasons you mentioned) is:
to create one: { a=v1, b=v2, c=v3 }
to receive one: { a,b,c } = ...