Let be a function with many input arguments like: F = F(x,y,a,b).
In Python, it is possible to pass some arguments as variables while other arguments as parameters like: F = F(x,y,a,b, (args=x,a)).
How can I do it in Fortran?
Related
I am trying to extract called functions to another module. I am successful if the function has a defined number of arguments.
// Create the arguments vector from the my argument list
SmallVector<Type *, sizeof(MyArgs)> ArgTys;
for (Value *V : MyArgs)
ArgTys.push_back(V->getType());
// Just get a void return type
Type *RetTy = Type::getVoidTy(TempContext);
// Create a new function with MyArgs as arguments
Constant *C = TempM->getOrInsertFunction(
"TempF", FunctionType::get(RetTy, ArgTys, false));
But if the function has a variable number of arguments, getOrInsertFunction only adds the arguments that I was able to capture with MyArgs in ArgTys.
How do I verify if source function has a variable number of arguments?
How do I use getOrInserFunction to declare a function with variable number of arguments?
According to the documentation:
You can declare a variable argument function by
FunctionType::get(RetTy, ArgTys, true);
(So, in your case, change that false argument for the "TempF" function.)
You can query if a function is using a variable argument list with the method
bool isVarArg() const
In Fortran, there are two standard ways to return a result from a function. The first one is by assigning the return value of the function to the function name.
function foo()
integer :: foo
foo = 10
end function foo
The second form, standardized in Fortran 90 is through a "result" variable.
function foo result(res)
integer :: res
res = 10
end function foo
Calling either form of the function returns the value 10. My question is, what was the rationale of the Fortran 90 committee for introducing result variables? Were they standardizing a common practice? Or were they allowing programs to be more modular by not tying the function name to a function result. For example, in the second version of foo(), the name of the function foo() could be changed to bar() and the function would still work as expected when called.
However, I may be wrong. Does anyone know what the actual rationale was for introducing result variables?
Introduced at the same time as the result was recursion. Before we get to how a recursive function comes about, some clarification on what a result variable is.
The function result is always returned through a result variable, whether result is used or not.1 With result the result variable has the name specified, and without it the result variable has the same name as the function. In this latter case use of the name is a reference to the result variable and not the function.
So, if the function foo has result variable foo then we can't do direct recursion:
recursive function foo(n)
foo = foo(n-1) ! Oh dear
end function
result comes about so that we can have
recursive function foo(n) result(res)
res = foo(n-1) ! Yay
end function
[1] Well, this is true up until Fortran 2008, when the definition of variable changed. For modern Fortran use instead the term function result.
I don't know why my code doesn't work.
fun lookup _ [] = 0
| lookup key ((k,v)::entries) =
if k = key
then v
else (lookup key entries)
That's what happened when I tested it in cmd.
val lookup = fn : ''a -> (''a * int) list -> int
- lookup (1,[(1,2),(2,3)]);
val it = fn : ((int * (int * int) list) * int) list -> int
There's nothing wrong with your code, you just didn't call lookup with enough arguments. You make a common mistakes among beginner SML programmers coming from other languages. I'll try to clarify that.
First, the most important thing to know about functions in Standard ML is this:
All functions in Standard ML take exactly one argument.
You might be confused at this point, because your lookup function looks as if it's taking two arguments. It kind of does, but not really.
There are two main "workarounds" (I'm using quotes because this is actually a great feature of the language) for representing functions that take multiple arguments:
1. Using curried functions
If you need to write a function which, conceptually, needs three arguments, then you'd write this:
fun quux a =
fn b =>
fn c =>
(* do something with a, b and c *)
So, quux is:
a function, which takes an argument a and returns
a function, which takes an argument b and returns
a function, which takes an argument c and returns
the result computed using a, b and c
How would you call quux? Like this, right?
((quux a) b) c
But function application is already left associative, so we can actually write this:
quux a b c
We don't need parentheses to "call" functions! In Standard ML parentheses don't mean "call this function". They're used just for grouping expressions together when you want to change associativity, like in mathematics: (1 + 2) * 3.
Because defining quux as above is really cumbersome, there's a syntactic shortcut in the language. Instead of writing this:
fun quux a =
fn b =>
fn c =>
(* do something with a, b and c *)
We can write just this:
fun quux a b c = (* do something with a, b and c *)
But, they're the same thing. quux is still a function which takes just argument a and returns a new function with argument b, which returns a new function which argument c.
Ok, so that was one way of representing multi-argument functions in Standard ML. It's also the one you used to define lookup.
2. Using tuples
Another common way of representing multi-argument functions is to accept a tuple (which may have from 2 to as many components as you wish). Here's the above example using a tuple now:
fun quux args =
case args of
(a,b,c) => (* do something with a, b and c *)
How could we call quux now? Like this:
quux (a,b,c)
Notice that I put a space between quux and the tuple. It's optional, but I do it all the time to keep remembering that function application in standard ML is not represented by parentheses. quux gets called because it's been put before the tuple (a,b,c). Tuples, however, do require parentheses, which is why you're seeing them above.
Again, as before, it's cumbersome to define quux like this:
fun quux args =
case args of
(a,b,c) => (* do something with a, b and c *)
So we can actually use another great feature of the language, pattern matching in argument position, that lets us write this:
fun quux (a,b,c) = (* do something with a, b and c *)
Ok, now we can really answer your question.
You defined lookup using the curried function syntax:
fun lookup _ [] = 0
But you "called" lookup using the tuple syntax, where 1 is the first element of the tuple and [(1,2),(2,3)] is the second element.
lookup (1, [(1,2),(2,3)])
Why doesn't the compiler complain, though. In this unfortunate case, it doesn't because it happens that the type of the first argument of lookup is a tuple. So, you've basically called lookup with a single argument.
What you wanted was this:
lookup 1 [(1,2),(2,3)]
Notice that I'm not defining a tuple anymore.
We can create functions with variable number of arguments using the ... notation in stdarg library. Is it also possible to pass these arguments by reference? E.g. perhaps to return a variable number of output values.
Not really (except with template varargs), for variadic functions in the sense of <stdarg.h>. You cannot call
void foo(int, ...);
as
int x = 0, y = 1;
foo(2,x,y);
and expect the x and y to be passed by reference. However, you can pass their address:
foo(2, &x, &y);
And you probably could play variadic template tricks or preprocessor macros tricks to transform FOO(x,y) into foo(2,&x,&y)
You can't with stdarg.h, but if you use c++ features you could.
I'd recommend looking into the implementation of std::tie as an example of how the standard library does this.
Whenever I define a function say funct(n), then can I assign value of n to a different variable such as m so that I can compare value of n which changes within the function with the initial value of m. Further, since I have nested and sometimes independent other functions, is there a way to make the m variable universal?
What I did is:
fun funct(n)= let val m=n in if (condition) then...
Further, here funct calls funct1 and funct1 calls funct2. The error message reads
Error: unbound variable or constructor: m
for funct2
Error: unbound variable or constructor: funct1
for funct1
Error: unbound variable or constructor: funct1
for funct
I suppose the single correction of m would solve the wholse cascade of errors.
You can access any identifier from scopes which are deeper than the one the identifer has been defined in. E.g.
fun funct(n) =
let fun funct1(x, y, z) = if n < 1 then ...
...
In this example, funct1 has access to n, which has been defined in an outer scope (namely as a parameter of funct).
Be careful though, in functional languages like ML, identifiers have a different meaning from those in imperative languages like C. In your example, n and m are not variables, meaning the values denoted by the identifiers will not change. You can only redefine the identifiers; however, code that uses an identifier before its redefinition will always refer to the original value of that identifier.