There are multiple ways of supporting the returning of more than one value from a function. A really bad way that used to be popular in C libraries many years ago (no idea if it's still used), was to set a global value in addition to the return value. So a function that returned a point to eg a file handle, would return 0
on error and set an global error code to indicate what went wrong:
if (fp = fopen(some file))
{
// do file io
}
else
{
// use errno to identify specific error type
}
A common way still used in C for example, is to supply a block of memory via a parameter:
p = malloc(sizeof(some struct));
if (func(&p))
{
// *p now has returned data in addition to the boolean return value
}
In eg C#, a similar approach is provided using "out parameters":
if (Method(out var p)) {
// p is set via the Method in addition to the boolean return value
These days though, there is a growing interest in functional programming and thus in how it handles returning multiple values, without the side effects of the above approaches. Whilst a curried function may only take in one value via its one parameter and return just one value, there is no restriction on what those values are. And so that value can be compound value, ie some sequence of sub values. A common such sequence is to use a tuple. And tuples may even be used for single parameter functions when that one parameter also is a compound value, eg:
(x, y) = polarToCartesian(r, θ)
Whilst tuples have their place, it can often make sense to replace that informal collection with some sort of struct, record or class, so we might then still have a single return value, but that value is eg an object:
class Polar
{
Polar(double radius, double theta) => (Radius, Theta) = (radius, theta);
double Radius { get; }
double Theta { get; }
}
class Cartesian
{
Cartesian(double x, double y) => (X, Y) = (x, y);
double X{ get; }
double Y{ get; }
}
public Cartesian
Cartesian PolarToCartesian(Polar polar)
{
...
}