They can result if you try to make a virtual function call from a constructor or destructor. Since you can't make a virtual function call from a constructor or destructor (the derived class object hasn't been constructed or has already been destroyed), it calls the base class version, which in the case of a pure virtual function, doesn't exist.
class Base
{
public:
Base() { reallyDoIt(); }
void reallyDoIt() { doIt(); } // DON'T DO THIS
virtual void doIt() = 0;
};
class Derived : public Base
{
void doIt() {}
};
int main(void)
{
Derived d; // This will cause "pure virtual function call" error
}
See also Raymond Chen's 2 articles on the subject
As well as the standard case of calling a virtual function from the constructor or destructor of an object with pure virtual functions you can also get a pure virtual function call (on MSVC at least) if you call a virtual function after the object has been destroyed. Obviously this is a pretty bad thing to try and do but if you're working with abstract classes as interfaces and you mess up then it's something that you might see. It's possibly more likely if you're using referenced counted interfaces and you have a ref count bug or if you have an object use/object destruction race condition in a multi-threaded program... The thing about these kinds of purecall is that it's often less easy to fathom out what's going on as a check for the 'usual suspects' of virtual calls in ctor and dtor will come up clean.
To help with debugging these kinds of problems you can, in various versions of MSVC, replace the runtime library's purecall handler. You do this by providing your own function with this signature:
int __cdecl _purecall(void)
and linking it before you link the runtime library. This gives YOU control of what happens when a purecall is detected. Once you have control you can do something more useful than the standard handler. I have a handler that can provide a stack trace of where the purecall happened; see here: http://www.lenholgate.com/blog/2006/01/purecall.html for more details.
(Note you can also call _set_purecall_handler() to install your handler in some versions of MSVC).
ELI5: what the heck is a "pure virtual function" in c++, and why do things crash when they call one?
functional programming - Can a pure function call external function? - Stack Overflow
Is a function getting a value from another function considered pure?
functional programming - Should a pure function take all of the functions it calls as arguments? - Computer Science Stack Exchange
Videos
title, for context, i noticed a payday 2 crash log of mine had that as the crash reason, and any explanation i can find on c++ forums is very confusing, and overwhelms me instantly lol
When you can
A pure function f can call any other function/method g0...gn.
However, g0...gn must be pure as well.
When you cannot
As soon as you get a pure function f and you invoke a non pure function g from within f, then f is no longer pure.
Yes, it is pure. It doesn't mutate any global state nor gives different results for same input.
Is a function getting a value from another function considered pure?
That depends on what the other function does, and what the calling function does. Impurity is infectious, purity isn't.
Calling a pure function doesn't change the purity of the calling function. Calling an impure function automatically makes the calling function impure also.
So, in your example, it depends on the purity of the part you left out: if that is pure, then the whole function is pure.
If this is a pure function, what is the difference from just using a global DEFAULT_SEPARATOR constant instead?
Nothing. A function that always returns the same value is indistinguishable from a constant. In fact, that is exactly how constants are modeled in λ-calculus.
Yes, those are both pure functions (assuming the elided part is also pure) because:
- The result depends only on the parameters.
- There are no side effects.
Note that if getDefaultSeparator() was not a pure function, then neither would process() be pure.
In Javascript, there's no meaningful difference between using a pure function or a constant and both can be used by pure function, as long as Javascript's ability to redefine functions or alter the values of constants is avoided.
A key concept behind pure functions is that they could be replaced with the value they return without affecting the results of the program.
No, f doesn't have to take g as an argument. Wikipedia's definition is a bit informal. Also informally, the behavior of a pure function is also allowed to depend on the code of the program. Or, to put it another way, the code of the program is considered fixed, not something we vary, so we don't try to track dependences on it.
So, something like f(x) = 2*g(x) is fine: if g is pure, f will be too.
No. For an algebraic structure over a set you fix the set of function symbols and the set of variables from the start. Then you can think of functions as constants. (Technically constants are functions with zero argument but anyway.) Therefore calling (pure) functions does not disrupt the purity.
The dollarToEuro's return value depends on an outside variable that is not an argument; therefore, the function is impure.
If the answer is NO, how then can we refactor the function to be pure?
One option is to pass in exchangeRate. This way, every time arguments are (something, somethingElse), the output is guaranteed to be something * somethingElse:
const exchangeRate = fetchFromDatabase(); // evaluates to say 0.9 for today;
const dollarToEuro = (x, exchangeRate) => {
return x * exchangeRate;
};
Note that for functional programming, you should avoid let - always use const to avoid reassignment.
Technically, any program that you execute on a computer is impure because it eventually compiles down to instructions like “move this value into eax” and “add this value to the contents of eax”, which are impure. That's not very helpful.
Instead, we think about purity using black boxes. If some code always produces the same outputs when given the same inputs then it's considered to be pure. By this definition, the following function is also pure even though internally it uses an impure memo table.
const fib = (() => {
const memo = [0, 1];
return n => {
if (n >= memo.length) memo[n] = fib(n - 1) + fib(n - 2);
return memo[n];
};
})();
console.log(fib(100));
We don't care about the internals because we are using a black box methodology for checking for purity. Similarly, we don't care that all code is eventually converted to impure machine instructions because we're thinking about purity using a black box methodology. Internals are not important.
Now, consider the following function.
const greet = name => {
console.log("Hello %s!", name);
};
greet("World");
greet("Snowman");
Is the greet function pure or impure? By our black box methodology, if we give it the same input (e.g. World) then it always prints the same output to the screen (i.e. Hello World!). In that sense, isn't it pure? No, it's not. The reason it's not pure is because we consider printing something to the screen a side effect. If our black box produces side effects then it is not pure.
What is a side effect? This is where the concept of referential transparency is useful. If a function is referentially transparent then we can always replace applications of that function with their results. Note that this is not the same as function inlining.
In function inlining, we replace applications of a function with the body of the function without altering the semantics of the program. However, a referentially transparent function can always be replaced with its return value without altering the semantics of the program. Consider the following example.
console.log("Hello %s!", "World");
console.log("Hello %s!", "Snowman");
Here, we inlined the definition of greet and it didn't change the semantics of the program.
Now, consider the following program.
undefined;
undefined;
Here, we replaced the applications of the greet function with their return values and it did change the semantics of the program. We are no longer printing greetings to the screen. That's the reason why printing is considered a side effect, and that's why the greet function is impure. It's not referentially transparent.
Now, let's consider another example. Consider the following program.
const main = async () => {
const response = await fetch("https://time.akamai.com/");
const serverTime = 1000 * await response.json();
const timeDiff = time => time - serverTime;
console.log("%d ms", timeDiff(Date.now()));
};
main();
Clearly, the main function is impure. However, is the timeDiff function pure or impure? Although it depends upon serverTime which comes from an impure network call, it is still referentially transparent because it returns the same outputs for the same inputs and because it doesn't have any side effects.
zerkms will probably disagree with me on this point. In his answer, he said that the dollarToEuro function in the following example is impure because “it depends upon the IO transitively.”
const exchangeRate = fetchFromDatabase(); // evaluates to say 0.9 for today;
const dollarToEuro = (x, exchangeRate) => {
return x * exchangeRate;
};
I have to disagree with him because the fact that the exchangeRate came from a database is irrelevant. It's an internal detail and our black box methodology for determining the purity of a function doesn't care about internal details.
In purely functional languages like Haskell, we have an escape hatch for executing arbitrary IO effects. It's called unsafePerformIO, and as the name implies if you do not use it correctly then it's not safe because it might break referential transparency. However, if you do know what you're doing then it's perfectly safe to use.
It's generally used for loading data from configuration files near the beginning of the program. Loading data from config files is an impure IO operation. However, we don't want to be burdened by passing the data as inputs to every function. Hence, if we use unsafePerformIO then we can load the data at the top level and all our pure functions can depend upon the immutable global config data.
Note that just because a function depends upon some data loaded from a config file, a database, or a network call, doesn't mean that the function is impure.
However, let's consider your original example which has different semantics.
let exchangeRate = fetchFromDatabase(); // evaluates to say 0.9 for today;
const dollarToEuro = (x) => {
return x * exchangeRate;
};
dollarToEuro(100) //90 today
dollarToEuro(100) //something else tomorrow
Here, I'm assuming that because exchangeRate is not defined as const, it's going to be modified while the program is running. If that's the case then dollarToEuro is definitely an impure function because when the exchangeRate is modified, it'll break referential transparency.
However, if the exchangeRate variable is not modified and will never be modified in the future (i.e. if it's a constant value), then even though it's defined as let, it won't break referential transparency. In that case, dollarToEuro is indeed a pure function.
Note that the value of exchangeRate can change every time you run the program again and it won't break referential transparency. It only breaks referential transparency if it changes while the program is running.
For example, if you run my timeDiff example multiple times then you'll get different values for serverTime and therefore different results. However, because the value of serverTime never changes while the program is running, the timeDiff function is pure.
A pure function is a function that meets 2 requirements:
- Given the same input, it will always return the same output.
- Produces no side effects.
Side effects can be defined as 'any application state change that is observable outside the called function other than its return value'.
To be more specific:
A function that modifies anything outside it's scope (even if it's not the global scope) is not a pure function.
In your example, if func2 modifies a variable outside its own scope, then it's not a pure function:
function func1() {
let name = "My Name"; // <-- the variable is not in the global scope but, in any case, it is outside the scope of func2
func2();
function func2() {
// alter name here.
}
}
Purity is not defined to care only about global variables, it cares about any non-local variables (and more) that shouldn't be mutated. An outer variable of a closure still counts as non-local, it doesn't need to be global.
So if func2 changes name, then it's impure. Whether func1 becomes impure as well through that depends on whether you consider only external purity - as long as name and func2 stay local within the function, it may still be pure.
My understanding has always been that if it doesnt change anything outside of itself it can be pure. On asking people about this in the past they have responded with "basically, yes".
But what about none-basically? Is there more to it than that?