September 12, 2013
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
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
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
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
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.

1 2
Next ›   Last »