[Issue 23589] [REG2.095] Purity check special case gives circular reference error.
https://issues.dlang.org/show_bug.cgi?id=23589 --- Comment #3 from Dlang Bot --- dlang/dmd pull request #14765 "merge stable" was merged into master: - 4b5a7826a74616e017698da79cb216a52b85775b by Iain Buclaw: fix Issue 23589 - [REG2.095] Purity check special case gives circular reference error https://github.com/dlang/dmd/pull/14765 --
[Issue 23589] [REG2.095] Purity check special case gives circular reference error.
https://issues.dlang.org/show_bug.cgi?id=23589 Dlang Bot changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --- Comment #2 from Dlang Bot --- dlang/dmd pull request #14750 "fix Issue 23589 - [REG2.095] Purity check special case gives circular reference error" was merged into stable: - df4670e4506c5f83bd35d9f330c420bec9baf163 by Iain Buclaw: fix Issue 23589 - [REG2.095] Purity check special case gives circular reference error https://github.com/dlang/dmd/pull/14750 --
[Issue 23589] [REG2.095] Purity check special case gives circular reference error.
https://issues.dlang.org/show_bug.cgi?id=23589 Dlang Bot changed: What|Removed |Added Keywords||pull --- Comment #1 from Dlang Bot --- @ibuclaw created dlang/dmd pull request #14750 "fix Issue 23589 - [REG2.095] Purity check special case gives circular reference error" fixing this issue: - fix Issue 23589 - [REG2.095] Purity check special case gives circular reference error https://github.com/dlang/dmd/pull/14750 --
[Issue 23589] [REG2.095] Purity check special case gives circular reference error.
https://issues.dlang.org/show_bug.cgi?id=23589 johanenge...@weka.io changed: What|Removed |Added Keywords||industry, rejects-valid --
[Issue 23589] New: [REG2.095] Purity check special case gives circular reference error.
https://issues.dlang.org/show_bug.cgi?id=23589 Issue ID: 23589 Summary: [REG2.095] Purity check special case gives circular reference error. Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: regression Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: johanenge...@weka.io The testcase below compiles with 2.094, but fails compilation with 2.095. The regression is introduced by this PR: https://github.com/dlang/dmd/pull/12023 (introduces size check for the special case of zero-sized struct). Removing the size check (`sd.determineSize(v.loc);`) "fixes" the regression. Testcase: ``` struct TemplStr(string Description_) {} template A() { bool member; alias THIS = typeof(this); static THIS staticInstance; static asSize() { return staticInstance.member; } } template B() { enum cols = columns(); enum cols_two = cols; TemplStr!(cols_two) tstr; } struct S { mixin A; mixin B; static string columns() { auto dummy = return "as"; } } ``` --
[Issue 12191] bad purity propagation for double-nested delegate templates
https://issues.dlang.org/show_bug.cgi?id=12191 Iain Buclaw changed: What|Removed |Added Priority|P2 |P3 --
[Issue 18590] nothrow constructor call still type-checks destructor for purity
https://issues.dlang.org/show_bug.cgi?id=18590 Iain Buclaw changed: What|Removed |Added Priority|P2 |P3 --
[Issue 7314] strong purity should be inferred at call site
https://issues.dlang.org/show_bug.cgi?id=7314 Iain Buclaw changed: What|Removed |Added Priority|P2 |P4 --
[Issue 17442] regex purity issues
https://issues.dlang.org/show_bug.cgi?id=17442 Iain Buclaw changed: What|Removed |Added Priority|P1 |P3 --
[Issue 12819] Refused purity conversion of immutable array of arrays
https://issues.dlang.org/show_bug.cgi?id=12819 Iain Buclaw changed: What|Removed |Added Priority|P1 |P4 --
[Issue 21202] [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors
https://issues.dlang.org/show_bug.cgi?id=21202 Issue 21202 depends on issue 21850, which changed state. Issue 21850 Summary: [REG2.093] Template inference of pure not working https://issues.dlang.org/show_bug.cgi?id=21850 What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --
[Issue 21202] [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors
https://issues.dlang.org/show_bug.cgi?id=21202 johanenge...@weka.io changed: What|Removed |Added Status|RESOLVED|CLOSED --
[Issue 21202] [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors
https://issues.dlang.org/show_bug.cgi?id=21202 RazvanN changed: What|Removed |Added Status|NEW |RESOLVED CC||razvan.nitu1...@gmail.com Resolution|--- |DUPLICATE --- Comment #2 from RazvanN --- *** This issue has been marked as a duplicate of issue 21850 *** --
[Issue 21202] [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors
https://issues.dlang.org/show_bug.cgi?id=21202 Johan Engelen changed: What|Removed |Added Depends on||21850 Referenced Issues: https://issues.dlang.org/show_bug.cgi?id=21850 [Issue 21850] [REG2.093] Template inference of pure not working --
[Issue 7314] strong purity should be inferred at call site
https://issues.dlang.org/show_bug.cgi?id=7314 timon.g...@gmx.ch changed: What|Removed |Added Status|RESOLVED|REOPENED Resolution|INVALID |--- --- Comment #3 from timon.g...@gmx.ch --- ??? --
[Issue 7314] strong purity should be inferred at call site
https://issues.dlang.org/show_bug.cgi?id=7314 mhh changed: What|Removed |Added Status|NEW |RESOLVED CC||maxha...@gmail.com Resolution|--- |INVALID --- Comment #2 from mhh --- spec problem + this behaviour would make it inconsistent with regular assignments --
[Issue 21202] [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors
https://issues.dlang.org/show_bug.cgi?id=21202 Dlang Bot changed: What|Removed |Added Keywords||pull --- Comment #1 from Dlang Bot --- @JohanEngelen updated dlang/phobos pull request #7670 "Help compiler deduce `pure` for moveEmplaceImpl" fixing this issue: - whitespace fix Fixes issue 21202 https://github.com/dlang/phobos/pull/7670 --
[Issue 21202] [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors
https://issues.dlang.org/show_bug.cgi?id=21202 johanenge...@weka.io changed: What|Removed |Added Keywords||industry --
[Issue 21202] New: [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors
https://issues.dlang.org/show_bug.cgi?id=21202 Issue ID: 21202 Summary: [REG2.093] std.algorithm.mutation.moveEmplace cannot deduce purity and errors Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: regression Priority: P1 Component: phobos Assignee: nob...@puremagic.com Reporter: johanenge...@weka.io This code no longer works since dlang 2.093: ``` struct Strukt2 { this(int* _block) { } } struct Strukt { int* block; Strukt2 foo() { return Strukt2(null); } alias foo this; } void johan() { Strukt a; Strukt b; import std.algorithm.mutation: moveEmplace; moveEmplace(a, b); } ``` Error: `pure` function `std.algorithm.mutation.moveEmplace!(Strukt).moveEmplace` cannot call impure function `std.algorithm.mutation.moveEmplaceImpl!(Strukt).moveEmplaceImpl` Can be fixed by annotating `moveEmplaceImpl` with `pure`. --
[Issue 20815] Wrong purity inference for postblit and copy constructor in template struct
https://issues.dlang.org/show_bug.cgi?id=20815 Atila Neves changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |INVALID --
[Issue 20815] New: Wrong purity inference for postblit and copy constructor in template struct
https://issues.dlang.org/show_bug.cgi?id=20815 Issue ID: 20815 Summary: Wrong purity inference for postblit and copy constructor in template struct Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: atila.ne...@gmail.com The code below shouldn't compile, but does. The postblit function is obviously not pure, but pure code is allowed to call it. Interestingly, marking the postblit as pure explicitly causes it to no longer compile. struct Struct(T) { this(this) { import std.stdio; writeln("oops"); } } void fun(Struct!int s) pure; void gun() pure { fun(Struct!int()); } --
[Issue 7456] Purity strength not documented
https://issues.dlang.org/show_bug.cgi?id=7456 berni44 changed: What|Removed |Added Status|NEW |RESOLVED CC||bugzi...@d-ecke.de Resolution|--- |WORKSFORME --- Comment #5 from berni44 --- Seems to be documented meanwhile: https://dlang.org/spec/function.html#pure-functions --
[Issue 20047] call of static nested function ignores purity
https://issues.dlang.org/show_bug.cgi?id=20047 Dlang Bot changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --- Comment #3 from Dlang Bot --- dlang/dmd pull request #10172 "fix handling of static impure functions nested in pure functions (issues 20047 and 20050)" was merged into master: - ccc7ed3d98f254b3326f0a7d06ebcb33f9038a1d by aG0aep6G: fix issue 20047 - call of static nested function ignores purity https://github.com/dlang/dmd/pull/10172 --
[Issue 20047] call of static nested function ignores purity
https://issues.dlang.org/show_bug.cgi?id=20047 Dlang Bot changed: What|Removed |Added Keywords||pull --- Comment #2 from Dlang Bot --- @aG0aep6G created dlang/dmd pull request #10172 "fix handling of static impure functions nested in pure functions (issues 20047 and 20050)" fixing this issue: - fix issue 20047 - call of static nested function ignores purity https://github.com/dlang/dmd/pull/10172 --
[Issue 20047] call of static nested function ignores purity
https://issues.dlang.org/show_bug.cgi?id=20047 --- Comment #1 from Mike Franklin --- This behavior was introduced in https://github.com/dlang/dmd/pull/4344 as a fix to Issue 14039 --
[Issue 20047] call of static nested function ignores purity
https://issues.dlang.org/show_bug.cgi?id=20047 Mike Franklin changed: What|Removed |Added CC||slavo5...@yahoo.com See Also||https://issues.dlang.org/sh ||ow_bug.cgi?id=14039 --
[Issue 20047] New: call of static nested function ignores purity
https://issues.dlang.org/show_bug.cgi?id=20047 Issue ID: 20047 Summary: call of static nested function ignores purity Product: D Version: D2 Hardware: All OS: All Status: NEW Keywords: accepts-invalid, safe Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: ag0ae...@gmail.com Came up here: https://github.com/dlang/druntime/pull/2673 This compiles but shouldn't: int* m; int* impure_function() { return m; } int* pure_function() pure { static int* bug() { return impure_function(); } return bug(); /* Shouldn't compile. `bug` isn't pure. */ } void main() { m = new int(42); immutable int* i = pure_function(); assert(*i == 42); /* passes */ *m = 13; assert(*i == 42); /* fails; immutable value has changed */ } Also affects @safe functions. --
Re: Purity of delegate-style toString
On Tuesday, 1 May 2018 at 12:03:15 UTC, ag0aep6g wrote: On 05/01/2018 01:44 PM, Per Nordlöw wrote: In which cases (if any) is it possible to make a delegate-style implementation of toString such as void toString(scope void delegate(const(char)[]) sink) const @trusted pure { // sink("..."); // sink.formattedWrite!"..."(...); } pure? You have to mark `sink` as pure, too: void toString(scope void delegate (const(char)[]) pure sink) const @trusted pure Then the toString method itself works, but it may not be callable by other code that wants to use an impure sink. For example, `format` works, but `writeln` doesn't: struct S { void toString(scope void delegate(const(char)[]) pure sink) const @trusted pure { import std.format: formattedWrite; sink("..."); sink.formattedWrite!"%s"(" ..."); } } void main() { import std.format: format; import std.stdio: writeln; writeln(format("%s", S())); /* Ok. Prints "... ...". */ writeln(S()); /* Nope. writeln would like to use an impure sink. */ } By the way, you shouldn't mark toString as @trusted when `sink` is @system. I had similar issue for opApply. The generalized problem is, the attributes (pure, nothrow, @safe, @nogc) are too strong on functionals (i.e. functions taking function/delegate arguments). We could (and IMO should) weaken the attributes to mean: the same as always, *assuming all function/delegate arguments have it*. Concrete example, say your `toString(scope void delegate(const(char)[]))` is conceptually pure, i.e. if `sink` is a pure function (by static typing), `toString(sink)` acts pure, and for impure `sink`, `toString(sink)` possibly impure. So purity of the functional `toString` depends on the purity of its arguments; that is very natural as most functionals call their parameters. The current state makes attributes virtually useless for functionals. Often, toString can be templetized without drawback (except virtual functions), but opApply cannot. opApply must not be a template to enable type deduction for the variable.[1] Making attributes act structurally has almost no consequences in terms of breakage; just more functions can be pure/nothrow/@nogc/@safe. It would make functionals impure/unsafe/.. that do not call their argument. The question is, in which contexts are they used and is it an issue -- is it a greater issue than this. Complete example what the change would do: Say you have void toString(scope void delegate(const(char)[]) sink) pure { sink("Example"); } toString is a pure functional, so calling it is pure iff the argument itself is. The compiler statically knows if the argument is pure and can infer the purity of the expression. [1] https://dlang.org/spec/statement.html#foreach_over_struct_and_classes (We could define very general special cases where type deduction can be archived, e.g. opApply(DG : int delegate(Args))(DG).)
[Issue 8063] Purity of assert's second parameter
https://issues.dlang.org/show_bug.cgi?id=8063 Oliver Rümpeleinchanged: What|Removed |Added Status|NEW |RESOLVED CC||ol...@fg4f.de Resolution|--- |FIXED --- Comment #2 from Oliver Rümpelein --- The output starting from 2.0.64 includes only the "Bad type size: 8"-message. Resolving. --
Re: Purity of delegate-style toString
On Tuesday, 1 May 2018 at 12:03:15 UTC, ag0aep6g wrote: By the way, you shouldn't mark toString as @trusted when `sink` is @system. Thanks
Re: Purity of delegate-style toString
On 05/01/2018 01:44 PM, Per Nordlöw wrote: In which cases (if any) is it possible to make a delegate-style implementation of toString such as void toString(scope void delegate(const(char)[]) sink) const @trusted pure { // sink("..."); // sink.formattedWrite!"..."(...); } pure? You have to mark `sink` as pure, too: void toString(scope void delegate (const(char)[]) pure sink) const @trusted pure Then the toString method itself works, but it may not be callable by other code that wants to use an impure sink. For example, `format` works, but `writeln` doesn't: struct S { void toString(scope void delegate(const(char)[]) pure sink) const @trusted pure { import std.format: formattedWrite; sink("..."); sink.formattedWrite!"%s"(" ..."); } } void main() { import std.format: format; import std.stdio: writeln; writeln(format("%s", S())); /* Ok. Prints "... ...". */ writeln(S()); /* Nope. writeln would like to use an impure sink. */ } By the way, you shouldn't mark toString as @trusted when `sink` is @system.
Purity of delegate-style toString
In which cases (if any) is it possible to make a delegate-style implementation of toString such as void toString(scope void delegate(const(char)[]) sink) const @trusted pure { // sink("..."); // sink.formattedWrite!"..."(...); } pure?
[Issue 18590] New: nothrow constructor call still type-checks destructor for purity
https://issues.dlang.org/show_bug.cgi?id=18590 Issue ID: 18590 Summary: nothrow constructor call still type-checks destructor for purity Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P2 Component: dmd Assignee: nob...@puremagic.com Reporter: c...@dawg.eu cat > bug.d << CODE extern(C) int printf(const char*, ...); struct F { static F create() pure nothrow { return F(1); } this(int) pure nothrow { } ~this() { printf("~this\n"); } } CODE dmd -c bug Error: pure function 'bug.F.create' cannot call impure function 'bug.F.~this' Apparently happens because `F(1)` is lowered to `(tmp = F(1)),tmp` internally. https://github.com/dlang/dmd/blob/93804714c4091a8d867c09ca7b5bf332acb34dfb/src/dmd/expression.d#L3931 --
[Issue 17442] regex purity issues
https://issues.dlang.org/show_bug.cgi?id=17442 Dmitry Olshanskychanged: What|Removed |Added Assignee|nob...@puremagic.com|dmitry.o...@gmail.com --
[Issue 7707] Purity inference fails when template used before it's defined
https://issues.dlang.org/show_bug.cgi?id=7707 Vladimir Panteleevchanged: What|Removed |Added Status|NEW |RESOLVED CC||dlang-bugzilla@thecybershad ||ow.net Resolution|--- |INVALID --- Comment #1 from Vladimir Panteleev --- This needs a self-contained test case. Please reopen if you consider this issue still valid and can provide a self-contained test case. --
Re: purity question
On Tue, May 30, 2017 at 11:10:19AM -0700, Jonathan M Davis via Digitalmars-d-learn wrote: [...] > Yeah, basically, D's pure was originally what is now sometimes called > "strongly pure," which is quite close to functionally pure in that the > same input results in the same output (it still allows alocating > memory and returning it though, so you can have equal but different > objects if the same function is called multiple times with the same > arguments in different contexts where the compiler doesn't memoize > it). However, pure was so restrictive as to be borderline useless, > because it could only pass types that were immutable or implicitly > convertible to immutable. So, it was expanded to include any function > which could not access global, mutable state, because such functions > can be called from a "strongly" pure function without violating the > strongly pure function's guarantees - and thus "weakly" pure functions > were born, making it so that D's pure is really more like @noglobal > than functionally pure. It's a critical building block in functional > purity, and strongly pure functions still get all of the benefits that > they got before (and now they can actually be useful, because they can > call many more functions), but _most_ pure functions are weakly pure > and thus don't get the full benefits of functional purity - and that's > why some folks like Ketmar tend to get annoyed with D's pure. But the > way it is is actually quite useful even if it's initially confusing. > And even when there are no strongly pure functions in your program, > knowing that a function cannot access global variables except through > its arguments means a lot in and of itself. [...] In retrospect, we could have named "weakly pure" something like @noglobal, and "strongly pure" as pure. But be that as it may, I think D's pure system is actually extremely ingenious. Look at it this way: in the classical sense of functional purity, which is what you get in (pure) functional languages, it can get quite difficult to implement the functionality you want, because the language enforces that every primitive you use in your implementation must be pure. The reasoning is that if you're only allowed to use pure primitives, then the resulting function is guaranteed to be pure. It's nice and simple. However, it's also rather cumbersome, especially in the context of an imperative language like D. For example, in a functional language you cannot assign new values to variables, and you cannot write for-loops, because the loop index is not allowed to mutate. You cannot mutate anything, because mutation makes the code impure. So instead of straightforward loops, you need to resort to things like tail recursion; instead of mutation, you need to use monads, and so on. I'm not saying this is a bad thing, but it's just cumbersome because you, the programmer, cannot simply implement a function with a straightforward algorithm, but you have to work harder to express the algorithm in functional terms using recursion and other functional (pure) constructs. The first insight in D's purity system is the observation that, given some function f(), from the caller's POV all they care about is that (1) the function always returns the same value given the same arguments, and (2) there are no visible side-effects. Point (2) is where the insight lies: in a sense, it *doesn't matter* if f() does all kinds of impure stuff in order to compute its return value, as long as the outside world cannot see it. It may be internally impure, but externally, as far as the outside world is concerned, it's pure, because the caller can't tell the difference. So D allows things like variables, mutation, for-loops, and all kinds of stuff inside (strongly) pure functions -- as long as no global state is touched, and as long as the function arguments aren't modified (from the caller's POV), f() is pure. In other words, as long as f() keeps its dirty laundry to itself and leaves the outside world untouched, it is externally pure, even if it's internally impure. The next insight is this: suppose f() calls g(), and g() is impure. In the traditional functional language purity system, this is outright illegal, because a pure function, by definition, cannot call an impure function, otherwise it is itself impure. However, suppose g() does not modify any global state. It *may* modify stuff through its arguments -- which makes it impure. But if f() is not allowed to modify its arguments and has no global state, then at worst, it can only pass its internal, non-global state to g(). Therefore, it is impossible for g() to reach global state through its arguments. Thus, f()'s (external) purity is preserved. Note the fine distinction here, that g()'s external purity is keyed on being called from inside a strongly-pure function f(). If f
Re: purity question
On Tuesday, May 30, 2017 16:54:13 ag0aep6g via Digitalmars-d-learn wrote: > On 05/30/2017 11:12 AM, Rene Zwanenburg wrote: > > If malloc were marked as pure, wouldn't that mean it must return the > > same pointer every time you call it with the same size? > > D's `pure` mostly means: "does not access mutable state, and does not do > input/output". > > There is never a requirement that a function must return the same value > for the same input. But a compiler is allowed to memoize the result of a > `pure` function when it has no mutable indirections in its parameter and > return types. Such a function is "strongly pure". > > When there are mutable indirections, the function is "weakly pure". > Weakly pure functions are not assumed to be memoizable, but "weakly > pure" still has meaning: > > * Can call weakly pure functions from strongly pure ones. > > * When a weakly pure function has mutable indirections in the return > type but not in the parameters (like malloc), then it must be returning > freshly allocated memory. That means, the result cannot be referenced > from anywhere else. So it can be converted to const/immutable/shared > implicitly. The spec calls that a "pure factory function". > > Repeating Biotronic's links, the spec and David Nadlinger's article are > the go-to resources for D's take on purity: > > https://dlang.org/spec/function.html#pure-functions > http://klickverbot.at/blog/2012/05/purity-in-d/ Yeah, basically, D's pure was originally what is now sometimes called "strongly pure," which is quite close to functionally pure in that the same input results in the same output (it still allows alocating memory and returning it though, so you can have equal but different objects if the same function is called multiple times with the same arguments in different contexts where the compiler doesn't memoize it). However, pure was so restrictive as to be borderline useless, because it could only pass types that were immutable or implicitly convertible to immutable. So, it was expanded to include any function which could not access global, mutable state, because such functions can be called from a "strongly" pure function without violating the strongly pure function's guarantees - and thus "weakly" pure functions were born, making it so that D's pure is really more like @noglobal than functionally pure. It's a critical building block in functional purity, and strongly pure functions still get all of the benefits that they got before (and now they can actually be useful, because they can call many more functions), but _most_ pure functions are weakly pure and thus don't get the full benefits of functional purity - and that's why some folks like Ketmar tend to get annoyed with D's pure. But the way it is is actually quite useful even if it's initially confusing. And even when there are no strongly pure functions in your program, knowing that a function cannot access global variables except through its arguments means a lot in and of itself. - Jonathan M Davis
Re: purity question
On 05/30/2017 11:12 AM, Rene Zwanenburg wrote: If malloc were marked as pure, wouldn't that mean it must return the same pointer every time you call it with the same size? D's `pure` mostly means: "does not access mutable state, and does not do input/output". There is never a requirement that a function must return the same value for the same input. But a compiler is allowed to memoize the result of a `pure` function when it has no mutable indirections in its parameter and return types. Such a function is "strongly pure". When there are mutable indirections, the function is "weakly pure". Weakly pure functions are not assumed to be memoizable, but "weakly pure" still has meaning: * Can call weakly pure functions from strongly pure ones. * When a weakly pure function has mutable indirections in the return type but not in the parameters (like malloc), then it must be returning freshly allocated memory. That means, the result cannot be referenced from anywhere else. So it can be converted to const/immutable/shared implicitly. The spec calls that a "pure factory function". Repeating Biotronic's links, the spec and David Nadlinger's article are the go-to resources for D's take on purity: https://dlang.org/spec/function.html#pure-functions http://klickverbot.at/blog/2012/05/purity-in-d/
Re: purity question
On Tuesday, 30 May 2017 at 13:45:07 UTC, Rene Zwanenburg wrote: On Tuesday, 30 May 2017 at 11:34:52 UTC, ketmar wrote: If malloc were marked as pure, wouldn't that mean it must return the same pointer every time you call it with the same size? of course. but D "pure" is not what other world knows as "pure". we love to mess with words. Well, there's the ability to modify non-const reference parameters from a pure function, but that's not applicable to malloc. Are there any other special rules? The rules[0] are: 0) Can't call functions not marked pure. 1) Can't touch anything mutable that's not explicitly passed to the pure function. 1b) Except GC internal state - i.e. memory can be allocated via the GC. 1c) And floating-point exception flags and modes. 2) Can't do I/O (can be seen as a special case of 1 and 0). There's a few more details, but that's the important stuff. For a good article on the subject, I recommend David Nadlinger's Purity in D: http://klickverbot.at/blog/2012/05/purity-in-d/ [0]: https://dlang.org/spec/function.html#pure-functions
Re: purity question
Rene Zwanenburg wrote: On Tuesday, 30 May 2017 at 11:34:52 UTC, ketmar wrote: If malloc were marked as pure, wouldn't that mean it must return the same pointer every time you call it with the same size? of course. but D "pure" is not what other world knows as "pure". we love to mess with words. Well, there's the ability to modify non-const reference parameters from a pure function, but that's not applicable to malloc. Are there any other special rules? "pure" methods can mutate object state.
Re: purity question
On Tuesday, 30 May 2017 at 11:34:52 UTC, ketmar wrote: If malloc were marked as pure, wouldn't that mean it must return the same pointer every time you call it with the same size? of course. but D "pure" is not what other world knows as "pure". we love to mess with words. Well, there's the ability to modify non-const reference parameters from a pure function, but that's not applicable to malloc. Are there any other special rules?
Re: purity question
Rene Zwanenburg wrote: On Monday, 29 May 2017 at 01:36:24 UTC, Jonathan M Davis wrote: A simple example: anything that has a malloc/free pair. Yeah, if you do it right, you should be fine, but you have to do it right, and it's very easy to miss some detail that makes it wrong to insist to the compiler that what you're doing is pure. If malloc were marked as pure, wouldn't that mean it must return the same pointer every time you call it with the same size? of course. but D "pure" is not what other world knows as "pure". we love to mess with words.
Re: purity question
On Monday, 29 May 2017 at 01:36:24 UTC, Jonathan M Davis wrote: A simple example: anything that has a malloc/free pair. Yeah, if you do it right, you should be fine, but you have to do it right, and it's very easy to miss some detail that makes it wrong to insist to the compiler that what you're doing is pure. If malloc were marked as pure, wouldn't that mean it must return the same pointer every time you call it with the same size?
Re: purity question
On Monday, 29 May 2017 at 08:49:07 UTC, ketmar wrote: Brad Roberts wrote: libraries that themselves aren't marked pure, there's a real need for escape hatches. A simple example: anything that has a malloc/free pair. they aren't pure. it is a sad misconception about purity, which D makes even more complex by allowing to mark, for example, *setters* as pure. but still, `malloc()` and `free()` aren't pure. and while various functions in std.math, for example, are marked `pure`, they aren't too. There is pureMalloc since 2.074.0 (it was never announced): https://github.com/dlang/druntime/pull/1746 However, without a pureFree it's rather limited in usefulness and needs to be workaround in real life: https://github.com/dlang/druntime/pull/1718
Re: purity question
On Monday, 29 May 2017 at 11:25:06 UTC, ketmar wrote: almost all of them, 'cause they depends on FPU rounding settings. Well, yeah. IIRC contemporary floating point machine language instructions allow embedding of rounding mode into the instruction. A pity languages are lagging behind, stuck in the 1980s... WebAssembly is locking it to the default IEEE754-2008 round-to-even. Which is reasonable as they aim for max portability, albeit a bit limiting.
Re: purity question
Ola Fosheim Grøstad wrote: On Monday, 29 May 2017 at 08:49:07 UTC, ketmar wrote: pure. and while various functions in std.math, for example, are marked `pure`, they aren't too. Out of curiosity, which functions in std.math aren't "pure" in the D sense? almost all of them, 'cause they depends on FPU rounding settings.
Re: purity question
On Monday, 29 May 2017 at 08:49:07 UTC, ketmar wrote: pure. and while various functions in std.math, for example, are marked `pure`, they aren't too. Out of curiosity, which functions in std.math aren't "pure" in the D sense?
Re: purity question
Brad Roberts wrote: libraries that themselves aren't marked pure, there's a real need for escape hatches. A simple example: anything that has a malloc/free pair. they aren't pure. it is a sad misconception about purity, which D makes even more complex by allowing to mark, for example, *setters* as pure. but still, `malloc()` and `free()` aren't pure. and while various functions in std.math, for example, are marked `pure`, they aren't too.
[Issue 17442] regex purity issues
https://issues.dlang.org/show_bug.cgi?id=17442 --- Comment #2 from Brad Roberts--- That's a tiny tip of a much larger iceberg. --
Re: purity question
On Sunday, 28 May 2017 at 23:49:16 UTC, Brad Roberts wrote: Is there a mechanism for declaring something pure when it's built from parts which individually aren't? string foo(string s) { // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc return s; } Ali has answered this two years ago: http://www.digitalmars.com/d/archives/digitalmars/D/learn/using_memset_withing_a_pure_function_74629.html#N74631 Copying for convenience: If you want to live dangerously, you can use assumePure, which is found in one of the unittest blocks of std.traits: import std.traits; auto assumePure(T)(T t) if (isFunctionPointer!T || isDelegate!T) { enum attrs = functionAttributes!T | FunctionAttribute.pure_; return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; } int i = 0; void foo() { ++i;// foo accesses mutable module-level data } void bar() pure { auto pureFoo = assumePure(); pureFoo();// <-- pure function is calling impure function } void main() { assert(i == 0); bar(); assert(i == 1);// mutation through a pure function } It also came up in other discussions (the keyword is `assumePure`), e.g. - http://forum.dlang.org/post/hpxxghbiomtitrmwe...@forum.dlang.org - http://forum.dlang.org/post/nfhqvffqtkfsxjewg...@forum.dlang.org
[Issue 17442] regex purity issues
https://issues.dlang.org/show_bug.cgi?id=17442 uplink.co...@googlemail.com changed: What|Removed |Added CC||uplink.co...@googlemail.com --- Comment #1 from uplink.co...@googlemail.com --- The reason for this is that regex calls malloc --
Re: purity question
On Sunday, May 28, 2017 18:46:22 Brad Roberts via Digitalmars-d-learn wrote: > Again, of course it's possible to do it wrong. Escape hatches are like > that. And of course things are being worked on and improved, I'm one of > the ones that's done a good bit of that at various points in time. I'm > really not seeking a lesson or lecture in why it's dangerous. Sorry, if I'm coming across like I'm lecturing you. I'm not trying to. I'm trying to be clear about the situation, and because this is on D.Learn, with something like this, I don't want to show how to get around the issue without clearly warning about the risks, because even if you know exactly what you're doing when casting to get around purity problems, many others reading this list will not. - Jonathan M Davis
Re: purity question
On 5/28/2017 6:46 PM, Brad Roberts via Digitalmars-d-learn wrote: Here's the bug that I'm digging into today, a clear example of an api that _should_ be pure, but based on the implementation is rather difficult for the compiler to infer. https://issues.dlang.org/show_bug.cgi?id=17442
Re: purity question
On 5/28/2017 6:36 PM, Jonathan M Davis via Digitalmars-d-learn wrote: On Sunday, May 28, 2017 17:53:25 Brad Roberts via Digitalmars-d-learn wrote: On 5/28/2017 5:34 PM, Jonathan M Davis via Digitalmars-d-learn wrote: On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: Is there a mechanism for declaring something pure when it's built from parts which individually aren't? string foo(string s) { // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc return s; } you can cast Ok, so there essentially isn't. I'm well aware of the risks of lying to the compiler, but it's also not sufficiently smart to unravel complex code. Combined with there being interesting parts of the standard libraries that themselves aren't marked pure, there's a real need for escape hatches. Well, the big thing is that there are a number of functions in Phobos that need to have someone go over them and fix them so that they are inferred to be pure when they should be. Some work has been done in that area, and the situation is certainly better than it once was, but not enough work has been done to make it so that we can at all reasonably that everything in Phobos that should be pure is and what isn't shouldn't be. A simple example: anything that has a malloc/free pair. Yeah, if you do it right, you should be fine, but you have to do it right, and it's very easy to miss some detail that makes it wrong to insist to the compiler that what you're doing is pure. So, arguably, having anything more user-friendly than a cast is pretty dangerous. Having folks slap something like @assume_pure on things (if there were such an attribute) could be pretty risky. We already have enough trouble with @trusted on that front. Ultimately, we want to be in a position where needing to get around pure is very rare, and in most cases, I'd just tell folks to give up on pure on that piece of code rather than trying to hack it into working. - Jonathan M Davis Again, of course it's possible to do it wrong. Escape hatches are like that. And of course things are being worked on and improved, I'm one of the ones that's done a good bit of that at various points in time. I'm really not seeking a lesson or lecture in why it's dangerous. Here's the bug that I'm digging into today, a clear example of an api that _should_ be pure, but based on the implementation is rather difficult for the compiler to infer.
Re: purity question
On Sunday, May 28, 2017 18:39:02 Brad Roberts via Digitalmars-d-learn wrote: > On 5/28/2017 6:27 PM, Jonathan M Davis via Digitalmars-d-learn wrote: > > There was a whole discussion or 3 is PRs about making malloc pure, and > > IIRC, it was done and then decided that it wasn't safe to do some for > > one reason or another (IIRC, it had to do with what would happen when > > calls were elided, because the caller was strongly pure, but I'm not > > sure). So, I'd be _very_ careful about deciding that it was safe to > > call malloc in pure code. I expect that it's just fine in some > > contexts, but it's easy enough to screw up and mark something as pure > > when it really shouldn't be because of some detail you missed that you > > should be _really_ careful about decided to cast to pure. > > That's one reason I explicitly referenced malloc/free pairs. It's a lot > easier to be sure that those together aren't violating purity. Agreed. But it's the intricacies like that which make having a clean backdoor for pure a bit dangerous, much as it would be nice when you actually need to do it and know what you're doing well enough to get it right. - Jonathan M Davis
Re: purity question
On 5/28/2017 6:27 PM, Jonathan M Davis via Digitalmars-d-learn wrote: On Monday, May 29, 2017 01:01:46 Stefan Koch via Digitalmars-d-learn wrote: On Monday, 29 May 2017 at 00:53:25 UTC, Brad Roberts wrote: On 5/28/2017 5:34 PM, Jonathan M Davis via Digitalmars-d-learn wrote: On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: Is there a mechanism for declaring something pure when it's built from parts which individually aren't? string foo(string s) { // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc return s; } you can cast Ok, so there essentially isn't. I'm well aware of the risks of lying to the compiler, but it's also not sufficiently smart to unravel complex code. Combined with there being interesting parts of the standard libraries that themselves aren't marked pure, there's a real need for escape hatches. A simple example: anything that has a malloc/free pair. There is void[] myPureMalloc(uint size) pure @trusted nothrow @nogc { alias pure_malloc_t = pure nothrow void* function(size_t size); return (cast(pure_malloc_t)malloc)(size)[0 .. size]; } There was a whole discussion or 3 is PRs about making malloc pure, and IIRC, it was done and then decided that it wasn't safe to do some for one reason or another (IIRC, it had to do with what would happen when calls were elided, because the caller was strongly pure, but I'm not sure). So, I'd be _very_ careful about deciding that it was safe to call malloc in pure code. I expect that it's just fine in some contexts, but it's easy enough to screw up and mark something as pure when it really shouldn't be because of some detail you missed that you should be _really_ careful about decided to cast to pure. - Jonathan M Davis That's one reason I explicitly referenced malloc/free pairs. It's a lot easier to be sure that those together aren't violating purity.
Re: purity question
On Sunday, May 28, 2017 17:53:25 Brad Roberts via Digitalmars-d-learn wrote: > On 5/28/2017 5:34 PM, Jonathan M Davis via Digitalmars-d-learn wrote: > > On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: > >> Is there a mechanism for declaring something pure when it's built from > >> parts which individually aren't? > >> > >> string foo(string s) > >> { > >> > >> // do something arbitrarily complex with s that doesn't touch > >> > >> globals or change global state except possibly state of the heap or gc > >> > >> return s; > >> > >> } > > > > you can cast > > Ok, so there essentially isn't. I'm well aware of the risks of lying to > the compiler, but it's also not sufficiently smart to unravel complex > code. Combined with there being interesting parts of the standard > libraries that themselves aren't marked pure, there's a real need for > escape hatches. Well, the big thing is that there are a number of functions in Phobos that need to have someone go over them and fix them so that they are inferred to be pure when they should be. Some work has been done in that area, and the situation is certainly better than it once was, but not enough work has been done to make it so that we can at all reasonably that everything in Phobos that should be pure is and what isn't shouldn't be. > A simple example: anything that has a malloc/free pair. Yeah, if you do it right, you should be fine, but you have to do it right, and it's very easy to miss some detail that makes it wrong to insist to the compiler that what you're doing is pure. So, arguably, having anything more user-friendly than a cast is pretty dangerous. Having folks slap something like @assume_pure on things (if there were such an attribute) could be pretty risky. We already have enough trouble with @trusted on that front. Ultimately, we want to be in a position where needing to get around pure is very rare, and in most cases, I'd just tell folks to give up on pure on that piece of code rather than trying to hack it into working. - Jonathan M Davis
Re: purity question
On Monday, May 29, 2017 01:01:46 Stefan Koch via Digitalmars-d-learn wrote: > On Monday, 29 May 2017 at 00:53:25 UTC, Brad Roberts wrote: > > On 5/28/2017 5:34 PM, Jonathan M Davis via Digitalmars-d-learn > > > > wrote: > >> On Sunday, May 28, 2017 16:49:16 Brad Roberts via > >> > >> Digitalmars-d-learn wrote: > >>> Is there a mechanism for declaring something pure when it's > >>> built from > >>> parts which individually aren't? > >>> > >>> string foo(string s) > >>> { > >>> > >>> // do something arbitrarily complex with s that doesn't > >>> > >>> touch > >>> globals or change global state except possibly state of the > >>> heap or gc > >>> > >>> return s; > >>> > >>> } > >> > >> you can cast > > > > Ok, so there essentially isn't. I'm well aware of the risks of > > lying to the compiler, but it's also not sufficiently smart to > > unravel complex code. Combined with there being interesting > > parts of the standard libraries that themselves aren't marked > > pure, there's a real need for escape hatches. A simple > > example: anything that has a malloc/free pair. > > There is > > void[] myPureMalloc(uint size) pure @trusted nothrow @nogc > { > alias pure_malloc_t = pure nothrow void* function(size_t size); > return (cast(pure_malloc_t)malloc)(size)[0 .. size]; > } There was a whole discussion or 3 is PRs about making malloc pure, and IIRC, it was done and then decided that it wasn't safe to do some for one reason or another (IIRC, it had to do with what would happen when calls were elided, because the caller was strongly pure, but I'm not sure). So, I'd be _very_ careful about deciding that it was safe to call malloc in pure code. I expect that it's just fine in some contexts, but it's easy enough to screw up and mark something as pure when it really shouldn't be because of some detail you missed that you should be _really_ careful about decided to cast to pure. - Jonathan M Davis
Re: purity question
On Monday, 29 May 2017 at 01:12:53 UTC, Era Scarecrow wrote: ... Hmm didn't notice the post had split. Otherwise i wouldn't have replied... That and thinking about the GC state (outside of allocating memory)...
Re: purity question
On Sunday, 28 May 2017 at 23:49:16 UTC, Brad Roberts wrote: // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc Sounds like the basic definition of pure to me; At least in regards to D. Memory allocation which is a system call, doesn't actually break purity. Then again if you were worried about not using the gc, there's the newer nogc property. [quote] TDPL pg. 165: 5.11.1 Pure functions In D, a function is considered pure if returning a result is it's only effect and the result depends only on the function's arguments. [/quote]
Re: purity question
On Monday, 29 May 2017 at 01:01:46 UTC, Stefan Koch wrote: There is void[] myPureMalloc(uint size) pure @trusted nothrow @nogc { import core.stdc.stdlib : malloc; alias pure_malloc_t = @nogc pure nothrow void* function(size_t size); return (cast(pure_malloc_t))(size)[0 .. size]; } This is the fixed version.
Re: purity question
On 5/28/2017 6:01 PM, Stefan Koch via Digitalmars-d-learn wrote: On Monday, 29 May 2017 at 00:53:25 UTC, Brad Roberts wrote: On 5/28/2017 5:34 PM, Jonathan M Davis via Digitalmars-d-learn wrote: On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: Is there a mechanism for declaring something pure when it's built from parts which individually aren't? string foo(string s) { // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc return s; } you can cast Ok, so there essentially isn't. I'm well aware of the risks of lying to the compiler, but it's also not sufficiently smart to unravel complex code. Combined with there being interesting parts of the standard libraries that themselves aren't marked pure, there's a real need for escape hatches. A simple example: anything that has a malloc/free pair. There is void[] myPureMalloc(uint size) pure @trusted nothrow @nogc { alias pure_malloc_t = pure nothrow void* function(size_t size); return (cast(pure_malloc_t)malloc)(size)[0 .. size]; } That's still a cast. It's a nice way to isolate the cast, but it's clearly still there. And as I said, that's just one simple example.
Re: purity question
On Monday, 29 May 2017 at 00:53:25 UTC, Brad Roberts wrote: On 5/28/2017 5:34 PM, Jonathan M Davis via Digitalmars-d-learn wrote: On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: Is there a mechanism for declaring something pure when it's built from parts which individually aren't? string foo(string s) { // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc return s; } you can cast Ok, so there essentially isn't. I'm well aware of the risks of lying to the compiler, but it's also not sufficiently smart to unravel complex code. Combined with there being interesting parts of the standard libraries that themselves aren't marked pure, there's a real need for escape hatches. A simple example: anything that has a malloc/free pair. There is void[] myPureMalloc(uint size) pure @trusted nothrow @nogc { alias pure_malloc_t = pure nothrow void* function(size_t size); return (cast(pure_malloc_t)malloc)(size)[0 .. size]; }
Re: purity question
On 5/28/2017 5:34 PM, Jonathan M Davis via Digitalmars-d-learn wrote: On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: Is there a mechanism for declaring something pure when it's built from parts which individually aren't? string foo(string s) { // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc return s; } you can cast Ok, so there essentially isn't. I'm well aware of the risks of lying to the compiler, but it's also not sufficiently smart to unravel complex code. Combined with there being interesting parts of the standard libraries that themselves aren't marked pure, there's a real need for escape hatches. A simple example: anything that has a malloc/free pair.
Re: purity question
On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: > Is there a mechanism for declaring something pure when it's built from > parts which individually aren't? > > string foo(string s) > { > // do something arbitrarily complex with s that doesn't touch > globals or change global state except possibly state of the heap or gc > return s; > } Either everything the function is doing is pure, or it can't be pure without cheating, and cheating is usually a bad idea. There is no @trusted equivalent for pure. Now, if you're absolutely sure that the function doesn't do anything that's actually going to run afoul of pure and what the compiler will assume about pure functions, but it's using stuff that wasn't properly marked as pure, or does something that can't be marked as pure for some reason but in this context would actually be fine, you can cast. For instance, std.datetime's LocalTime is a singleton which gets the timezone conversion from the system. Its operations can't be pure, but it can be constructed as pure, and because it's a singleton, it will return the same instance every time. Originally, a static constructor was used to initialize the singleton (which therefore worked great with pure), but because of circular dependency pain with static constructors, we had to get rid of the static constructors in std.datetime. The solution was to move the initialization into another function which was not pure, and then when we call it from theh singleton function, we cast it to pure: static immutable(LocalTime) opCall() @trusted pure nothrow { alias FuncType = @safe pure nothrow immutable(LocalTime) function(); return (cast(FuncType))(); } static immutable(LocalTime) singleton() @trusted { import core.stdc.time : tzset; import std.concurrency : initOnce; static instance = new immutable(LocalTime)(); static shared bool guard; initOnce!guard({tzset(); return true;}()); return instance; } Now, in the vast majority of cases, I would strongly advise against cheating in this manner, because you need to be absolutely sure that you're not actually violating pure (particularly what the compiler will assume about pure) by what you're doing, and usually what it comes down to is that something that your function is calling needs to be fixed so that it can be inferred as pure, or it simply needs to be marked as pure. Casting is a horrible hack that should only be used as a last resort and only when you're 100% sure that it's fine. However, you _can_ use casting as a backdoor if you really have to. - Jonathan M Davis
purity question
Is there a mechanism for declaring something pure when it's built from parts which individually aren't? string foo(string s) { // do something arbitrarily complex with s that doesn't touch globals or change global state except possibly state of the heap or gc return s; }
[Issue 17442] New: regex purity issues
https://issues.dlang.org/show_bug.cgi?id=17442 Issue ID: 17442 Summary: regex purity issues Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: phobos Assignee: nob...@puremagic.com Reporter: bra...@puremagic.com At least two of the functions in std.regex that ought to be usable in a pure context aren't. I suspect there's a broader issue with that subsystem, but haven't investigated. - module bugregex; string unifyNewLine(string str) pure { import std.regex; return std.regex.replace(str, regex(`\r\n|\r|\n`, "g"), "\n"); } - $ dmd -c -ofbugregex.o bugregex.d bugregex.d(7): Error: pure function 'bugregex.unifyNewLine' cannot call impure function 'std.regex.regex!string.regex' bugregex.d(7): Error: pure function 'bugregex.unifyNewLine' cannot call impure function 'std.regex.replace!(match, string, char, Regex!char).replace' --
[Issue 11047] UDA + getAttributes bypass purity/safety check
https://issues.dlang.org/show_bug.cgi?id=11047 --- Comment #4 from github-bugzi...@puremagic.com --- Commits pushed to stable at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/55bd78ded94a1f40ee80c4e42791f216e5d58c41 fix Issue 11047 - UDA + getAttributes bypass purity/safety check https://github.com/dlang/dmd/commit/d1c3b6a1eab3347d9b6eb832b99ee45f70bd3702 Merge pull request #5863 from WalterBright/fix11047 --
Re: thisExePath purity
On 9/20/16 3:42 PM, crimaniak wrote: On Tuesday, 20 September 2016 at 13:35:27 UTC, Steven Schveighoffer wrote: Note that if you don't import the module that contains the static ctor, it should be trimmed by the linker. Let's imagine linker can trim even imported module with static ctor, if we have something like: immutable string executablePath; @local shared static this() { import std.file : thisExePath; executablePath = thisExePath(); } and there is no references to executablePath. Here it would be useful, I think. Attribute @local (or @module? the name does not matter) mean this block used only to init other symbols in this module so it can be skipped if no references. But if this is all that is in the module, why import the module if you aren't going to use any of it? I would absolutely caution you from putting static this() inside any template. Unfortunately, due to the way D generates these static constructors, any module that uses staticMemoize, or *imports a module that uses it*, will be marked as having a static constructor, and will potentially create cycles. Please be more detail about cycles. Do you mean something like this? https://isocpp.org/wiki/faq/ctors#static-init-order Sort of, I mean this: https://dlang.org/spec/module.html#order_of_static_ctor In other words, because the template has a static ctor in it, just instantiating it in your unrelated module puts static ctor in your module. And then cycles can appear that you wouldn't expect to happen. -Steve
Re: thisExePath purity
On Tuesday, 20 September 2016 at 13:35:27 UTC, Steven Schveighoffer wrote: Yes, but if your code does instantiate it, it is called, even if you don't ever call the function that calls it. Yes, it's not ideal but better then just global variable and static block - it's called in any case, even if variable is not used at all. Ideal solution will be something like attribute for static block leading to make it optional, so module will not be included if no usage of other symbols found. But I don't know way how to make it so template is used. Note that if you don't import the module that contains the static ctor, it should be trimmed by the linker. Let's imagine linker can trim even imported module with static ctor, if we have something like: immutable string executablePath; @local shared static this() { import std.file : thisExePath; executablePath = thisExePath(); } and there is no references to executablePath. Here it would be useful, I think. Attribute @local (or @module? the name does not matter) mean this block used only to init other symbols in this module so it can be skipped if no references. I would absolutely caution you from putting static this() inside any template. Unfortunately, due to the way D generates these static constructors, any module that uses staticMemoize, or *imports a module that uses it*, will be marked as having a static constructor, and will potentially create cycles. Please be more detail about cycles. Do you mean something like this? https://isocpp.org/wiki/faq/ctors#static-init-order
Re: thisExePath purity
On Tuesday, 20 September 2016 at 09:14:39 UTC, Marc Schütz wrote: Have a look at `std.concurrency.initOnce`: https://dlang.org/phobos/std_concurrency.html#.initOnce But you will still need to use assumePure() for calling `thisExePath`, and it might do other things that are impure... Yes, it's near but in this case I try to fix purity, so any variants of lazy initialization is not applicable here.
Re: thisExePath purity
On Tuesday, 20 September 2016 at 04:26:05 UTC, Jonathan M Davis wrote: On Tuesday, September 20, 2016 04:17:21 crimaniak via Digitalmars-d-learn wrote: static shared immutable ReturnType!T value; I would point out that immutable is implicitly shared, so there's no reason to put shared on an immutable variable. However, you _do_ want to put shared on a static constructor that initializes an immutable variable so that it's only run once for the program instead of once per thread (the compiler really should enforce that, but there's a longstanding bug that allows you to reinitialize an immutable variable by not putting shared on the static constructor and starting multiple threads). Ok, I got it. Thanks.
Re: thisExePath purity
On 9/20/16 12:17 AM, crimaniak wrote: Hi and thanks all! On Tuesday, 20 September 2016 at 00:43:10 UTC, Jonathan M Davis wrote: immutable string executablePath; shared static this() { import std.file : thisExePath(); executablePath = thisExePath(); } This code is good for my needs but I start to think about how to call thisExePath only if it is really used and come to this solution: import std.traits: ReturnType, Parameters; string staticMemoize(alias T, Parms = Parameters!T)() pure { struct Holder(alias T) { static shared immutable ReturnType!T value; shared static this(){ value = T(Parms); } } return Holder!T.value; } unittest { import std.file : thisExePath; assert(staticMemoize!thisExePath == thisExePath); } Something like this. Need to refine about input parameters, but I hope, idea is clear. Unlike the function memoize from phobos staticMemoize really pure. And unlike proposed solution with ordinary variable staticMemoize is lazy, because no call - no instantiation. Yes, but if your code does instantiate it, it is called, even if you don't ever call the function that calls it. Note that if you don't import the module that contains the static ctor, it should be trimmed by the linker. I would absolutely caution you from putting static this() inside any template. Unfortunately, due to the way D generates these static constructors, any module that uses staticMemoize, or *imports a module that uses it*, will be marked as having a static constructor, and will potentially create cycles. -Steve
Re: thisExePath purity
On Tuesday, 20 September 2016 at 04:17:21 UTC, crimaniak wrote: Hi and thanks all! On Tuesday, 20 September 2016 at 00:43:10 UTC, Jonathan M Davis wrote: immutable string executablePath; shared static this() { import std.file : thisExePath(); executablePath = thisExePath(); } This code is good for my needs but I start to think about how to call thisExePath only if it is really used and come to this solution: import std.traits: ReturnType, Parameters; string staticMemoize(alias T, Parms = Parameters!T)() pure { struct Holder(alias T) { static shared immutable ReturnType!T value; shared static this(){ value = T(Parms); } } return Holder!T.value; } unittest { import std.file : thisExePath; assert(staticMemoize!thisExePath == thisExePath); } Something like this. Need to refine about input parameters, but I hope, idea is clear. Unlike the function memoize from phobos staticMemoize really pure. And unlike proposed solution with ordinary variable staticMemoize is lazy, because no call - no instantiation. Have a look at `std.concurrency.initOnce`: https://dlang.org/phobos/std_concurrency.html#.initOnce But you will still need to use assumePure() for calling `thisExePath`, and it might do other things that are impure...
Re: thisExePath purity
On Tuesday, September 20, 2016 04:17:21 crimaniak via Digitalmars-d-learn wrote: > static shared immutable ReturnType!T value; I would point out that immutable is implicitly shared, so there's no reason to put shared on an immutable variable. However, you _do_ want to put shared on a static constructor that initializes an immutable variable so that it's only run once for the program instead of once per thread (the compiler really should enforce that, but there's a longstanding bug that allows you to reinitialize an immutable variable by not putting shared on the static constructor and starting multiple threads). - Jonathan M Davis
Re: thisExePath purity
Hi and thanks all! On Tuesday, 20 September 2016 at 00:43:10 UTC, Jonathan M Davis wrote: immutable string executablePath; shared static this() { import std.file : thisExePath(); executablePath = thisExePath(); } This code is good for my needs but I start to think about how to call thisExePath only if it is really used and come to this solution: import std.traits: ReturnType, Parameters; string staticMemoize(alias T, Parms = Parameters!T)() pure { struct Holder(alias T) { static shared immutable ReturnType!T value; shared static this(){ value = T(Parms); } } return Holder!T.value; } unittest { import std.file : thisExePath; assert(staticMemoize!thisExePath == thisExePath); } Something like this. Need to refine about input parameters, but I hope, idea is clear. Unlike the function memoize from phobos staticMemoize really pure. And unlike proposed solution with ordinary variable staticMemoize is lazy, because no call - no instantiation. https://dlang.org/library/std/functional/memoize.html
Re: thisExePath purity
On Tuesday, September 20, 2016 00:37:10 Stefan Koch via Digitalmars-d-learn wrote: > On Tuesday, 20 September 2016 at 00:01:58 UTC, crimaniak wrote: > > Hi! > > > > Is there situations when output of thisExePath() can be > > different during runtime? If yes, what the reason? > > If no, is this possible to mark it as pure in phobos? > > > > https://dlang.org/library/std/file/this_exe_path.html > > No way to do that. > It does I/O. > However you cheat. > look for assumePure in https://dlang.org/phobos/std_traits.html > and then you can create a wrapper for it that is fake pure. Yes, you can cast a function pointer to force purity, but that's almost always a bad idea. It makes far more sense to just grab the value once and reuse it. The only time that I'd suggest using the casting trick for something like this would be when you can't afford to use static constructors, and you can't afford to pass the value around. Casting to pure should be a tool of last resort. It _is_ an option though if you really have no reasonable alternative. Another thing to consider in this case is that casting like that would actually be needlessly expensive if he actually needs to make the call more than once. It would be far cheaper to just save the result and reuse it. And if it's stored in an immutable module-level or static variable, then it can be used in a pure function. - Jonathan M Davis
Re: thisExePath purity
On Tuesday, September 20, 2016 00:01:58 crimaniak via Digitalmars-d-learn wrote: > Hi! > > Is there situations when output of thisExePath() can be different > during runtime? If yes, what the reason? > If no, is this possible to mark it as pure in phobos? > > https://dlang.org/library/std/file/this_exe_path.html In principle, it should be impossible for it to change while the program is running. However, what Phobos has to do to get the information can't be pure. In the best case, it involves calling C functions that we can reasonably assume will be pure but can't technically guarantee will be, but in some cases, it actually involves querying the file system (e.g. on Linux, it reads "/proc/self/exe"), which definitely can't be pure, because it involves I/O. If you really want a pure way to deal with this, then I'd suggest grabbing the value at startup and setting it to an immutable variable. e.g. something like immutable string executablePath; shared static this() { import std.file : thisExePath(); executablePath = thisExePath(); } and then you can use that variable in pure code, because it's guaranteed not to change. - Jonathan M Davis
Re: thisExePath purity
On 9/19/16 8:01 PM, crimaniak wrote: Hi! Is there situations when output of thisExePath() can be different during runtime? If yes, what the reason? If no, is this possible to mark it as pure in phobos? https://dlang.org/library/std/file/this_exe_path.html Not in a way that D can ensure purity. Yes, it will not change. But that guarantee is not communicated via the OS functions required to call to get the information. One thing you can do: immutable string myPath; shared static this() { import std.file: thisExePath; myPath = thisExePath; } // now use myPath as required from pure functions. -Steve
Re: thisExePath purity
On Tuesday, 20 September 2016 at 00:01:58 UTC, crimaniak wrote: Hi! Is there situations when output of thisExePath() can be different during runtime? If yes, what the reason? If no, is this possible to mark it as pure in phobos? https://dlang.org/library/std/file/this_exe_path.html No way to do that. It does I/O. However you cheat. look for assumePure in https://dlang.org/phobos/std_traits.html and then you can create a wrapper for it that is fake pure.
thisExePath purity
Hi! Is there situations when output of thisExePath() can be different during runtime? If yes, what the reason? If no, is this possible to mark it as pure in phobos? https://dlang.org/library/std/file/this_exe_path.html
[Issue 11047] UDA + getAttributes bypass purity/safety check
https://issues.dlang.org/show_bug.cgi?id=11047 --- Comment #3 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/55bd78ded94a1f40ee80c4e42791f216e5d58c41 fix Issue 11047 - UDA + getAttributes bypass purity/safety check https://github.com/dlang/dmd/commit/d1c3b6a1eab3347d9b6eb832b99ee45f70bd3702 Merge pull request #5863 from WalterBright/fix11047 fix Issue 11047 - UDA + getAttributes bypass purity/safety check --
[Issue 11047] UDA + getAttributes bypass purity/safety check
https://issues.dlang.org/show_bug.cgi?id=11047 Walter Brightchanged: What|Removed |Added Keywords||pull --- Comment #2 from Walter Bright --- https://github.com/dlang/dmd/pull/5863 --
[Issue 11047] UDA + getAttributes bypass purity/safety check
https://issues.dlang.org/show_bug.cgi?id=11047 --- Comment #1 from Walter Bright--- http://dlang.org/spec/attribute.html#UserDefinedAttribute They are defined as "compile time expressions" meaning they have to be evaluatable at compile time into a manifest constant. The bug here is this is not being checked. --
[Issue 11047] UDA + getAttributes bypass purity/safety check
https://issues.dlang.org/show_bug.cgi?id=11047 Walter Brightchanged: What|Removed |Added CC||bugzi...@digitalmars.com See Also||https://issues.dlang.org/sh ||ow_bug.cgi?id=13442 --
Re: Weak Purity Blog Post
Yeah, there's a lot more stuff I could have talked about, but I think I'll leave it for other posts. About testing, I think the way protection works in D (i.e., private members are accessible within the same file) is important, too. I was a bit suspicious of that feature when I first looked at D (coming from C++) but now I actually like the kind of project structure it leads to. I think better testability is just one of the advantages, but I'll write up a full blog post sometime.
Re: Weak Purity Blog Post
On Monday, 28 March 2016 at 01:44:02 UTC, sarn wrote: D's implementation of functional purity supports "weak" purity - functions that can mutate arguments but are otherwise traditionally pure. I wrote a post about some of the practical benefits of this kind of purity: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html Nice article. A suggestion: The point about improved testability when designing for purity is well made. In D, this is further supported by the ability to write and place unit tests alongside the functions themselves. That's my personal opinion at least - because unit test are so easy to write in D, it encourages design for testability. My suggestion is to add a note about this to the post. --Jon
Re: Weak Purity Blog Post
On Monday, 28 March 2016 at 01:44:02 UTC, sarn wrote: I wrote a post about some of the practical benefits of this kind of purity: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html Great. It would be nice if you added a section that discusses purity in collaboration with allocators. See discussions: http://forum.dlang.org/post/yvwtjybwphxovrxav...@forum.dlang.org http://forum.dlang.org/post/ejaarbdzcqgqhkxla...@forum.dlang.org and https://github.com/D-Programming-Language/druntime/pull/1183#issuecomment-202444315
Re: Weak Purity Blog Post
On Monday, 28 March 2016 at 09:59:12 UTC, ag0aep6g wrote: On 28.03.2016 03:44, sarn wrote: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html From there: Well, you can get the usual (“strong”) purity guarantee just by making all pointer or reference type arguments const. Indirections in the return type also play into this. David Nadlinger explains this in his article on the matter: http://klickverbot.at/blog/2012/05/purity-in-d/#indirections-in-the-return-type Thanks. I updated the post.
Re: Weak Purity Blog Post
On 28.03.2016 03:44, sarn wrote: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html From there: Well, you can get the usual (“strong”) purity guarantee just by making all pointer or reference type arguments const. Indirections in the return type also play into this. David Nadlinger explains this in his article on the matter: http://klickverbot.at/blog/2012/05/purity-in-d/#indirections-in-the-return-type
Re: Weak Purity Blog Post
On 3/27/2016 10:41 PM, deadalnix wrote: https://www.reddit.com/r/programming/comments/4c8zs6/how_dirtying_pure_functions_a_little_can_be/ BTW, thanks for posting it.
Re: Weak Purity Blog Post
On 3/27/2016 6:44 PM, sarn wrote: D's implementation of functional purity supports "weak" purity - functions that can mutate arguments but are otherwise traditionally pure. I wrote a post about some of the practical benefits of this kind of purity: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html It's a nice article, you should put your name on it as the author!
Re: Weak Purity Blog Post
On 3/27/2016 10:41 PM, deadalnix wrote: On Monday, 28 March 2016 at 05:21:36 UTC, Joakim wrote: On Monday, 28 March 2016 at 01:44:02 UTC, sarn wrote: D's implementation of functional purity supports "weak" purity - functions that can mutate arguments but are otherwise traditionally pure. I wrote a post about some of the practical benefits of this kind of purity: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html Very well-written, someone post it on Reddit. https://www.reddit.com/r/programming/comments/4c8zs6/how_dirtying_pure_functions_a_little_can_be/ Queue my usual harangue: Articles do MUCH MUCH better on reddit if, when posted, a brief description of the content of the article is also posted. Like what sarn posted here. Not doing so seriously blunts the value. People need a reason to click on the article. It's why when you google something, you don't just get a list of links. You get a blurb with each link.
Weak Purity Blog Post
D's implementation of functional purity supports "weak" purity - functions that can mutate arguments but are otherwise traditionally pure. I wrote a post about some of the practical benefits of this kind of purity: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html
Re: Containers, Allocators and Purity
On Thursday, 24 March 2016 at 11:18:06 UTC, Nordlöw wrote: Could somebody briefly outline how the thread-locality (non-GC-locked) of allocators relates to the purity of the containers using them? This because I want to move forward with optimizations in my knowledge graph that requires GC-free array containers storing value typed elements (integers) which preferrably has pure API. Specifically, I want to use something like https://github.com/economicmodeling/containers/blob/master/src/containers/dynamicarray.d that is `@safe pure` and uses lock-free allocations in a heavily multi-threaded application. If I want purity aswell which `std.experimental.allocators` are possible? After a quick glance at: https://github.com/economicmodeling/containers/blob/master/src/containers/dynamicarray.d It looks like if `useGC == false`, all of the methods should be `pure`-ready, except for `remove(size_t)` and `~this()`. These two methods use `typeid.destroy`, which I don't think is `pure`.
Re: Containers, Allocators and Purity
On Thursday, 24 March 2016 at 11:18:06 UTC, Nordlöw wrote: Could somebody briefly outline how the thread-locality (non-GC-locked) of allocators relates to the purity of the containers using them? This because I want to move forward with optimizations in my knowledge graph that requires GC-free array containers storing value typed elements (integers) which preferrably has pure API. Specifically, I want to use something like https://github.com/economicmodeling/containers/blob/master/src/containers/dynamicarray.d that is `@safe pure` and uses lock-free allocations in a heavily multi-threaded application. If I want purity aswell which `std.experimental.allocators` are possible? Currently almost nothing in `std.experimental.allocators` is explicitly marked as pure, except for some of the things in ./common.d (https://github.com/D-Programming-Language/phobos/pull/3957 *shameless plug*). Thankfully make, makeArray, dispose and some of the allocators are templates, so you can rely on attribute inference. The most important thing is that you need to have pure `allocate` and `deallocate` methods. After this `make` and friends will work like magic (at least for types with pure `this` and `~this`). `pure` statefull allocator essentially means that it has to be thread-local, so there are no global side-effects. Essentially, to achieve this you can make a large initial allocation in each thread (even from a non-pure allocator) and then you can make `pure` sub-allocations out of it. You can read more about my adventures with my `pure` smart pointer here: http://forum.dlang.org/post/eegjluaiwvdxfnbxk...@forum.dlang.org http://forum.dlang.org/post/bvgyrfvuqrqcyvhkq...@forum.dlang.org
Containers, Allocators and Purity
Could somebody briefly outline how the thread-locality (non-GC-locked) of allocators relates to the purity of the containers using them? This because I want to move forward with optimizations in my knowledge graph that requires GC-free array containers storing value typed elements (integers) which preferrably has pure API. Specifically, I want to use something like https://github.com/economicmodeling/containers/blob/master/src/containers/dynamicarray.d that is `@safe pure` and uses lock-free allocations in a heavily multi-threaded application. If I want purity aswell which `std.experimental.allocators` are possible?
Re: Container Purity
On Wednesday, 9 December 2015 at 10:47:18 UTC, Nordlöw wrote: that uses std.experimental.container Correction: I mean std.experimental.allocator
Container Purity
Is it currently possible for a container such as https://github.com/economicmodeling/containers/blob/master/src/containers/dynamicarray.d that uses std.experimental.container to be completely pure? If not can be made to? I wonder because only length(), empty(), front() and back() are tagged as pure in DynamicArray at https://github.com/economicmodeling/containers/blob/master/src/containers/dynamicarray.d are marked as pure. Is there a reason for this?
Re: Container Purity
Allocators usually use global state. Such code is usually treated as impure.