Please note: by a "pure" function, I don't mean "pure virtual"
I'm referring to this
If a function "reads" some global state, does that automatically render it impure? or does it depend on other factors?
If it automatically renders it impure, please explain why.
If it depends on other factors, please explain what are they.
A "pure" function is a function whose result depends only on its input arguments. If it reads anything else, it is not a pure function.
In certain specialized instances, yes. For example, if you had a global cache of already-computed values that was only read and written by your function, it would still be mathematically pure, in the sense that the output only depended on the inputs, but it wouldn't be pure in the strictest sense. For example:
static int cache[256] = {0};
int compute_something(uint8_t input)
{
if(cache[input] == 0)
cache[input] = (perform expensive computation on input that won't return 0);
return cache[input];
}
In this case, so long as no other function touches the global cache, it's still a mathematically pure function, even though it technically depends on external global state. However, this state is just a performance optimization -- it would still perform the same computation without it, just more slowly.
Pure functions are required to construct pure expressions. Constant expressions are pure by definition.
So, if your global 'state' doesn't change you are fine.
Also see referential transparency:
A more subtle example is that of a function that uses a global variable (or a dynamically scoped variable, or a lexical closure) to help it compute its results. Since this variable is not passed as a parameter but can be altered, the results of subsequent calls to the function can differ even if the parameters are identical. (In pure functional programming, destructive assignment is not allowed; thus a function that uses global (or dynamically scoped) variables is still referentially transparent, since these variables cannot change.)
In Haskell for instance, you can create an endless list of random numbers on the impure side, and pass that list to your pure function. The implementation will generate the next number your pure function is using only when it needs it, but the function is still pure.
Related
In my Simulink model I have several Function Caller blocks like this:
Simple Function Caller block
The function prototype would simply be y = someFunction(). The output argument uses a custom enum type and is given as someEnum(1).
The output signal is defined as one-dimensional throughout.
When generating code from the model, these Function Callers have always yielded a function stub in the expected form of
extern someEnum someFunction(void);.
However, after a lot of changes recently, I've just noticed that code generation now suddenly yields function stubs in the form of
extern void someFunction(someEnum *rty_y);
for some (not all!) Function Caller blocks.
I have compared every parameter about the Function caller blocks and the related output signals that I could find but I can't find any difference between the affected ones and those working as expected in the current version or the same blocks in previous versions. All functions and signals have been renamed, but that's also true for those Function Caller blocks that are not affected.
The Code Generation options are also identical.
I have tried to understand from the help files what might cause the coder to use pointer arguments instead of direct return values for the function stubs but couldn't find anything.
Any hint at what might cause the code generator to use pointers would be greatly appreciated.
Found the problem. Some of the affected blocks had their C/C++ return argument set to "void" in their "Configure C/C++ Function Interface" dialog.
Some of the affected blocks (unfortunately, both of those I had checked before as well) were still set to "y" here and I had to change the setting to "void" and back to "y" before it yielded the desired result.
I have following function:
def timestamp(key: String)
: String
= Monoid.combine(key, Instant.now().getEpochSecond.toString)
and wanted to know, if it is pure or not? A pure function for me is, given the same input returns always the same output. But the function above, given always the same string will returns another string with another time, that it is in my opinion not pure.
No, it's not pure by any definition I know of. A good discussion of pure functions is here: https://alvinalexander.com/scala/fp-book/definition-of-pure-function. In Alvin's definition of purity he says:
A pure function has no “back doors,” which means:
...
It cannot depend on any external I/O. It can’t rely on input from files, databases, web services, UIs, etc; it can’t produce output, such as writing to a file, database, or web service, writing to a screen, etc.
Reading the time of the current system uses I/O so it is not pure.
You are right, it is not a pure function as it returns different result for the same arguments. Mathematically speaking it is not a function at all.
Definition of Pure function from Wikipedia
The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices (usually—see below).
Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices (usually—see below).
First, I have had a look at this excellent article already.
I have a MATLAB script, called sdp. I have another MATLAB script called track. I run track after sdp, as track uses some of the outputs from sdp. To run track I need to call a function called action many many times. I have action defined as a function in a separate MATLAB file. Each call of this action has some inputs, say x1,x2,x3, but x2,x3are just "data" which will never change. They were the same in sdp, same in track, and will remain the same in action. Here, x2,x3 are huge matrices. And there are many of them (think like x2,x3,...x10)
The lame way is to define x2,x3 as global in sdp and then in track, so I can call action with only x1. But this slows down my performance incredibly. How can I call action again and again with only x1 such that it remembers what x2,x3 are? Each call is very fast, and if I do this inline for example, it is super fast.
Perhaps I can use some persistent variables. But I don't understand exactly if they are applicable to my example. I don't know how to use them exactly either.
Have a look at object oriented programming in Matlab. Make an action object where you assign the member variables x2 ... to the results from sdp. You can then call a method of action with only x1. Think of the object as a function with state, where the state information in your case are the constant results of sdp.
Another way to do this would be to use a functional approach where you pass action to track as a function handle, where it can operate on the variables of track.
Passing large matrices in MATLAB is efficient. Semantically it uses call-by-value, but it's implemented as call-by-reference until modified. Wrap all the unchanging parameters in a struct of parameters and pass it around.
params.x2 = 1;
params.x3 = [17 39];
params.minimum_velocity = 19;
action('advance', params);
You've already discovered that globals don't perform well. Don't worry about the syntactic sugar of hiding variables somewhere... there are advantages to clearly seeing where the inputs come from, and performance will be good.
This approach also makes it easy to add new data members, or even auxiliary metadata, like a description of the run, the time it was executed, etc. The structs can be combined into arrays to describe multiple runs with different parameters.
I am learning functional programming and I can understand why immutability is preferred over mutable objects.
This article also explains it well.
But I am unable to understand why assignments should be performed inside of pure functions.
One reason that I can understand is variable mutability leads to locking and since in a pure function in scala we mostly tail recursion and this creates variables/objects on the call stack rather than a heap.
Is there any other reason why one should avoid variable assignment in functional programming.
There is a difference between assignments and re-assignments. re-assignments are not allowed in functional programming because its mutability is not allowed in pure functions.Variable assignment is allowed.
val a = 1 //assignment allowed
a = 2 //re-assignment not allowed
Reading in a impure fashion (changing state) from the external world is a side-effect in functional programming.
So, function accessing a global variable which can potentially be mutated is not pure.
Just makes life easy.
Generally
When you are disciplined life is less chaotic. Thats exactly what functional programming advocates. When life is less chaotic you can concentrate on better things in life.
So, the main reason for immutability
It becomes hard to reason about the correctness of the program with mutations. In case of concurrent programs this is very painful to debug.
that means it becomes hard to keep track of changes variables undergo in order to understand the code/program or to debug the program.
Mutation is one of the side effect where which makes program hard to understand and reason about.
Functional programming enforces this discipline (use of immutability) so that code is maintainable, expressive and understandable.
Mutation is one of the side effects
Pure function is that one which does not have side effects.
Side effects:
Mutation of variables
Mutation of mutable data structures
Reading or writing to a file/console (external source)
Throwing exceptions to the halt program
Avoiding above mentioned side effects makes a function depend only on the parameters of the function rather than any outside values or state.
Pure function is the most isolated function which neither reads from the world nor writes to the world. It does not halt or break the program control flow.
The above properties make the pure function easy to understand and reason about.
Pure function is mathematical function
Its a mapping from co-domain to range where every value in co-domain is mapped to exactly one value in range.
That means if f(2) is equal to 4 then f(2) is 4 irrespective of what the state of the world is.
Pure function is a relation between a set of inputs and a set of permissible outputs with the property that each input is related to exactly one output.
How to implement Software in the Loop for control systems design with Modelica (OpenModelica, jModelica) for a plant and C/C++ routine for a controller. What approaches you can suggest?
I thought external C Functions would help but seems they have some restrictions such that they should obey reference transparancy property ie return the same values for the same inputs (should not have internal states).
In that case, the issue with calling external C functions does not apply. It is true that Modelica restricts the use of functions in the continuous equations such that the function must return the same value for the same arguments. In those cases, you must find a way to pass the state into the function and have it return the new state (if you want to satisfy this "purity" requirement). This is obviously quite tedious to do with C code (you would have to pass in the state, assign all state variables (probably globals) run your code, then extract the values of all the state variables and return them).
Fortunately for you, you don't need to worry about this. The reason is because your function only needs to be called from within a when clause. If you are triggering your when clause based on time (e.g. using the sample(...) function), I'm pretty sure you are guaranteed that the function will only be invoked once at each time.
Basically, your setup would be something like this:
algorithm
when sample(0, sample_rate) then
u := controllerEvaluation(x, y, t);
end when;
In this way, you can pass time, the necessary states, x, and inputs, y (or u, depending on your perspective), into the controller and you get back the controller command to the plant, u.
In this context, the when clause is a representation of your scheduler and because it doesn't include any state events (like you would have, for example, with a tooth wheel encoder or other asynchronous interrupt) the simulator can schedule all these function invocations without any risk of having to repeat them.