View mode: basic / threaded / horizontal-split · Log in · Help
January 15, 2013
Re: Exceptional coding style
On 01/15/13 12:21, bearophile wrote:
> Artur Skawina:
> 
>> Library territory. There's no need to put this in a D compiler.
> 
> One of the threads about possible ways to allow to implement that in library code:
> 
> http://forum.dlang.org/thread/nxhsgwliuwdgidaoudud@forum.dlang.org
> 
> 
>> Except if you'd like to have 'printf("%.2g", d)' instead of 'printf!"%.2g"(d)' syntax.
> 
> In some cases I don't mind a syntax like 'printf!"%.2g"(d)'. But I'd like D to offer ways to remove/avoid template bloat in most of those cases.

You can't both avoid template bloat *and* statically check the arguments.
Statically checking dynamic data is not possible, obviously. But it's not
always a problem, as as long as everything is properly inlined the overhead
can be /less/ than zero. Anyway, a way to do these check right now could be
something like:

  auto printf(string fmt, A...)(A a) /*@inline*/ {
     static bool isFlag(char c) {
        switch (c) {
           case '0':  case '#': case '-': case ' ': case '+':
           case '\'': case 'I': // Non-std.
              return true;
           default: return false;
        }
     }
     static bool checkArgs(B...)(string fmt) {
        if (!__ctfe)
           assert(0, "This function relies on bounds checks happening at CT");
        while (fmt.length && fmt[0]!='%')
           fmt = fmt[1..$];
        if (fmt.length==0)
           return true;
        static if (B.length==0)
           return fmt.length==0;
        else {
           size_t skip = 1;
           // Flags
           while (isFlag(fmt[skip]))
              ++skip;
           // Width
           while (fmt[skip]>='0' && fmt[skip]<='9')
              ++skip;
           // Precision
              // XXX skip \.[0-9]* , \.\*, \.[0-9]+\$ 
           // Length modifier
              // XXX skip them.
           // Conversion spec
           if (
               (fmt[skip]=='d' && is(B[0]==int))
            || (fmt[skip]=='g' && is(B[0]==double))
            || (fmt[skip]=='s' && is(typeof(cast()*B[0])==char))
            /* XXX etc */
               )
              return checkArgs!(B[1..$])(fmt[skip+1..$]);
           assert(0, "printf format error: '" ~ fmt ~ "', remaining args: " ~ B.stringof);
        }
     }

     static assert(checkArgs!A(fmt), "Invalid or unsupported printf args");

     import si = std.stdio, std.string;
     return si.printf(toStringz(fmt), a);
  }

  void main() {
     printf!"Pi == %d.%d != %3d\n"(3, 14, 314);
     printf!"Pi == %d.%d == %g\n"(3, 14, 3.14);
     printf!"Pi == %d.%d == %g == %s\n"(3, 14, 3.14, "3.14".ptr);

     // correctly flagged as invalid:
     //printf!"%"(42);
  }

But ideally the syntax should be

  printf(A...)(static string s, A a)

which would be "lowered" to the equivalent of

  printf(string s, A...)(A a)

and similarly:

  printf(A...)(alias a, A a)

should behave as

  print(alias a, A...)(A a)


Having this work just for templated functions would probably be ok.

artur
January 15, 2013
Re: Exceptional coding style
Artur Skawina:

> You can't both avoid template bloat *and* statically check the 
> arguments.

