Is a memoized pure function itself considered pure?Haskell ways to the 3n+1 problemCompute if a function is...
What is this fighter jet at Weymouth NAS?
Prevent use of CNAME record for untrusted domain
Is first Ubuntu user root?
Did Dr. Hannibal Lecter like Clarice or was he attracted to her?
How can I download a file from a host I can only SSH to through another host?
Open subspaces of CW complexes
Why did my folder names end up like this, and how can I fix this using a script?
How many birds in the bush?
Redacting URLs as an email-phishing preventative?
Why is the UK so keen to remove the "backstop" when their leadership seems to think that no border will be needed in Northern Ireland?
How to use properly "sich selbst"
Breaker Mapping Questions
Location of label edges in Tikz Graph
"There were either twelve sexes or none."
Beginner to guitar playing - where should I begin?
Billiard balls collision
Joining lists with same elements
Is this password scheme legit?
Number of academics in various EU countries
Do you pay one or two mana to bounce a transformed Delver of Secrets with Repeal?
Hangman game in Python - need feedback on the quality of code
Contours of a national emergency in the United States
What's special ammo in Destiny 2?
Where does learning new skills fit into Agile?
Is a memoized pure function itself considered pure?
Haskell ways to the 3n+1 problemCompute if a function is pureIs this method pure?When to use [Pure] on a constructor?Programatically determine that some functions are pureCan a function be pure if it depends on an immutable instance field?Is anything gained by making dependencies explicit via function argument lists when implementing pure methods?Naming conventions for pure functionsPure functional vs tell, don't ask?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
Let’s say fn(x) is a pure function that does something expensive, like returning a list of the prime factors of x.
And let’s say we make a memoized version of the same function called memoizedFn(x). It always returns the same result for a given input, but it maintains a private cache of previous results to improve performance.
Formally speaking, is memoizedFn(x) considered pure?
Or is there some other name or qualifying term used to refer to such a function in FP discussions? (i.e. a function with side effects that may affect the computational complexity of subsequent calls but that may not affect the return values.)
terminology pure-function
add a comment |
Let’s say fn(x) is a pure function that does something expensive, like returning a list of the prime factors of x.
And let’s say we make a memoized version of the same function called memoizedFn(x). It always returns the same result for a given input, but it maintains a private cache of previous results to improve performance.
Formally speaking, is memoizedFn(x) considered pure?
Or is there some other name or qualifying term used to refer to such a function in FP discussions? (i.e. a function with side effects that may affect the computational complexity of subsequent calls but that may not affect the return values.)
terminology pure-function
5
Maybe it is not pure for purists, but "pure enough" for pragmatic people ;-)
– Doc Brown
10 hours ago
@DocBrown I agree, just wondering if there’s a more formal term for ‘pure enough’
– callum
10 hours ago
Executing a pure function will most likely modify the processor's instruction cache, branch predictors etc. But that's probably "pure enough" for purists as well - or you can forget about pure functions altogether.
– gnasher729
8 hours ago
@callum No, there is no formal definition of "pure enough". When arguing about purity and the semantic equivalence of two "referentially transparent" calls, you always have to state exactly which semantics you are going to apply. At some low level of implementation detail it will always break down and have different memory effects or timings. That's why you have to be pragmatic: what level of detail is useful for reasoning about your code?
– Bergi
52 mins ago
add a comment |
Let’s say fn(x) is a pure function that does something expensive, like returning a list of the prime factors of x.
And let’s say we make a memoized version of the same function called memoizedFn(x). It always returns the same result for a given input, but it maintains a private cache of previous results to improve performance.
Formally speaking, is memoizedFn(x) considered pure?
Or is there some other name or qualifying term used to refer to such a function in FP discussions? (i.e. a function with side effects that may affect the computational complexity of subsequent calls but that may not affect the return values.)
terminology pure-function
Let’s say fn(x) is a pure function that does something expensive, like returning a list of the prime factors of x.
And let’s say we make a memoized version of the same function called memoizedFn(x). It always returns the same result for a given input, but it maintains a private cache of previous results to improve performance.
Formally speaking, is memoizedFn(x) considered pure?
Or is there some other name or qualifying term used to refer to such a function in FP discussions? (i.e. a function with side effects that may affect the computational complexity of subsequent calls but that may not affect the return values.)
terminology pure-function
terminology pure-function
edited 8 hours ago
Robert Harvey♦
172k47 gold badges403 silver badges611 bronze badges
172k47 gold badges403 silver badges611 bronze badges
asked 10 hours ago
callumcallum
4,4448 gold badges23 silver badges27 bronze badges
4,4448 gold badges23 silver badges27 bronze badges
5
Maybe it is not pure for purists, but "pure enough" for pragmatic people ;-)
– Doc Brown
10 hours ago
@DocBrown I agree, just wondering if there’s a more formal term for ‘pure enough’
– callum
10 hours ago
Executing a pure function will most likely modify the processor's instruction cache, branch predictors etc. But that's probably "pure enough" for purists as well - or you can forget about pure functions altogether.
– gnasher729
8 hours ago
@callum No, there is no formal definition of "pure enough". When arguing about purity and the semantic equivalence of two "referentially transparent" calls, you always have to state exactly which semantics you are going to apply. At some low level of implementation detail it will always break down and have different memory effects or timings. That's why you have to be pragmatic: what level of detail is useful for reasoning about your code?
– Bergi
52 mins ago
add a comment |
5
Maybe it is not pure for purists, but "pure enough" for pragmatic people ;-)
– Doc Brown
10 hours ago
@DocBrown I agree, just wondering if there’s a more formal term for ‘pure enough’
– callum
10 hours ago
Executing a pure function will most likely modify the processor's instruction cache, branch predictors etc. But that's probably "pure enough" for purists as well - or you can forget about pure functions altogether.
– gnasher729
8 hours ago
@callum No, there is no formal definition of "pure enough". When arguing about purity and the semantic equivalence of two "referentially transparent" calls, you always have to state exactly which semantics you are going to apply. At some low level of implementation detail it will always break down and have different memory effects or timings. That's why you have to be pragmatic: what level of detail is useful for reasoning about your code?
– Bergi
52 mins ago
5
5
Maybe it is not pure for purists, but "pure enough" for pragmatic people ;-)
– Doc Brown
10 hours ago
Maybe it is not pure for purists, but "pure enough" for pragmatic people ;-)
– Doc Brown
10 hours ago
@DocBrown I agree, just wondering if there’s a more formal term for ‘pure enough’
– callum
10 hours ago
@DocBrown I agree, just wondering if there’s a more formal term for ‘pure enough’
– callum
10 hours ago
Executing a pure function will most likely modify the processor's instruction cache, branch predictors etc. But that's probably "pure enough" for purists as well - or you can forget about pure functions altogether.
– gnasher729
8 hours ago
Executing a pure function will most likely modify the processor's instruction cache, branch predictors etc. But that's probably "pure enough" for purists as well - or you can forget about pure functions altogether.
– gnasher729
8 hours ago
@callum No, there is no formal definition of "pure enough". When arguing about purity and the semantic equivalence of two "referentially transparent" calls, you always have to state exactly which semantics you are going to apply. At some low level of implementation detail it will always break down and have different memory effects or timings. That's why you have to be pragmatic: what level of detail is useful for reasoning about your code?
– Bergi
52 mins ago
@callum No, there is no formal definition of "pure enough". When arguing about purity and the semantic equivalence of two "referentially transparent" calls, you always have to state exactly which semantics you are going to apply. At some low level of implementation detail it will always break down and have different memory effects or timings. That's why you have to be pragmatic: what level of detail is useful for reasoning about your code?
– Bergi
52 mins ago
add a comment |
3 Answers
3
active
oldest
votes
Yes. The memoized version of a pure function is also a pure function.
All that function purity cares about is the effect that input parameters on the return value of the function (passing the same input should always produce the same output) and any side effects relevant to global states (e.g. text to the terminal or UI or network). Computation time and extra memory usages is irrelevant to function purity.
Caches of a pure function is pretty much invisible to the program, a functional programming language is allowed to automatically optimise a pure function to a memoized version of the function if it can determine that it'll be beneficial to do so. In practice, automatically determining when memoization is beneficial is actually quite a difficult problem, but such optimisation would be valid.
add a comment |
Wikipedia defines a "Pure Function" as a function that has the following properties:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).
In effect, a pure function returns the same output given the same input, and doesn't affect anything else outside of the function. For purposes of purity, it doesn't matter how the function computes its return value, so long as it returns the same output given the same input.
Functionally pure languages like Haskell routinely use memoization to speed up a function by caching its previously computed results.
add a comment |
It depends on how you do it.
Usually people want to memoize by mutating some sort of cache dictionary. This has all the problems associated with impure mutation, such as having to worry about concurrency, worrying about the cache growing too large, etc.
However, you can memoize without impure memory mutation. One example is in this answer, where I track the memoized values externally by means of a lengths argument.
In the link Robert Harvey provided, lazy evaluation is used to avoid side effects.
Another technique sometimes seen is to explicitly mark the memoization as an impure side effect in the context of an IO type, such as with cats-effect's memoize function.
This last one brings up the point that sometimes the goal is just encapsulating mutation rather than eliminating it. Most functional programmers consider it "pure enough" to make impurity explicit and encapsulated.
If you want a term to differentiate it from a truly pure function, I think it's sufficient to just say "memoized with a mutable dictionary." That lets people know how to use it safely.
I don't think any of the purer solution solves the above problems: While you lose any concurrency worries, you also lose any chance for two concurrently started calls likecollatz(100)andcollatz(200)to cooperate. And IIUIC, the problem with cache growing too large remains (though Haskell may have some nice tricks for this?).
– maaartinus
33 mins ago
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "131"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f396501%2fis-a-memoized-pure-function-itself-considered-pure%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Yes. The memoized version of a pure function is also a pure function.
All that function purity cares about is the effect that input parameters on the return value of the function (passing the same input should always produce the same output) and any side effects relevant to global states (e.g. text to the terminal or UI or network). Computation time and extra memory usages is irrelevant to function purity.
Caches of a pure function is pretty much invisible to the program, a functional programming language is allowed to automatically optimise a pure function to a memoized version of the function if it can determine that it'll be beneficial to do so. In practice, automatically determining when memoization is beneficial is actually quite a difficult problem, but such optimisation would be valid.
add a comment |
Yes. The memoized version of a pure function is also a pure function.
All that function purity cares about is the effect that input parameters on the return value of the function (passing the same input should always produce the same output) and any side effects relevant to global states (e.g. text to the terminal or UI or network). Computation time and extra memory usages is irrelevant to function purity.
Caches of a pure function is pretty much invisible to the program, a functional programming language is allowed to automatically optimise a pure function to a memoized version of the function if it can determine that it'll be beneficial to do so. In practice, automatically determining when memoization is beneficial is actually quite a difficult problem, but such optimisation would be valid.
add a comment |
Yes. The memoized version of a pure function is also a pure function.
All that function purity cares about is the effect that input parameters on the return value of the function (passing the same input should always produce the same output) and any side effects relevant to global states (e.g. text to the terminal or UI or network). Computation time and extra memory usages is irrelevant to function purity.
Caches of a pure function is pretty much invisible to the program, a functional programming language is allowed to automatically optimise a pure function to a memoized version of the function if it can determine that it'll be beneficial to do so. In practice, automatically determining when memoization is beneficial is actually quite a difficult problem, but such optimisation would be valid.
Yes. The memoized version of a pure function is also a pure function.
All that function purity cares about is the effect that input parameters on the return value of the function (passing the same input should always produce the same output) and any side effects relevant to global states (e.g. text to the terminal or UI or network). Computation time and extra memory usages is irrelevant to function purity.
Caches of a pure function is pretty much invisible to the program, a functional programming language is allowed to automatically optimise a pure function to a memoized version of the function if it can determine that it'll be beneficial to do so. In practice, automatically determining when memoization is beneficial is actually quite a difficult problem, but such optimisation would be valid.
edited 1 hour ago
answered 8 hours ago
Lie RyanLie Ryan
7,4411 gold badge20 silver badges28 bronze badges
7,4411 gold badge20 silver badges28 bronze badges
add a comment |
add a comment |
Wikipedia defines a "Pure Function" as a function that has the following properties:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).
In effect, a pure function returns the same output given the same input, and doesn't affect anything else outside of the function. For purposes of purity, it doesn't matter how the function computes its return value, so long as it returns the same output given the same input.
Functionally pure languages like Haskell routinely use memoization to speed up a function by caching its previously computed results.
add a comment |
Wikipedia defines a "Pure Function" as a function that has the following properties:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).
In effect, a pure function returns the same output given the same input, and doesn't affect anything else outside of the function. For purposes of purity, it doesn't matter how the function computes its return value, so long as it returns the same output given the same input.
Functionally pure languages like Haskell routinely use memoization to speed up a function by caching its previously computed results.
add a comment |
Wikipedia defines a "Pure Function" as a function that has the following properties:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).
In effect, a pure function returns the same output given the same input, and doesn't affect anything else outside of the function. For purposes of purity, it doesn't matter how the function computes its return value, so long as it returns the same output given the same input.
Functionally pure languages like Haskell routinely use memoization to speed up a function by caching its previously computed results.
Wikipedia defines a "Pure Function" as a function that has the following properties:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).
In effect, a pure function returns the same output given the same input, and doesn't affect anything else outside of the function. For purposes of purity, it doesn't matter how the function computes its return value, so long as it returns the same output given the same input.
Functionally pure languages like Haskell routinely use memoization to speed up a function by caching its previously computed results.
answered 8 hours ago
Robert Harvey♦Robert Harvey
172k47 gold badges403 silver badges611 bronze badges
172k47 gold badges403 silver badges611 bronze badges
add a comment |
add a comment |
It depends on how you do it.
Usually people want to memoize by mutating some sort of cache dictionary. This has all the problems associated with impure mutation, such as having to worry about concurrency, worrying about the cache growing too large, etc.
However, you can memoize without impure memory mutation. One example is in this answer, where I track the memoized values externally by means of a lengths argument.
In the link Robert Harvey provided, lazy evaluation is used to avoid side effects.
Another technique sometimes seen is to explicitly mark the memoization as an impure side effect in the context of an IO type, such as with cats-effect's memoize function.
This last one brings up the point that sometimes the goal is just encapsulating mutation rather than eliminating it. Most functional programmers consider it "pure enough" to make impurity explicit and encapsulated.
If you want a term to differentiate it from a truly pure function, I think it's sufficient to just say "memoized with a mutable dictionary." That lets people know how to use it safely.
I don't think any of the purer solution solves the above problems: While you lose any concurrency worries, you also lose any chance for two concurrently started calls likecollatz(100)andcollatz(200)to cooperate. And IIUIC, the problem with cache growing too large remains (though Haskell may have some nice tricks for this?).
– maaartinus
33 mins ago
add a comment |
It depends on how you do it.
Usually people want to memoize by mutating some sort of cache dictionary. This has all the problems associated with impure mutation, such as having to worry about concurrency, worrying about the cache growing too large, etc.
However, you can memoize without impure memory mutation. One example is in this answer, where I track the memoized values externally by means of a lengths argument.
In the link Robert Harvey provided, lazy evaluation is used to avoid side effects.
Another technique sometimes seen is to explicitly mark the memoization as an impure side effect in the context of an IO type, such as with cats-effect's memoize function.
This last one brings up the point that sometimes the goal is just encapsulating mutation rather than eliminating it. Most functional programmers consider it "pure enough" to make impurity explicit and encapsulated.
If you want a term to differentiate it from a truly pure function, I think it's sufficient to just say "memoized with a mutable dictionary." That lets people know how to use it safely.
I don't think any of the purer solution solves the above problems: While you lose any concurrency worries, you also lose any chance for two concurrently started calls likecollatz(100)andcollatz(200)to cooperate. And IIUIC, the problem with cache growing too large remains (though Haskell may have some nice tricks for this?).
– maaartinus
33 mins ago
add a comment |
It depends on how you do it.
Usually people want to memoize by mutating some sort of cache dictionary. This has all the problems associated with impure mutation, such as having to worry about concurrency, worrying about the cache growing too large, etc.
However, you can memoize without impure memory mutation. One example is in this answer, where I track the memoized values externally by means of a lengths argument.
In the link Robert Harvey provided, lazy evaluation is used to avoid side effects.
Another technique sometimes seen is to explicitly mark the memoization as an impure side effect in the context of an IO type, such as with cats-effect's memoize function.
This last one brings up the point that sometimes the goal is just encapsulating mutation rather than eliminating it. Most functional programmers consider it "pure enough" to make impurity explicit and encapsulated.
If you want a term to differentiate it from a truly pure function, I think it's sufficient to just say "memoized with a mutable dictionary." That lets people know how to use it safely.
It depends on how you do it.
Usually people want to memoize by mutating some sort of cache dictionary. This has all the problems associated with impure mutation, such as having to worry about concurrency, worrying about the cache growing too large, etc.
However, you can memoize without impure memory mutation. One example is in this answer, where I track the memoized values externally by means of a lengths argument.
In the link Robert Harvey provided, lazy evaluation is used to avoid side effects.
Another technique sometimes seen is to explicitly mark the memoization as an impure side effect in the context of an IO type, such as with cats-effect's memoize function.
This last one brings up the point that sometimes the goal is just encapsulating mutation rather than eliminating it. Most functional programmers consider it "pure enough" to make impurity explicit and encapsulated.
If you want a term to differentiate it from a truly pure function, I think it's sufficient to just say "memoized with a mutable dictionary." That lets people know how to use it safely.
answered 6 hours ago
Karl BielefeldtKarl Bielefeldt
124k34 gold badges228 silver badges425 bronze badges
124k34 gold badges228 silver badges425 bronze badges
I don't think any of the purer solution solves the above problems: While you lose any concurrency worries, you also lose any chance for two concurrently started calls likecollatz(100)andcollatz(200)to cooperate. And IIUIC, the problem with cache growing too large remains (though Haskell may have some nice tricks for this?).
– maaartinus
33 mins ago
add a comment |
I don't think any of the purer solution solves the above problems: While you lose any concurrency worries, you also lose any chance for two concurrently started calls likecollatz(100)andcollatz(200)to cooperate. And IIUIC, the problem with cache growing too large remains (though Haskell may have some nice tricks for this?).
– maaartinus
33 mins ago
I don't think any of the purer solution solves the above problems: While you lose any concurrency worries, you also lose any chance for two concurrently started calls like
collatz(100) and collatz(200) to cooperate. And IIUIC, the problem with cache growing too large remains (though Haskell may have some nice tricks for this?).– maaartinus
33 mins ago
I don't think any of the purer solution solves the above problems: While you lose any concurrency worries, you also lose any chance for two concurrently started calls like
collatz(100) and collatz(200) to cooperate. And IIUIC, the problem with cache growing too large remains (though Haskell may have some nice tricks for this?).– maaartinus
33 mins ago
add a comment |
Thanks for contributing an answer to Software Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f396501%2fis-a-memoized-pure-function-itself-considered-pure%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
Maybe it is not pure for purists, but "pure enough" for pragmatic people ;-)
– Doc Brown
10 hours ago
@DocBrown I agree, just wondering if there’s a more formal term for ‘pure enough’
– callum
10 hours ago
Executing a pure function will most likely modify the processor's instruction cache, branch predictors etc. But that's probably "pure enough" for purists as well - or you can forget about pure functions altogether.
– gnasher729
8 hours ago
@callum No, there is no formal definition of "pure enough". When arguing about purity and the semantic equivalence of two "referentially transparent" calls, you always have to state exactly which semantics you are going to apply. At some low level of implementation detail it will always break down and have different memory effects or timings. That's why you have to be pragmatic: what level of detail is useful for reasoning about your code?
– Bergi
52 mins ago