lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

On Sat, Aug 17, 2013 at 12:52 PM, Jay Carlson <> wrote:
> Somebody else can add the C standard citations and correct me; I'm not on
> the net as I'm writing this.
> On Aug 15, 2013 11:00 PM, "Andres Perera" <> wrote:
>> On Wed, Aug 14, 2013 at 7:23 PM, Jay Carlson <> wrote:
>> > tl;dr: if you have all the constraints C did 25 years ago, printf/scanf
>> > are reasonable. If you take Go's concrete syntax for expressing structured
>> > data as a given, using string patterns seem more ergonomic. I don't see why
>> > we should be constrained by either in 2013, but I don't have any concrete
>> > solution other than for Lua. E4X, RIP.
>> >
>> > On Aug 13, 2013, at 5:28 PM, William Ahern wrote:
>> >
>> >> On Tue, Aug 13, 2013 at 02:18:43AM -0400, Jay Carlson wrote:
>> >>> It is a cute idea, but just like printf, it's a symptom of a lack of
>> >>> expressive power at compile-time.
>> >>> [...[
>> >>> Most C compilers these days have special mechanisms hooked up to the
>> >>> printf/scanf functions to warn of mismatches in type between the
>> >>> format
>> >>> string and the arguments. So there's a special case again: you can't
>> >>> write
>> >>> your own replacements with the same functionality, especially if you
>> >>> are
>> >>> in the -Werror camp, where warnings are treated as errors.
>> >>
>> >> You can get close. Using C99's variable argument macros and C11's
>> >> _Restrict,
>> >> you can translate at compile time each argument to a pair of
>> >> arguments--type
>> >> and value. This type information can then be used at run time by the
>> >> printf
>> >> implementation.
>> >
>> > Hmm, _Generic? OK, there's a couple hours wasted:
>> >
>> > ===
>> > #define f_(X) _Generic((X), \
>> >   long double: fmt_long_double(X), \
>> >   double: fmt_double(X), \
>> >   unsigned int: fmt_unsigned_int(X), \
>> >   const char *: fmt_string(X)) (X)
>> then i guess i want to print an unsigned int always as %u, or another
>> size appropriate format? why associate a type that encodes signedness
>> and size (unsigned int) with a string representation of decimal (%u)
>> over octal (%o)?
> Because the signedness of integers in C is part of their type.

The radix is not.

Notice how I'm talking about b10 vs b8. And once you create a radix
associated type for the purpose of printing you
> end up causing a combinatorial explosion of types
> whose only purpose is to define subtly distinct toprintf() methods

> You snipped the rest of the code; I'll paste the end:
>> Usage:
>>  fmt("yarrrgh", 12.7, (unsigned int) 4000000000);
>>  fmt_with_spec("%s %g %u\n", "yarrrgh", 12.7, (unsigned int) 4000000000));
> The point of this is not just to build a debug aid like print() but also to
> support at least run-time diagnosis of argument/spec mismatches without
> requiring compiler support.

> C11 has been off my radar, so I didn't know there was a way of doing type
> dispatch at compile-time. I am not certain there really is, because I am
> confused by the wording of _Generic in relation to the pointer zoo.
>> people that try to come up with format-inducing printf() replacements,
>> where induction is based on argument type and the language doesn't
>> support typeclasses, end up causing a combinatorial explosion of types
>> whose only purpose is to define subtly distinct toprintf() methods
> printf does not support every argument type, and there are a fixed number of
> numeric types anyway.

Then again, printf() is not adapted as-is to other programs. Let's use
printf() as an example of a function with a little string language for
the purpose of formatting text. Let's use string.format() as an
instance of such an adaptation.

>> whats a *real* problem with printf() in a safe memory model runtime,
>> where you dont get segfaults in f("%s %s", a1) for reading a possibly
>> NULL pointer??
> (tl;dr: I don't understand what you mean by "safe memory model runtime"; my
> mental model of C and probably Go doesn't fit so I'm going to think out loud
> about how to implement what I think you mean.)

In f("%s %s", a1), there is a missing argument. It's perfectly
feasible for a libc to segfault.