www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - conv text and pure

reply "Daniel Davidson" <nospam spam.com> writes:
Should text be pure?

I have multiple enforce statements of the form:

       enforce(0 == _history.length ||
               !binaryFun!(orderingPred)(additional, 
_history[$-1]),
               text(V.stringof, " must be added in chronological 
order, but ",
                    additional, " comes before ", _history[$-1]));

and I was hoping that statement would not be the reason for 
keeping the containing function from being pure.

Is there a simple work around?

Regarding pure in general:

   - Is there a global list of standard functions that are in the 
queue for this designation? (or is every function taking a 
separate issue)
   - Where does (or should) purity fall in terms of priority?
   - Isn't it the case that unnecessary, forced impurity is like a 
plague, once it starts the spread is rapid. In general, have most 
developers given up on its benefit in their code now preferring 
/* pure */?

Thanks
Dan
Oct 23 2013
parent reply "Andrej Mitrovic" <andrej.mitrovich gmail.com> writes:
On Wednesday, 23 October 2013 at 19:55:26 UTC, Daniel Davidson 
wrote:
 Should text be pure?
It's pure in 2.064, the upcoming release.
Oct 23 2013
parent reply "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 23 October 2013 at 19:56:26 UTC, Andrej Mitrovic 
wrote:
 On Wednesday, 23 October 2013 at 19:55:26 UTC, Daniel Davidson 
 wrote:
 Should text be pure?
It's pure in 2.064, the upcoming release.
Great, thanks. What is the best way to get on that version for the Mac (pointer to instructions)? Thanks Dan
Oct 23 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 10/23/13, Daniel Davidson <nospam spam.com> wrote:
 Great, thanks. What is the best way to get on that version for
 the Mac (pointer to instructions)?
You can download the beta here: http://forum.dlang.org/thread/52605C84.6010109 walterbright.com
Oct 23 2013
parent reply "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 23 October 2013 at 20:18:39 UTC, Andrej Mitrovic 
wrote:
 On 10/23/13, Daniel Davidson <nospam spam.com> wrote:
 Great, thanks. What is the best way to get on that version for
 the Mac (pointer to instructions)?
You can download the beta here: http://forum.dlang.org/thread/52605C84.6010109 walterbright.com
Thanks for pointer. I am using it and the file conv.d has: string text(T...)(T args) { return textImpl!string(args); } So, when you say it is pure, what are you referring to. I think pure could be specified as a block, but when I search up the next prior pure occurrence is: safe pure unittest So I don't think it is in a pure block. Also I still get: Error: pure function 'plus.utils.history.History!(const(S), "a.date < b.date").History.opOpAssign!("~", S).opOpAssign' cannot call impure function 'std.conv.text!(string, string, const(S), string, const(S)).text' So, I am still looking for workaround if possible and answers to the general questions on pure. Thanks Dan
Oct 23 2013
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 10/23/2013 02:17 PM, Daniel Davidson wrote:
 On Wednesday, 23 October 2013 at 20:18:39 UTC, Andrej Mitrovic wrote:
 On 10/23/13, Daniel Davidson <nospam spam.com> wrote:
 Great, thanks. What is the best way to get on that version for
 the Mac (pointer to instructions)?
You can download the beta here: http://forum.dlang.org/thread/52605C84.6010109 walterbright.com
Thanks for pointer. I am using it and the file conv.d has: string text(T...)(T args) { return textImpl!string(args); } So, when you say it is pure, what are you referring to. I think pure could be specified as a block, but when I search up the next prior pure occurrence is: safe pure unittest So I don't think it is in a pure block. Also I still get: Error: pure function 'plus.utils.history.History!(const(S), "a.date < b.date").History.opOpAssign!("~", S).opOpAssign' cannot call impure function 'std.conv.text!(string, string, const(S), string, const(S)).text' So, I am still looking for workaround if possible and answers to the general questions on pure. Thanks Dan
Perhaps it missed the beta cut. The following compiles with git head (or at least with v2.064-devel-b12d171): import std.conv; import std.exception; void foo(int i) pure { enforce (i == 42, i.text); } void main() { foo(42); } Ali
Oct 23 2013
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Oct 23, 2013 at 11:17:30PM +0200, Daniel Davidson wrote:
 On Wednesday, 23 October 2013 at 20:18:39 UTC, Andrej Mitrovic
 wrote:
