September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
On 12/09/13 22:23, Jonathan M Davis wrote:
> You can put the try-catch in a version(assert) block to get around that
> problem, but it is true that it's not exactly ideal. However, there really
> isn't any way around that with a function that takes a format string unless
> you want it to ignore bad arguments. You'd need a function like text which
> just appends all of its arguments together in order to get around that
> problem.
Well, I have been using text() to generate my assert error messages, but the trouble is that (at least in 2.063) it's not @safe, pure or nothrow ... :-(
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
On Thu, Sep 12, 2013 at 11:37:10PM +0200, Joseph Rushton Wakeling wrote: > On 12/09/13 22:23, Jonathan M Davis wrote: > >You can put the try-catch in a version(assert) block to get around that problem, but it is true that it's not exactly ideal. However, there really isn't any way around that with a function that takes a format string unless you want it to ignore bad arguments. You'd need a function like text which just appends all of its arguments together in order to get around that problem. > > Well, I have been using text() to generate my assert error messages, > but the trouble is that (at least in 2.063) it's not @safe, pure or > nothrow ... :-( Even in git HEAD, text() may still throw. So ultimately, you still need assumeWontThrow: https://github.com/D-Programming-Language/phobos/pull/1571 :) T -- Some days you win; most days you lose. |
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Thursday, 12 September 2013 at 20:07:40 UTC, Jonathan M Davis wrote:
> On Thursday, September 12, 2013 12:42:34 H. S. Teoh wrote:
>> On Thu, Sep 12, 2013 at 09:12:18PM +0200, bearophile wrote:
>> > H. S. Teoh:
>> > >In phobos git HEAD, std.format has been made pure @safe nothrow (and
>> > >
>> > >CTFE-able), so you should be able to write your assert as:
>> > > assert(condition, format("x = %s, blahblah", x));
>> >
>> > With the latest DMD from updated GIT head:
>> >
>> >
>> > import std.string: format;
>> > void main() pure nothrow {
>> >
>> > string x = "hello";
>> > bool condition = true;
>> > assert(condition, format("x = %s, blahblah", x));
>> >
>> > }
>> >
>> >
>> > It gives:
>> >
>> > test.d(5): Error: 'std.string.format!(char, string).format' is not nothrow
>> > test.d(2): Error: function 'D main' is nothrow yet may throw
>>
>> [...]
>>
>> Oops. Apparently I wrote nothrow but forgot to test it. I did test pure
>> and @safe, though, so at least those two should work.
>
> format can't be nothrow, because it throws when you screw up the format
> specifiers. You have to wrap it in a try-catch block and assert(0) in the catch
> block if you want to put it in a nothrow function. std.datetime does this in
> at least a few places.
>
> - Jonathan M Davis
Why don't we have a format function that is statically checked?
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On Thu, Sep 12, 2013 at 11:45:07PM +0200, Meta wrote: > On Thursday, 12 September 2013 at 20:07:40 UTC, Jonathan M Davis wrote: [...] > >format can't be nothrow, because it throws when you screw up the format specifiers. You have to wrap it in a try-catch block and assert(0) in the catch block if you want to put it in a nothrow function. std.datetime does this in at least a few places. > > > >- Jonathan M Davis > > Why don't we have a format function that is statically checked? Currently, this is not possible, because the format string may be a runtime-computed value. For example: void main(string[] args) { // fmtString is only known at runtime. auto fmtString = File("fmtstrings.cfg").byLine().front.idup; // This will throw if command-line arguments don't match // format string. writefln(fmtString, args[1..$]); } It *is* true, however, that the vast majority of format usage uses a static format string. In those cases, it *would* be nice to have a nothrow variant of format(). Arguably, we could have this variant of format: string staticFormat(string fmt, T...)(T args) { ... } which takes a compile-time format string. Then it can be statically verified to be pure, @safe, nothrow, etc.. This is actually more tricky than it sounds, though. Specifiers like "%s" are parsed into Format!char objects, which may be passed to a user-defined type's toString method, so the nothrow-ness of staticFormat() may change depending on whether the user-defined toString throws. T -- Старый друг лучше новых двух. |
September 13, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Thursday, 12 September 2013 at 22:04:20 UTC, H. S. Teoh wrote: > Currently, this is not possible, because the format string may be a runtime-computed value. For example: > > ... > When you don't have a runtime computed format string, though (which is generally the case for my code, at least), it would be extremely useful for a literal format string to be statically verified and nothrow. One really nice thing I've seen with the Rust language is that they have a fmt macro that statically verifies that the types of its arguments match the format string. > It *is* true, however, that the vast majority of format usage uses a > static format string. In those cases, it *would* be nice to have a > nothrow variant of format(). Arguably, we could have this variant of > format: > > string staticFormat(string fmt, T...)(T args) { ... } > > which takes a compile-time format string. Then it can be statically > verified to be pure, @safe, nothrow, etc.. > > This is actually more tricky than it sounds, though. Specifiers like > "%s" are parsed into Format!char objects, which may be passed to a > user-defined type's toString method, so the nothrow-ness of > staticFormat() may change depending on whether the user-defined toString > throws. Is it necessary to allow toString to throw? I can't think of any reason other than the object being in an invalid state, in which case maybe it should throw an Error. |
Copyright © 1999-2021 by the D Language Foundation