[Issue 8185] Pure functions and pointers

d-bugmail at puremagic.com d-bugmail at puremagic.com
Mon Jun 4 00:52:49 PDT 2012


http://d.puremagic.com/issues/show_bug.cgi?id=8185



--- Comment #20 from Denis Shelomovskij <verylonglogin.reg at gmail.com> 2012-06-04 11:54:40 MSD ---
(In reply to comment #19)
> I honestly don't understand why much in the way of examples are needed.

OK. I have written some examples. Are they too obvious to not be in docs?
Honestly, I'll be amazed if most of D programmers have thought about most of
that cases.

Examples:

pure functions (not sure if @system only or @safe too) in D are guaranteed to
be pure only if used according to it's documentation. There is no guarantees in
other case.
---
/// b argument have to be true or result will depend on global state
size_t f(size_t i, bool b) pure; // strongly pure

void main()
{
    size_t i1 = f(1, false); // can depend on global state
    size_t i2 = f(1, false); // f is free to produce different result here
    // And if second f call is optimized out using i2 = i1,
    // (because f is strongly pure) a program will behave
    // differently in release mode so be careful.
}
---

For @system pure functions, it's your responsibility to pass correct arguments
to functions. These functions (even strongly pure) can be impure for
"incorrect" arguments and even results in "undefined behavior".
---
extern (C) size_t strlen(in char* s) nothrow pure; // strongly pure

/// cstr must be zero-ended
size_t myStrlen(in char[] cstr) pure // strongly pure
{
    return strlen(cstr.ptr);
}

void main()
{
    char[3] str = "abc";
    // str isn't zero-ended so myStrlen call
    // results in undefined behavior.
    size_t l1 = myStrlen(str);
    size_t l2 = myStrlen(str); // can give different result
}
---

@system strongly pure functions often can't be optimized out:
---
extern (C) size_t strlen(in char* s) nothrow pure; // strongly pure

void f(in char* cstr, int* n) pure
{
    // strlen have to be executed every iteration,
    // because compiler doesn't know if n is
    // connected with cstr someway
    for(size_t i = 0; i < strlen(cstr); ++i)
    {
        *n += cstr[i];
    }
}
---

Same apply even if these functions hasn't pointers/arrays in it's signature:
---
size_t f(size_t) nothrow pure; // strongly pure

void g(size_t i1, ref size_t i2) pure
{
    // f have to be executed every iteration,
    // because compiler doesn't know if i1 is
    // connected with i2 someway (f can expect
    // that it's argument is an address of i2)
    for(size_t i = 0; i < f(i1); ++i)
    {
        i2 *= 3;
    }
}
---

One has to carefully watch if a function is strongly pure by it's signature
(the compiler is guaranteed to determine function purity type by it's signature
only to prevent different behavior between cases with/without a signature):
---
void f(size_t x) pure // strongly pure, can't have side effects
{
    *cast(int*) x = 5; // undefined behavior
}


__gshared int tmp;
void g(size_t x, ref int dummy = tmp) pure // weakly pure, can have side
effects
{
    *cast(int*) x = 5; // correct
}
---

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list