On 10/23/13, Daniel Davidson <nospam spam.com> wrote:
Great, thanks. What is the best way to get on that version for the
Mac (pointer to instructions)?
You can download the beta here: http://forum.dlang.org/thread/52605C84.6010109 walterbright.com
Thanks for pointer. I am using it and the file conv.d has: string text(T...)(T args) { return textImpl!string(args); } So, when you say it is pure, what are you referring to. I think pure could be specified as a block, but when I search up the next prior pure occurrence is: safe pure unittest
No, pure can't be specified as a block. You can only mark a function as pure. Furthermore, the above function is a template function, which means the compiler will perform attribute inference on it. So provided textImpl has no impure operations, it should be inferred as pure, unless args has some impure methods in it that's being used by textImpl.
 So I don't think it is in a pure block. Also I still get:
 
 Error: pure function 'plus.utils.history.History!(const(S), "a.date
 < b.date").History.opOpAssign!("~", S).opOpAssign' cannot call
 impure function 'std.conv.text!(string, string, const(S), string,
 const(S)).text'
 
 So, I am still looking for workaround if possible and answers to the
 general questions on pure.
[...] OK, I'm looking at the implementation of textImpl in std/conv.d, and it seems that the only thing it does is to call to!string(...) on each of its arguments, and append the result to a local variable called 'result'. Since array appending is pure (otherwise we have major problems with D purity), the only culprit seems to be the calls to to!string(). What arguments are you passing to text()? Do all of them have toString methods that are marked pure? Keep in mind that the default toString implementation (e.g. inherited from Object) may not necessarily be marked pure, so that could be the cause of your problems here. It would be nice if you could provide a suitably minimized version of your code that exhibits this purity issue, so that we can track it down. It's kinda hard to figure out what's wrong based on verbal descriptions alone. (I apologize if you've already posted said code; I've been too busy to keep up with every post in this forum.) T -- Those who've learned LaTeX swear by it. Those who are learning LaTeX swear at it. -- Pete Bleackley
Oct 23 2013
parent reply "Daniel Davidson" <nospam spam.com> writes:
On Wednesday, 23 October 2013 at 21:37:25 UTC, H. S. Teoh wrote:
 On Wed, Oct 23, 2013 at 11:17:30PM +0200, Daniel Davidson wrote:
 On Wednesday, 23 October 2013 at 20:18:39 UTC, Andrej Mitrovic
 wrote:
