Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Pure functions #520

Closed
raroni opened this issue Oct 2, 2017 · 4 comments
Closed

Proposal: Pure functions #520

raroni opened this issue Oct 2, 2017 · 4 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@raroni
Copy link

raroni commented Oct 2, 2017

This is an invitation to discussion as much as it is a proposal. While function purity known from traditional functional languages probably does not belong in Zig, I believe a weaker kind of purity is worth considering. Reasoning about a program's potential states is often overwhelming or impossible. With pure functions, we can make it much easier for the programmer to reason about the state space, and as a nice side-benefit, a new class of compiler optimizations become feasible (as far as I can see anyway).

More concretely, when I write C/C++ I often miss the ability to limit a function to only access passed arguments. Example (note pure qualifier before fn):

pure fn myFunc(a: int, b: &int) -> int {
  // compiler error: pure functions cannot access vars defined outside its scope
  myGlobalVar = 23; 

  // compiler error: pure functions cannot call impure functions
  myImpureFunc();

  // OK:
  *b = 123;
  return a + 2;
}

Note that this particular formulation of purity allows changing referenced values (in contrast to functional languages).

Function purity in non-functional languages, was eloquently addressed some years back by John Carmack:
https://www.gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php

The language D has some form of this purity. Personally, I like their notion of function purity though I admittedly do not have experience using it in practice. For reference and inspiration, here's a nice article about its design:
http://klickverbot.at/blog/2012/05/purity-in-d/

Advantages of pure functions:

  • Defines a clear and simple contract between caller and callee.
  • Makes it easier/faster for programmers to reason about a piece of code (less potential side effects to think about).
  • Enables optimizations that are not feasible otherwise: e.g. g(x)+g(x) could safely be replaced by 2*g(x) if g is pure and x is not a pointer.
  • Calls to pure functions where arguments can be resolved statically can be evaluated at compile time.
  • Fits well with Zig's philosophy of optimality and clarity (I guess this last one is subjective).

I do not have much experience with language design and/or compiler authoring, so I am sorry if I am overlooking some obvious reason why this would be a bad idea. Anyway, I would love to hear your thoughts on this. Thanks.

@raroni raroni changed the title Pure functions Proposal: Pure functions Oct 2, 2017
@PavelVozenilek
Copy link

In practice it would be handy if calling "no side effects" function is visually distinct from an ordinary function call. E.g. by different highlighting in IDE, or like this:

var x = foo(); /// ordinary function
var y = bar(()); /// pure function

@thejoshwolfe
Copy link
Sponsor Contributor

See also #425.

@andrewrk andrewrk added this to the 0.2.0 milestone Oct 2, 2017
@PavelVozenilek
Copy link

PavelVozenilek commented Oct 3, 2017

If a function uses comptime decision it may be both pure and impure. Bad design but it may happen.

C++ has similar problem, a template may throw or not, depending on a type. They added nothrow(bool-expression-here) to decide, turning bad thing into even worse.

@andrewrk andrewrk modified the milestones: 0.2.0, 0.3.0 Oct 19, 2017
@andrewrk andrewrk modified the milestones: 0.3.0, 0.4.0 Feb 28, 2018
@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Feb 5, 2019
@andrewrk andrewrk modified the milestones: 0.4.0, 0.5.0 Feb 5, 2019
@hmusgrave
Copy link

Is it worth reconsidering something like this proposal (perhaps as a calling convention -- noclosure or noglobals, and then raising a compileError if we do something we can't prove like calling an opaque function pointer?) to reap some benefits that are in line with Zig's philosophy? Right now by community convention we can be pretty sure nobody allocates without us knowing about it, but this proposal would afford the caller similar guarantees regarding:

  1. Stderr/Stdout
  2. Network requests
  3. Register bit-banging
  4. GUI redraws
  5. Accessing some global lock
  6. Anything else we might dream up in the future -- important because library authors and users will inevitably disagree about which operations are safe to not expose in the call signature, and this empowers users to easily detect such breaking changes if/when they care.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

5 participants