Thank you for pointing out this. It is surely important and I have not thought about it before.
[a, b] = f(x) rely on a tuple, at least in Python. I assume that the MATLAB functionality is implemented in a similar way. Unfortunately, types like lists, tuples, or collections are not part of the Fortran language. Therefore, one needs use a derived type if
b are of different types or an temporary array if
b are of the same type. Note that stdlib already includes a list type: Stdlib linked list by ChetanKarwa · Pull Request #491 · fortran-lang/stdlib · GitHub.
f2matlab: converts Fortran 90 code to Matlab m-files, by benbarrowes. Accordingly, only basic data types and constructions are recommended.
Recent books with a mission similar to yours are
Introduction to Unconstrained Optimization with R (2019)
by Shashi Kant Mishra and Bhagwat Ram
Thank you @Beliavsky for commenting.
Yes, I am aware of f2matlab. It may be a good point to start with. One of the limitations is that it requires the program to be in the same file. This is hardly true for the code I have in mind.
In fact, I am thinking about using OCaml. Attempts have been made with successes to some degree. I am just wondering whether there exist mature tools than some dirty scripts written by myself/my student.
I will have a look at the books you mention.
[a, b] = f(x) rely on a tuple, at least in Python.” You need a tuple if you want to return multiple arguments of different types. Fortran could define the syntax for use with multiple arguments pf the same type as syntactic sugar for:
c = f(x) a = c(1) b = c(2)
Mind you I would find that less useful than a tuple result.
I would also like to be able to return multiple values from a function, see the discussion here: Syntax of interactive Fortran - #18 by certik
We should create a standalone issue at the incubator repository to discuss this more.
I can see only one disadvantage: what if you use such a function in an expression? A short answer is that you would not be able to. The advantage is that it does not require any kind of a tuple type.
A long answer is that you could if we introduce a tuple type that would be the result. However, I would not, it seems it would open all kinds performance and design issues. Would it still be useful without a tuple type?
So a function that returns multiple values would indeed be similar to a subroutine. However, it is much more readable — you know exactly what are the “in” and “out” arguments. And since you cannot use a subroutine in an expression, it’s not a limitation that a function with multiple output values also cannot be.
Hi @certik , great to get supportive comments from you and thank you for that!
In MATLAB, if
f returns multiple values, say three, like
[a1, a2, a3] = f(x),
then we have the flexibility of calling
f with one or two outputs, namely
[a1, a2] = f(x), a1 = f(x).
If the function is used in an expression, then the first output, i.e., a1 will play the role.
In Matlab, can the results be named in the function call, so that if the function defines outputs c1 and c2, one can write
[c1=a1, c2=a2] = f(x)
? If a function can return a variable number of outputs, they may not match what the user intended. With a subroutine one can write
For clarity, I think it’s a good idea to use keyword arguments when calling a procedure with optional arguments.
In a functional language the tuple could be used in an expression as an argument to a procedure. So you could have
… g( f(x) )…
where g is a function of more than one argument. However it would have a large impact on the standard. You would have to define procedure arguments in terms of “tuples”, where in Fortran “tuples” are defined in terms of keyword and optional arguments. It is certainly possible to define the use of keyword arguments as equivalent to tuple constructors and it may be possible to do the same for optional arguments, though the default arguments of other languages are easier to map to tuple constructors.
@certik, @milancurcic , etc. in this case, I notice a bothersome inconsistency in your statements at the other thread. On one hand, I see several comments in other threads that call for a simple, minimal language in Fortran; on the other hand, like with the case here, there is a call and support for features that really complicate matters relative to its foundation and legacy since FORTRAN I even.
The fact is in Fortran, a function result has certain characteristics that includes type, kind, and rank (TKR).
Returning multiple “values” with possibly even different type/kind/rank comes across as a change that runs orthogonal to the current standard and also a needless complication.
Should the use case be something like an
eigensolver, the “canonical” Fortrannesque approach, especially considering all the primitive-appearing intrinsic functions in the language and also prior comments re: avoidance of object-oriented (OO) design and seeking functional paradigm, will be for a math library (say in
stdlib?) to just supply
lam = eigenvalue(A) .. c = eigenvector(A)
The case for multiple value function results in Fortran appears rather weak, based on the use cases that have been reported thus far.
First, I’m glad you liked the blog post. And your project sounds interesting and commendable. I’m excited to see how it goes.
For functions with multiple outputs, I’ve generally taken to using derived types, but totally understand how it can in some ways obscure “the math”. @rouson often says that “software abstractions should resemble blackboard abstractions” (you’ll have to ask him where the original quote comes from), so my question is:
How do you write a function with multiple outputs on the blackboard? Is it
a, b = f(x), or something else? If that’s what you want, then I do like Python (and other languages) destructuring/pattern matching syntax. For many use cases it would be useful “syntactic sugar” for something like the following to be automatically transformed:
function f(x) result(a, b) real, intent(in) :: x real :: a, b
subroutine f(x, a, b) real, intent(in) :: x real, intent(out) :: a, b end subroutine
a, b = f(x)
call f(x, a, b)
but you do of course run into the problem, what happens with
z = g(f(x))
block real :: a, b call f(x, a, b) z = g(a, b) end block
seems a reasonable and straightforward transformation. Do you think it’s doable in LFortran @certik ? If so I think it would go a long way towards a proposal to the committee (I would certainly be in favor of it).
I’m curious, in Matlab what happens? In Python you can do it after-the-fact like
z = f(x) # returns a, b, c a, y = z b, c = y
Yes, that’s doable. But there are other issues, what about
g(1, f(x), 3) would it be equivalent to
g(1, a, b, 3)? If so, then we have essentially invented the
*args syntax from Python.
I would initially not allow such functions in expressions. But if we want to allow it, then all the above must be resolved.
That would be very ineficient, you would have to diagonalize the matrix twice. You always compute
lam at the same time.
I view the function result as a variable, that you declare in
result(a). So it’s a natural extension to allow more than one such variable.
Things would get complicated if we introduces “tuples”, but if we don’t, then the change seems small and easy to understand for a newcomer.
I think that would be reasonable. Maybe there are some other edge cases I’m not yet seeing though.
Does that seem so bad? If it makes the code look more like the math I think that’s a good thing and exactly what we should be striving for. If we can make it easier for scientists and engineers to write code that looks like what they wrote on their white boards, that’s a huge win.
So essentially it behaves like a tuple in Python, but it’s never actually a tuple, you can only see the results of a tuple operation. Using Python:
t = f(a, b) x, y, z = t
We cannot do these two lines individually, we can only do:
x, y, z = f(a, b)
This avoids adding a whole new type to Fortran, and always treating the “tuple” as separate entities, separate return variables from a function.
I think that would serve a lot of use cases and not introduce any runtime penalty. Of course, any time I’ve asked the committee for syntactic sugar so far, it has flopped, but maybe if we prototype it and convince other compiler writers of its usefulness it could work?
I don’t think Fortran should add this. Suppose there is a function call
g(a, f1(x), b, f2(x), c)
Currently you know that
c is the 5th argument of
g, and you can check the definition of
g to set
c appropriately. If
f2(x) can return tuples, you don’t know what argument
c corresponds to unless you also look at the definitions of functions
f2. Such code would be difficult to understand.
Exactly. My worry also.
I would simply not allow functions that return more than one variable in expressions.
Could Fortran allow a tuple to be set to the components of a derived type, so that the commented line in the code below would be valid? Then a function that returned a derived type could be accessed as if it returned a tuple.
module m type, public :: dt integer :: a,b end type dt end module m program main use m type(dt) :: x integer :: a,b x = dt(3,4) ! a, b = x ! equivalent to lines below a = x%a b = x%b end program main
There is a precedent for this kind of behavior. You can write
The compiler “unwraps” the derived type for you.
As far as I know today, MATLAB does not support named arguments.