On 10/23/13, Daniel Davidson <nospam spam.com> wrote:
Great, thanks. What is the best way to get on that version 
for the
Mac (pointer to instructions)?
You can download the beta here: http://forum.dlang.org/thread/52605C84.6010109 walterbright.com
Thanks for pointer. I am using it and the file conv.d has: string text(T...)(T args) { return textImpl!string(args); } So, when you say it is pure, what are you referring to. I think pure could be specified as a block, but when I search up the next prior pure occurrence is: safe pure unittest
No, pure can't be specified as a block. You can only mark a function as pure.
I think that is not correct. Consider: int x = 3; struct S { pure { void foo() { //x = 4; } } } pure blocks seem to have the effect you would expect. In fact it seems like you can stream them together to make code more pleasant: const pure ... { ... }
 Furthermore, the above function is a template function, which 
 means the
 compiler will perform attribute inference on it. So provided 
 textImpl
 has no impure operations, it should be inferred as pure, unless 
 args has
 some impure methods in it that's being used by textImpl.


 So I don't think it is in a pure block. Also I still get:
 
 Error: pure function 'plus.utils.history.History!(const(S), 
 "a.date
 < b.date").History.opOpAssign!("~", S).opOpAssign' cannot call
 impure function 'std.conv.text!(string, string, const(S), 
 string,
 const(S)).text'
 
 So, I am still looking for workaround if possible and answers 
 to the
 general questions on pure.
[...] OK, I'm looking at the implementation of textImpl in std/conv.d, and it seems that the only thing it does is to call to!string(...) on each of its arguments, and append the result to a local variable called 'result'. Since array appending is pure (otherwise we have major problems with D purity), the only culprit seems to be the calls to to!string(). What arguments are you passing to text()? Do all of them have toString methods that are marked pure? Keep in mind that the default toString implementation (e.g. inherited from Object) may not necessarily be marked pure, so that could be the cause of your problems here. It would be nice if you could provide a suitably minimized version of your code that exhibits this purity issue, so that we can track it down. It's kinda hard to figure out what's wrong based on verbal descriptions alone. (I apologize if you've already posted said code; I've been too busy to keep up with every post in this forum.)
Here is the self-contained code (I hope) that you can see it happening in: http://pastebin.com/hb0Dz50r BTW: any and all constructive criticism on any aspect of code is welcome. I have not previously posted this code, but per your request on a previous thread (http://forum.dlang.org/post/xvymqxecgmkyvpvegird forum.dlang.org) I did post sample code of struggles with immutable members. I've since mostly given up on immutable members (partially on your explanations and reasoning) and therefore immutable in general and so I find it's presence in the language like grapes to Tantalus. Not sure why I'm even fighting for purity since my main purpose for it originally was to allow for easy creation of immutable(T). Thanks Dan
Oct 23 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 23 October 2013 at 22:12:50 UTC, Daniel Davidson 
wrote:
 No, pure can't be specified as a block. You can only mark a 
 function as
 pure.
Any attribute can be specified as a block, as well as with colon notation.
Oct 23 2013
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, October 24, 2013 00:12:48 Daniel Davidson wrote:
 On Wednesday, 23 October 2013 at 21:37:25 UTC, H. S. Teoh wrote:
 On Wed, Oct 23, 2013 at 11:17:30PM +0200, Daniel Davidson wrote:
 On Wednesday, 23 October 2013 at 20:18:39 UTC, Andrej Mitrovic
 
 wrote:
On 10/23/13, Daniel Davidson <nospam spam.com> wrote:
Great, thanks. What is the best way to get on that version
for the
Mac (pointer to instructions)?
You can download the beta here: http://forum.dlang.org/thread/52605C84.6010109 walterbright.com
Thanks for pointer. I am using it and the file conv.d has: string text(T...)(T args) { return textImpl!string(args); } So, when you say it is pure, what are you referring to. I think pure could be specified as a block, but when I search up the next prior pure occurrence is: safe pure unittest
No, pure can't be specified as a block. You can only mark a function as pure.
I think that is not correct. Consider: int x = 3; struct S { pure { void foo() { //x = 4; } } } pure blocks seem to have the effect you would expect. In fact it seems like you can stream them together to make code more pleasant: const pure ... { ... }
You can use pretty much any attribute with a block or a :, so you can use a pure block, but it's almost always a bad idea to put pure, nothrow, safe, or trusted on a templated function, because whether the attribute is valid or not almost always depends on the template arguments. So, if you use such an attribute no a templated function, you restrict the types that will work with that function. Rather, templated functions infer pure, nothrow, and safe, so in most cases, using those attributes on templated functions should be unnecessary. Now, the template inferrence needs a lot of work, so it doesn't generally work on the more complicated cases yet (e.g. a struct declared inside of a templated function doesn't end up getting inferrence for its member functions like it should), but that will be fixed. That combined with the fact that several lower level constructs in druntime and Phobos still need some work to make them properly pure, nothrow, and/or trusted/ safe makes it so that a lot less of Phobos is pure, nothrow, or safe than should be the case. Progress is being made on that however (as evidenced by the fact that format can now be pure in the beta for 2.064). - Jonathan M Davis
Oct 23 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Progress is being made on that however (as evidenced by the
 fact that format can now be pure in the beta for 2.064).
Now two of the most common "offenders" of pure/nothrow in my high level code are iota() and arr.dup. Bye, bearophile
Oct 23 2013
parent reply "Daniel Davidson" <nospam spam.com> writes:
On Thursday, 24 October 2013 at 00:02:30 UTC, bearophile wrote:
 Jonathan M Davis:

 Progress is being made on that however (as evidenced by the
 fact that format can now be pure in the beta for 2.064).
Now two of the most common "offenders" of pure/nothrow in my high level code are iota() and arr.dup. Bye, bearophile
Is arr.dup really impure or is it something queued up to become pure? Thanks Dan
Oct 28 2013
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, October 28, 2013 13:40:03 Daniel Davidson wrote:
 On Thursday, 24 October 2013 at 00:02:30 UTC, bearophile wrote:
 Jonathan M Davis:
 Progress is being made on that however (as evidenced by the
 fact that format can now be pure in the beta for 2.064).
Now two of the most common "offenders" of pure/nothrow in my high level code are iota() and arr.dup. Bye, bearophile
Is arr.dup really impure or is it something queued up to become pure?
It's essentially a bug that the compiler does not consider it pure. Memory allocation is valid in pure functions, and dup is just as pure as new is. It can't be pure if copying the array's elements isn't pure (e.g. if the elements have impure postblits), but it can certainly be pure for the built-in types and any user-defined types for which copying is pure. - Jonathan M Davis
Oct 28 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 24, 2013 at 12:12:48AM +0200, Daniel Davidson wrote:
 On Wednesday, 23 October 2013 at 21:37:25 UTC, H. S. Teoh wrote:
On Wed, Oct 23, 2013 at 11:17:30PM +0200, Daniel Davidson wrote:
[...]
So, when you say it is pure, what are you referring to. I think pure
could be specified as a block, but when I search up the next prior
pure occurrence is:
   safe pure unittest
No, pure can't be specified as a block. You can only mark a function as pure.
I think that is not correct. Consider: int x = 3; struct S { pure { void foo() { //x = 4; } } } pure blocks seem to have the effect you would expect. In fact it seems like you can stream them together to make code more pleasant: const pure ... { ... }
You're right. I didn't make myself clear: pure blocks are allowed but not inside a function, i.e., this isn't supported currently: void foo() { pure { ... } ... } My bad. [...]
 Here is the self-contained code (I hope) that you can see it
 happening in:
 http://pastebin.com/hb0Dz50r
 
 BTW: any and all constructive criticism on any aspect of code is
 welcome.
[...] Thanks! Sorry I have to run now; I'll take a look at your code later, and perhaps try to track down the source of the purity error. T -- "I suspect the best way to deal with procrastination is to put off the procrastination itself until later. I've been meaning to try this, but haven't gotten around to it yet. " -- swr
Oct 23 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 24, 2013 at 12:12:48AM +0200, Daniel Davidson wrote:
[...]
 Here is the self-contained code (I hope) that you can see it
 happening in:
 http://pastebin.com/hb0Dz50r
[...] Hmm. Somebody claimed that 2.064 beta has made text() pure, but that's only partially true, because it calls to!(), and so its purity depends on the purity of to!(). Unfortunately, to!() is NOT pure for many basic types, including to!string(double.init). Furthermore, to!string(S) for some struct S appears to be impure by default unless you manually define a toString method that declares itself pure. Unfortunately, to!string(DateTime.init) isn't pure either, which means that if your struct contains DateTime and you need to format it then you're out of luck. So basically, text() is still practically unusable for anything that isn't already trivially convertible to string (like string itself). Or int -- apparently to!string(int.init) does work in pure code. IOW, the purity of text() and to() still has a long ways to go before user code can depend on it. :-( Please file a bug in the bugtracker. In the meantime, I'm going to track down exactly why to!string(double) isn't pure, since there's no valid reason why it can't be. T -- I am Ohm of Borg. Resistance is voltage over current.
Oct 24 2013
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 24, 2013 at 11:36:09AM -0700, H. S. Teoh wrote:
 On Thu, Oct 24, 2013 at 12:12:48AM +0200, Daniel Davidson wrote:
 [...]
 Here is the self-contained code (I hope) that you can see it
 happening in:
 http://pastebin.com/hb0Dz50r
[...] Hmm. Somebody claimed that 2.064 beta has made text() pure, but that's only partially true, because it calls to!(), and so its purity depends on the purity of to!(). Unfortunately, to!() is NOT pure for many basic types, including to!string(double.init).
[...]
 In the meantime, I'm going to track down exactly why to!string(double)
 isn't pure, since there's no valid reason why it can't be.
[...] So I traced the code down in Phobos, and discovered that the reason to!string(double.init) isn't pure is because it ultimately calls the C library snprintf to format floating-point values. And the fact that it uses toString(scope void delegate(const(char)[])), which can't be made pure because its purity depends on the purity of the delegate, and currently the compiler has no way of inferring this, and the language has no way to express this. :-( Which means unless we rewrite large swaths of std.conv, making text(double.init) pure isn't going to happen anytime soon. :-( T -- It is not the employer who pays the wages. Employers only handle the money. It is the customer who pays the wages. -- Henry Ford
Oct 24 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 10/23/13, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 Furthermore, the above function is a template function, which means the
 compiler will perform attribute inference on it. So provided textImpl
 has no impure operations, it should be inferred as pure, unless args has
 some impure methods in it that's being used by textImpl.
Yeah that may just be the issue. The reason I mentioned 2.064 is because std.conv.to and std.string.format are now pure, and text() likely uses these in one way or another.
Oct 23 2013
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 23 October 2013 at 21:17:31 UTC, Daniel Davidson 
wrote:
 const(S))
make sure your struct's toString are all marked pure too.
Oct 23 2013