In a well designed statically compiled language you don't need to 
instantiate templates and let them generate binary code to 
statically verify a condition. What's needed to test compile time 
arguments is just some compile-time computation; there is no need 
for such computation to leave any trace in the resulting binary. 
Beside the idea of "ghost types" (it's not a Pokemon), see also 
this little thread:

http://forum.dlang.org/thread/nxhsgwliuwdgidaoudud@forum.dlang.org

D needs ways to avoid some template bloat in the first place, not 
just to remove it later.

In some cases I'd like to write code like this, but to not let 
this generate different template instantiations (this means x is 
really a run-time value, but it's required to be known at 
compile-time):

void foo(int x)(string s) {}

Bye,
bearophile
January 15, 2013
Re: Exceptional coding style
On 01/15/2013 11:57 AM, mist wrote:
> Well, probably I am playing "good vision nazi" here, as 12 font size
> seems HUGE to me, far beyond the comfort zone.

It's just preference. I do not have any problems with font size 9.
January 15, 2013
Re: Exceptional coding style
On Tuesday, 15 January 2013 at 13:55:53 UTC, Timon Gehr wrote:
> On 01/15/2013 11:57 AM, mist wrote:
>> Well, probably I am playing "good vision nazi" here, as 12 
>> font size
>> seems HUGE to me, far beyond the comfort zone.
>
> It's just preference. I do not have any problems with font size 
> 9.

I do not know of any editor that does not support "ctrl + scroll" 
to change the font sizes on the fly.

I always change the font size of my editor, depending on how 
concentrated I am, my position in my seat, or by how complicated 
the current algorithm is. Or simply if somebody is looking over 
my shoulder.

Your editor's font size should not be statically dictated by a 
single number.
January 15, 2013
Re: Exceptional coding style
On Tuesday, 15 January 2013 at 11:43:20 UTC, Simen Kjaeraas wrote:
> On 2013-58-15 11:01, Russel Winder <russel@winder.org.uk> wrote:
>
>> On Mon, 2013-01-14 at 11:24 -0800, Walter Bright wrote:
>>> Quite a nice read on the coding style used in Doom.
>>>
>>> http://kotaku.com/5975610/the-exceptional-beauty-of-doom-3s-source-code?post=56177550
>>
>> On the other hand I don't like some parts of the style he is 
>> putting
>> forward as good.
>>
>> Go has an extreme position on this, there is one and only one 
>> style of
>> code that is acceptable, the one defined in the gofmt program 
>> that is
>> used to format all Go code. I happen not to like some parts of 
>> it, but I
>> live with the enforced style.
>>
>> Python is less extreme, in that there are many styles of code 
>> allowed,
>> but there is PEP-8 which is "Python style as Guido intended".  
>> This is
>> supported by the pep8 program for enforcing elements of style. 
>> I have
>> disagreement with some of the choices, but I live with it, and 
>> format my
>> code to PEP-8 except for the line length rule – which is just 
>> so 1980s.
>>
>> C, C++, D, Fortran, Groovy, probably need to learn a lesson 
>> from one or
>> other of these.
>>
>> The issue is that having a single global style standard for a
>> programming language makes it easier to read code in that 
>> language.
>
> I agree a canonical form could be nice. Even so, I am firmly of 
> the
> opinion that such should not be forced upon programmers. 
> Prettifiers certainly can help here.

Not really; prettiffiers works for 99% of the code and mess the 
remaining 1%, that's why it is better to "force" programmers to 
use one style and not relying on a tool..
January 15, 2013
Re: Exceptional coding style
On 01/15/13 14:25, bearophile wrote:
> Artur Skawina:
> 
>> You can't both avoid template bloat *and* statically check the arguments.
> 
> In a well designed statically compiled language you don't need to instantiate templates and let them generate binary code to statically verify a condition. What's needed to test compile time arguments is just some compile-time computation; there is no need for such computation to leave any trace in the resulting binary.

You do realize that the code I posted in the previous message gave you static
verification at compile time and _zero_ runtime overhead? It's incomplete and
adds a toStringz call because it's just a POC. Actually that call can be dropped,
assuming a template string parameter is always null-terminated (which could be
specced that way), and then:

  void main() {
     printf!"Pi == %d.%d == %g == %s\n"(3, 14, 3.14, "3.14".ptr);
  }

compiles to:

  <_Dmain>:
      55                      push   %ebp
      89 e5                   mov    %esp,%ebp
      83 ec 28                sub    $0x28,%esp
      dd 05 88 d7 06 08       fldl   0x806d788
      c7 44 24 14 64 d7 06    movl   $0x806d764,0x14(%esp)
      08 
      dd 5c 24 0c             fstpl  0xc(%esp)
      c7 44 24 08 0e 00 00    movl   $0xe,0x8(%esp)
      00 
      c7 44 24 04 03 00 00    movl   $0x3,0x4(%esp)
      00 
      c7 04 24 69 d7 06 08    movl   $0x806d769,(%esp)
      e8 4c f2 ff ff          call   8049100 <printf@plt>
      31 c0                   xor    %eax,%eax
      c9                      leave  
      c3                      ret    

You can't get any less overhead than this; not even when using a "well designed
statically compiled language".

Being able to easily force evaluation at compile time and even a compile-time
mutable ephemeral storage class would be good ideas, but are not necessary for
this (they would make some things simpler, eliminate the need for recursion etc - yes).

> Beside the idea of "ghost types" (it's not a Pokemon), see also this little thread:
> 
> http://forum.dlang.org/thread/nxhsgwliuwdgidaoudud@forum.dlang.org
> 
> D needs ways to avoid some template bloat in the first place, not just to remove it later.
> 
> In some cases I'd like to write code like this, but to not let this generate different template instantiations (this means x is really a run-time value, but it's required to be known at compile-time):
> 
> void foo(int x)(string s) {}

A /run-time value known at compile-time/ is an oxymoron.

How would your above function to differ from this one
'void foo(alias x)(string s) {}' ?
Are you asking for 'void foo(alias int x)(string s) {}'?


artur
January 15, 2013
Re: Exceptional coding style
> Not really; prettiffiers works for 99% of the code and mess the
> remaining 1%, that's why it is better to "force" programmers to
> use one style and not relying on a tool..

ok but one can argue that having an coding standard defined by the 
community (like design and syntax of D) plus an standard (buildin) 
prettyprinter like goformat could be much better then the current known 
tools out there
January 15, 2013
Re: Exceptional coding style
Artur Skawina:

> static assert(checkArgs!A(fmt), "Invalid or unsupported printf 
> args");

A template constraint is better, I think.


>You can't get any less overhead than this; not even when using a 
>"well designed
statically compiled language".<

Maybe if you compile that with dmd and you look in the binary I 
think you will find some stuff related to that that's not needed.


>> void foo(int x)(string s) {}
>
> A /run-time value known at compile-time/ is an oxymoron.
>
> How would your above function to differ from this one
> 'void foo(alias x)(string s) {}' ?
> Are you asking for 'void foo(alias int x)(string s) {}'?

That wasn't an important request, feel free to ignore it.

What I was trying to say is not impossible. The run-time 
semantics of this:

void foo(static int x)(string s) {}

Is meant to be the same as:

void foo(int x, string s) {}

The only difference is that the compiler requires x to be 
statically known (but then you can't use specialize code on the 
value of x, because that's really not a template function).

This is also allowed, and it's similar to what we were discussing 
about:

void foo(static int x)(string s) if (predicate(x)) {}

Bye,
bearophile
January 15, 2013
Re: Exceptional coding style
On Tue, 2013-01-15 at 15:07 +0100, monarch_dodra wrote:
[…]
> 
> I do not know of any editor that does not support "ctrl + scroll" 
> to change the font sizes on the fly.

Emacs, VIM,…

[…]
> Your editor's font size should not be statically dictated by a 
> single number.

It depends on whether you want all the text to be a single size in which
case yes just one number to set the font size ;-)
-- 
Russel.
=============================================================================
Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder@ekiga.net
41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel@winder.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder
January 15, 2013
Re: Exceptional coding style
On Tue, Jan 15, 2013 at 11:23:40AM +0100, FG wrote:
> On 2013-01-15 09:29, monarch_dodra wrote:
> >I still prefer "writeln" over "writefln". While writefln issafe, you
> >can still botch the amount of args, and or flag types, in which case
> >writefln will throw. Writeln never throws (due to a code error).
> 
> What about the argument that a format string makes translation easier?

Current format string syntax still has a ways to go before it can make
translation easier. Consider this example:

	writeln("%s is found in %s", file.name, dir.name);

Sounds ideal for translation, right? Except that it's not. First,
reading the format string alone says nothing about what meaning is
intended. What is found in a what? Also, it doesn't let you vary the
word order correctly. Nor does it let you perform inflection correctly.

For true ease of translation, you need:

1) Logical naming of format arguments, e.g.:

	"%{filename} is found in %{dirname}"

and of course, some way to associate logical names with actual
arguments.

2) Some way to indicate the function of each word so that inflection can
be cone correctly, e.g.:

	"%{filename.nominative} is found in %{dirname.locative}"

or something like that, in languages where words change form depending
on function. There will, of course, need to be requisite mechanisms for
interpreting these word function identifiers.

3) Some way to indicate multiplicity:

	"1 file was found" vs. "2 files were found"

would require the quantity of files to be passed to the formatting
function so that the appropriate translation can be selected. Keep in
mind the different languages have different rules as to how to map
quantity to word forms; just because English has only two forms
(singular, plural) doesn't mean that that's enough. Russian, for
example, requires 3 distinct forms: one for singular, one for numbers
2-4, a third for 5 onwards (with the second form recurring for selected
subranges of the latter).

Current format strings are far from making translation truly easier.


T

-- 
Philosophy: how to make a career out of daydreaming.
1 2 3 4 5 6 7 8 9
Top | Discussion index | About this forum | D home