What is the difference between a function and a subroutine? I was told that the difference between a function and a subroutine is as follows:
A function takes parameters, works locally and does not alter any value or work with any value outside its scope (high cohesion). It also returns some value. A subroutine works directly with the values of the caller or code segment which invoked it and does not return values (low cohesion), i.e. branching some code to some other code in order to do some processing and come back.
Is this true? Or is there no difference, just two terms to denote one?
I disagree. If you pass a parameter by reference to a function, you would be able to modify that value outside the scope of the function. Furthermore, functions do not have to return a value. Consider void some_func() in C. So the premises in the OP are invalid.
In my mind, the difference between function and subroutine is semantic. That is to say some languages use different terminology.
A function returns a value whereas a subroutine does not. A function should not change the values of actual arguments whereas a subroutine could change them.
Thats my definition of them ;-)
If we talk in C, C++, Java and other related high level language:
a. A subroutine is a logical construct used in writing Algorithms (or flowcharts) to designate processing functionality in one place. The subroutine provides some output based on input where the processing may remain unchanged.
b. A function is a realization of the Subroutine concept in the programming language
Both function and subroutine return a value but while the function can not change the value of the arguments coming IN on its way OUT, a subroutine can. Also, you need to define a variable name for outgoing value, where as for function you only need to define the ingoing variables. For e.g., a function:
double multi(double x, double y)
{
double result;
result = x*y;
return(result)
}
will have only input arguments and won't need the output variable for the returning value. On the other hand same operation done through a subroutine will look like this:
double mult(double x, double y, double result)
{
result = x*y;
x=20;
y = 2;
return()
}
This will do the same as the function did, that is return the product of x and y but in this case you (1) you need to define result as a variable and (2) you can change the values of x and y on its way back.
One of the differences could be from the origin where the terminology comes from.
Subroutine is more of a computer architecture/organization terminology which means a reusable group of instructions which performs one task. It is is stored in memory once, but used as often as necessary.
Function got its origin from mathematical function where the basic idea is mapping a set of inputs to a set of permissible outputs with the property that each input is related to exactly one output.
In terms of Visual Basic a subroutine is a set of instructions that carries out a well defined task. The instructions are placed within Sub and End Sub statements.
Functions are similar to subroutines, except that the functions return a value. Subroutines perform a task but do not report anything to the calling program. A function commonly carries out some calculations and reports the result to the caller.
Based on Wikipedia subroutine definition:
In computer programming, a subroutine is a sequence of program
instructions that perform a specific task, packaged as a unit. This
unit can then be used in programs wherever that particular task should
be performed.
Subroutines may be defined within programs, or separately in libraries
that can be used by many programs. In different programming languages,
a subroutine may be called a procedure, a function, a routine, a
method, or a subprogram. The generic term callable unit is sometimes
used.
In Python, there is no distinction between subroutines and functions.
In VB/VB.NET function can return some result/data, and subroutine/sub can't.
In C# both subroutine and function referred to a method.
Sometimes in OOP the function that belongs to the class is called a method.
There is no more need to distinguish between function, subroutine and procedure because of hight level languages abstract that difference, so in the end, there is very little semantic difference between those two.
Yes, they are different, similar to what you mentioned.
A function has deterministic output and no side effects.
A subroutine does not have these restrictions.
A classic example of a function is int multiply(int a, int b)
It is deterministic as multiply(2, 3) will always give you 6.
It has no side effects because it does not modify any values outside its scope, including the values of a and b.
An example of a subroutine is void consume(Food sandwich)
It has no output so it is not a function.
It has side effects as calling this code will consume the sandwich and you can't call any operations on the same sandwich anymore.
You can think of a function as f(x) = y, or for the case of multiply, f(a, b) = c. Yes, this is programming and not math. But math models and begs to be used. So we use math in cs. If you are interested to know why the distinction between function and subroutine, you should check out functional programming. It works like magic.
From the view of the user, there is no difference between a programming function and a subroutine but in theory, there definitely is!
The concept itself is different between a subroutine and a function. Formally, the OP's definition is correct. Subroutines don't take arguments or give return values by formal semantics. That's just an interpretion with conventions. And variables in subroutines are accessible in other subroutines of the same file although this can be achieved as well in C with some difficulties.
Summary:
Subroutines work only based on side-effects, in the view of the programming language you are programming with. The concept itself has no explicit arguments or return values. You have to use side effects to simulate them.
Functions are mappings of input to output value(s) in the original sense, some kind of general substitution operation. In the adopted sense of the programming world, functions are an abstraction of subroutines with information about return value and arguments, inspired by mathematical functions. The additional formal abstraction differentiates a function from a subroutine in programming context.
Details:
The subroutine originally is simply a repeatable snippet of code which you can call in between other code. It originates in Assembly or Machine language programming and designates the instruction sequence itself. In the light of this meaning, Perl also uses the term subroutine for its callable code snippets.
Subroutines are concrete objects.
This is what I understood: the concept of a (pure) function is a mathematical concept which is a special case of mathematical relations with an own formal notation. You have an input or argument and it is defined what value is represented by the function with the given argument. The original function concept is entirely unrelated to instructions or calculations. Mathematical operations (or instructions in the programming world) only are a popular formal representation (description) of the actual mapping. The original function term itself is not defined as code. Calculations do not constitute the function, so that functions actually don't have any computational overhead because they are direct mappings. Function complexity considerations only arrived as there is an overhead to find the mapping.
Functions are abstract objects.
Now, since the whole PC-stuff is running on small machine instructions, the easiest way to model (or instantiate) mathematics is with a sequence of instructions itself. Computer Science has been founded by mathematicians (noteworthy: Alan Turing) and the first programming concepts are based on it so there is a need to bring mathematics into the machine. That's how I imagine the reason why "function" is the name of something which is implemented as subroutine and why the term "pure" function was coined to differentiate the original function concept from the overly broad term-use in programming languages.
Note: in Assembly Language Programming, it is typically said, that a subroutine has been passed arguments and gives a return value. This is an interpretation on top of the concrete formal semantics. Calling conventions specify the location where values, to be considered as arguments and return values, should be written to before calling a subroutine or returning. The call itself takes only a subroutine address, and has no formal arguments or return values.
PS: functions in programming languages don't necessarily need to be a subroutine (even though programming language terminology developed this way). Functions in functional programming languages can be constant variables, arrays or hash tables. Isn't every datastructure in ECMAScript a function?
The difference is isolation. A subroutine is just a piece of the program that begins with a label and ends with a go to. A function is outside the namespace of the rest of the program. It is like a separate program that can have the same variable names as used in the calling program, and whatever it does to them does not affect the state of those variables with the same name in the calling program.
From a coding perspective, the isolation means that you don’t have to use the variable names that are local to the function.
Sub double:
a = a + a
Return
fnDouble(whatever):
whatever = whatever + whatever
Return whatever
The subroutine works only on a. If you want to double b you have to set a = b before calling the subroutine. Then you may need to set a to null or zero after. Then when you want to double c you have to again set a to equal c.
Also the sub might have in it some other variable, z, that is changed when the sub is jumped to, which is a bit dangerous.
The essential is isolation of names to the function (unless declared global in the function.)
I am writing this answer from a VBA for excel perspective. If you are writing a function then you can use it as an expression i. e. you can call it from any cell in excel.
eg: normal vlookup function in excel cannot look up values > 256 characters. So I used this function:
Function MyVlookup(Lval As Range, c As Range, oset As Long) As Variant
Dim cl As Range
For Each cl In c.Columns(1).Cells
If UCase(Lval) = UCase(cl) Then
MyVlookup = cl.Offset(, oset - 1)
Exit Function
End If
Next
End Function
This is not my code. Got it from another internet post. It works fine.
But the real advantage is I can now call it from any cell in excel. If wrote a subroutine I couldn't do that.
Every subroutine performs some specific task. For some subroutines, that task is to compute or retrieve some data value. Subroutines of this type are called functions. We say that a function returns a value. Generally, the returned value is meant to be used somehow in the program that calls the function.
Related
I have a huge lib of math functions, like pdf or cdf of statistical distributions. But often e.g. the inverse cdf can be only calculated numerically, e.g. using Newton-Raphson or bisection, in the latter we would need to check if cdf(x) is > or < then the target y0.
However, many functions have further parameters like a Gaussian distribution having certain mean and sigma, so cdf is cdf(x,mean,sigma). Whereas other functions, such as standard normal cdf, have no further parameters, or some have even 3 or 4 further parameters.
A similar problem would happen if you want to apply bisection for either linear functions (2 parameters) or parabolas (3 parameters). Or if you want not the inverse function, but e.g. the integral of f.
The easiest implementation would be to define cdf as global function f(x); and to check for >y0 or global variables.
However, this is a very old-fashioned way, and Freepascal also supports procedural parameters, for calls like x=icdf(0.9987,#cdfStdNorm)
Even overloading is supported to allow calls like x2=icdf(0.9987,0,2,#cdfNorm) to pass also mean and sigma.
But this ends up still in two separate code blocks (even whole functions), because in one case we need to call cdf only with x, and in 2nd example also with mean and sigma.
Is there an elegant solution for this problem in Freepascal? Maybe using variant records? Or an object-oriented approach? I have no glue about OO, but I know the variant object style would require to change at least the headers of many functions because I want to apply the technique not only for inverse cdf calculation, but also to numerical integration, root finding, optimization, etc.
Or is it "best" just to define a real function type with e.g. x + 5 parameters (maybe as array), and to ignore the unused parameters? But for me it looks that then I would need many "wrapper" functions or to re-code all the existing functions (to use the arrays, even if they are sometimes not needed!).
Maybe macros can help as well? Any Freepascal hints are very welcome!
If you make it a (function .. of object), mean and sigma could be part of the class, and the function could internally just access it. Only the really changing parameters during the iteration would be parameters. (read: x)
Anonymous methods as talked about by David and Rudy is a further step to avoid having to declare a class for each such invocation, but that is convenience thing and IMHO not the core of the question. At the expense of declaring the class, your core code is free of global variable use and anonymous methods might also come with a performance cost, depending on usage.
Free Pascal also supports nested functions (function... is nested), which is the original Pascal closure-like way which was never adopted by Pascal compilers from Borland. A nested procedure passed as callback can access local variables in the procedure where it was declared. The Free Pascal numlib numeric math package uses this in some cases for similar cases like yours. For math it is even more natural.
Delphi never implements old constructs because borrowing syntax from other languages looks better on bulletlists and keeps the subscriptions flowing.
I am trying to integrate two Fortran-90 subroutines in one main function. The algorithm used in both the subroutines is logically similar but differs in array sizes (e.g. using 4 parameters to calculate a value instead of 3 etc).
I can either declare the array, allocate memory in main function and pass it as argument to subroutine or have the subroutine do it when called. In former case I will end up passing on a lot of arguments and in the latter case I will end up allocating and de-allocating variables a lot of times but passing only few arguments during subroutine call.
As the code might end up calling the subroutines several thousand times, I want to make sure that I choose the mot efficient way to achieve my goal. Can somebody shed any light on this?
If the arguments are conceptually linked you could create an object (derived data type) containing the parameters you want to use as arguments and pass the object to the subroutine.
I was under the impression that the main differences between subroutines and functions in Fortran was that functions returned values, while subroutines change some or all of the values passed as arguments. But then I learned that you could modify variables passed in to functions as arguments too. I'm confused, and can't find a good reference for the differences between them.
So, what are the differences between the two constructs, and when and why should one be preferred over the other?
Whether to use one or another is more or less a matter of programming style. You are allowed to write the arguments of both functions and subroutines as intent(in), intent(inout) or intent(out).
My personal style is however to only use the intent(in) arguments for functions, which is also a requirement for pure functions. An exception to this rule can be made when en error code intent(out) argument is necessary.
There is a subtle trap hidden in functions which return different results for the same input argument value. Consider a hypothetical function returning a random number
real function rnd()
end function
calling it once
x = rnd()
is completely OK. Calling it multiple times in a single expression
x = (rnd() + rnd()) / 2
can result in the function being called only once. Fortran language rules allow such behaviour. Therefore, the standard Fortran procedure for getting random numbers random_number() is a subroutine (and because all intrinsic functions are pure).
Where ever you cannot use a function, use a subroutine.
Any function can by converted to a subroutine by moving the result variable to a dummy argument with intent(out). The opposite process may be more problematic.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between a ‘function’ and a ‘procedure’?
I searched online for an answer to this question, and the answer I got was that a function can return a value, modify a value, etc., but a subroutine cannot. But I am not satisfied with this explanation and it seems to me that the difference ought to be more than just a matter of terminology.
So I am looking for a more conceptual answer to the question.
A function mirrors the mathematical definition of a function, which is a mapping from 1 or more inputs to a value.1
A subroutine is a general-purpose term for any chunk of code that has a definite entry point and exit point.
However, the precise meaning of these terms will vary from context to context.
1. Obviously, this is not the formal mathematical definition of a function.
A generic definition of function in programming languages is a piece of code that accepts zero or more input values and returns zero or one output value.
The most common definition of subroutine is a function that does not return anything and normally does not accept anything. It is only a piece of code with a name.
Actually in most languages functions do not differ in the way you declare them. So a subroutine may be called a function, but a function not necessarily may be called a subroutine.
Also there is people that consider functions and subroutines the same thing with a different name.
Subroutine - Wikipedia
It's worth noting as an addendum to #Oli's answer that in the mathematical sense a function must be "well-defined", which is to say its output is uniquely determined by its inputs, while this often isn't the case in programming languages.
Those that do make this guarantee (and also that their functions not cause side-effects) are called pure functional languages, an example of which being Haskell. They have the advantage (among others) of their functions being provably correct in their behaviour, which is generally not possible if functions rely on external state and/or have side-effects.
A function must return some value and must not change a global variable or a variable declared outside of the function's body. Under this situation, a function can only mimic it's mathematical counter part (the thing which maps a mathematical object to another mathematical object)
A subroutine doesn't return anything and usually is impure as it has to change some global state or variable otherwise there is no point in calling it. There is no mathematical parallel for a subroutine.
After much painful debugging, I believe I've found a unique property of Fortran that I'd like to verify here at stackoverflow.
What I've been noticing is that, at the very least, the value of internal logical variables are preserved across function or subroutine calls.
Here is some example code to illustrate my point:
PROGRAM function_variable_preserve
IMPLICIT NONE
CHARACTER(len=8) :: func_negative_or_not ! Declares function name
INTEGER :: input
CHARACTER(len=8) :: output
input = -9
output = func_negative_or_not(input)
WRITE(*,10) input, " is ", output
10 FORMAT("FUNCTION: ", I2, 2A)
CALL sub_negative_or_not(input, output)
WRITE(*,20) input, " is ", output
20 FORMAT("SUBROUTINE: ", I2, 2A)
WRITE(*,*) 'Expected negative.'
input = 7
output = func_negative_or_not(output)
WRITE(*,10) input, " is ", output
CALL sub_negative_or_not(input, output)
WRITE(*,20) input, " is ", output
WRITE(*,*) 'Expected positive.'
END PROGRAM function_variable_preserve
CHARACTER(len=*) FUNCTION func_negative_or_not(input)
IMPLICIT NONE
INTEGER, INTENT(IN) :: input
LOGICAL :: negative = .FALSE.
IF (input < 0) THEN
negative = .TRUE.
END IF
IF (negative) THEN
func_negative_or_not = 'negative'
ELSE
func_negative_or_not = 'positive'
END IF
END FUNCTION func_negative_or_not
SUBROUTINE sub_negative_or_not(input, output)
IMPLICIT NONE
INTEGER, INTENT(IN) :: input
CHARACTER(len=*), INTENT(OUT) :: output
LOGICAL :: negative = .FALSE.
IF (input < 0) THEN
negative = .TRUE.
END IF
IF (negative) THEN
output = 'negative'
ELSE
output = 'positive'
END IF
END SUBROUTINE sub_negative_or_not
This is the output:
FUNCTION: -9 is negative
SUBROUTINE: -9 is negative
Expected negative.
FUNCTION: 7 is negative
SUBROUTINE: 7 is negative
Expected positive.
As you can see, it appears that once the function or subroutine is called once, the logical variable negative, if switched to .TRUE., remains as such despite the initialization of negative to .FALSE. in the type declaration statement.
I could, of course, correct this problem by just adding a line
negative = .FALSE.
after declaring the variable in my function and subroutine.
However, it seems very odd to me that this be necessary.
For the sake of portability and code reusability, shouldn't the language (or compiler maybe) require re-initialization of all internal variables each time the subroutine or function is called?
To answer your question: Yes Fortran does preserve the value of internal variables through function and subroutine calls.
Under certain conditions ...
If you declare an internal variable with the SAVE attribute it's value is saved from one call to the next. This is, of course, useful in some cases.
However, your question is a common reaction upon first learning about one of Fortran's gotchas: if you initialise an internal variable in its declaration then it automatically acquires the SAVE attribute. You have done exactly that in your subroutines. This is standard-conforming. If you don't want this to happen don't initialise in the declaration.
This is the cause of much surprise and complaint from (some) newcomers to the language. But no matter how hard they complain it's not going to change so you just have to (a) know about it and (b) program in awareness of it.
This isn't too different from static function-scoped variables in C or C++.
Programming language design was in its infancy, back when FORTRAN was
developed. If it were being designed from scratch today, no doubt many of the design
decisions would have been different.
Originally, FORTRAN didn't even support recursion, there was no dynamic memory
allocation, programs played all sorts of type-punning games with COMMON blocks
and EQUIVALENCE statements, procedures could have multiple entry points....so the
memory model was basically for the compiler/linker to lay out everything, even local
variables and numeric literal constants, into fixed storage locations, rather than on
the stack. If you wanted, you could even write code that changed the value of "2" to
"42"!
By now, there is an awful lot of legacy FORTRAN code out there, and compiler writers go to great lengths to preserve backward-compatible semantics. I can't quote chapter and verse from the standard that mandates the behavior you've noted, nor its rationale, but it seems reasonable that backward compatibility trumped modern language design sensibilities, in this instance.
This has been discussed several times here, most recently at Fortran assignment on declaration and SAVE attribute gotcha
You don't have to discover this behavior by experimentation, it is clearly stated in the better textbooks.
Different languages are different and have different behaviors.
There is a historical reason for this behavior. Many compilers for Fortran 77 and earlier preserved the values of ALL local variables across calls of procedures. Programmers weren't supposed to rely upon this behavior but many did. According to the standard, if you wanted a local variable (non-COMMON) to retain its value you needed to use "SAVE". But many programmers ignored this. In that era programs were less frequently ported to different platforms and compilers, so incorrect assumptions might never be noticed. It is common to find this problem in legacy programs -- current Fortran compilers typically provide a compiler switch to cause all variables to be saved. It would be silly for the language standard to require that all local variables retain their values. But an intermediate requirement that would rescue many programs that were careless with "SAVE" would be to require all variables initialized in their declarations to automatically have the SAVE attribute. Hence what you discovered....