February 12, 2013
On Monday, 4 February 2013 at 23:55:25 UTC, bearophile wrote:
> Is the Fwend user of Rosettacode (or some other interested person) around here? I have written partial D implementations for three tasks, maybe a little of coordination will speedup the work:
>
> http://rosettacode.org/wiki/Permutations/Rank_of_a_permutation
> http://rosettacode.org/wiki/Universal_Turing_machine
> http://rosettacode.org/wiki/RCRPG
>
> Bye,
> bearophile

If you're posting code on Rosetta code you are presenting that code as idiomatic. Doesn't that require some discussion of what is idiomatic D? You tend to use the superfluous parens which the properties discussion would suggest are becoming more idiomatic not to use. You also use 'in' a lot in function inputs while others have argued against it. This is not an attack on your code at all, but maybe there should be some discussion of and consensus on what is idiomatic.
February 12, 2013
ixid:

> If you're posting code on Rosetta code you are presenting that code as idiomatic.

The D code on Rosettacode has some stylistic uniformity, and I think in most cases it follows the dstyle (http://dlang.org/dstyle.html ), but that code is not meant to be "production code" (lot of people in other languages don't add unittests, etc). So it is not idiomatic, and it's not meant to be. If you go on Rosettacode you can't expect to see code similar to Phobos code.

There is also variability: some D entries of Rosettacode have unittests and are written in a readable style, other entries try to be short simple, and other entries are very strongly typed and longer, other entries look almost as C, and so on. This is done on purpose, to show various kinds of D coding. None of those ways is the only idiomatic one.


> You tend to use the superfluous parens which the properties discussion would suggest are becoming more idiomatic not to use.

-property was supposed to become the standard semantics of the D language. So I have written code that way. Later things are changing. Now I am waiting to see what's coming out of the property discussion. If the final decision is that those parentheses aren't needed nor idiomatic, I/we will (slowly) remove the parentheses from the entries.


> You also use 'in' a lot in function inputs while others have argued against it.

"in" is currently not good if you are writing a long term large library, or a larger program you want to use for lot of time, etc, because it assumes some type system semantics that is not yet implemented.
But for the purposes of Rosettacode using "in" is good, because it's short, readable, and if/when scope will break some entries, I/we will fix them.


> This is not an attack on your code at all, but maybe there should be some discussion of and consensus on what is idiomatic.

One problem of Rosettacode is that it's not so good to discuss. GitHub offers better means to discuss on the code.

What other things do you want to discuss about?

Bye,
bearophile
February 12, 2013
> What other things do you want to discuss about?

I mean some level of D community discussion of the language as a whole as to what is an idiomatic style, perhaps after the current issues are settled, not anything specific about your code. There are areas like complex UFCS statements where it would help to have agreed, suggested ways of formatting.
February 12, 2013
ixid:

> I mean some level of D community discussion of the language as a whole as to what is an idiomatic style, perhaps after the current issues are settled, not anything specific about your code.

Such discussion seems better in the main D newsgroup. But it also seems a good way to waste time with hundreds of posts that produce nothing of value :-)


> There are areas like complex UFCS statements where it would help to have agreed, suggested ways of formatting.

I think this is currently a good way to format that kind of chains, this is inspired by similar F# formatting:


auto r = fooSomething()
         .barSomething!pred1()
         .bazSomething()
         .spamSomething!fun2();


In some cases on Rosettacode I have followed that formatting pattern.

Bye,
bearophile
February 13, 2013
If some of you has a little of time to review code, I have converted the very fast C memory mapped version of "Ordered words" to D:

http://rosettacode.org/wiki/Ordered_words#Mmap

http://rosettacode.org/wiki/Ordered_words#Memory_Mapped_Version

The C version contains several pointers that get juggled around, even with a negative index:

if (s[0] < s[-1]) r = 0;

So the C entry is rather bug-prone (and it doesn't compile on GCC Windows). The D entry is portable, and uses mostly slices and (non-negative) array indexes.


The D findWord function is fiddly still:

const(char)[] findWord(const char[] s) pure nothrow @safe {
    size_t wordEnd = 0;
    while (wordEnd < s.length && s[wordEnd] != '\n'
           && s[wordEnd] != '\r')
        wordEnd++;
    return s[0 .. wordEnd];
}


I think a takeWhile (similar to a Python itertools function) is able to replace it:

return s.takeWhile!(c => !"\n\r".canFind(c));


Using the current Phobos (but a benchmark shows with DMD it's slower):

const(char)[] findWord(const char[] s) pure /*nothrow*/ @safe {
    immutable wordEnd = s.countUntil!q{a == '\n' || a == '\r'}();
    return s[0 .. wordEnd >= 0 ? wordEnd : $];
}

Bye,
bearophile
February 16, 2013
On 5-2-2013 23:44, bearophile wrote:
>> Jos van Uden:

>>> Partial translation of the universal_turing_machine-Ruby:
>>> http://codepad.org/nUXLzAg2
>>
>> I'd have to first read up on the subject.
>
> It's a simple task, just to implement an universal Turing machine. It's a matter of finding a balance between the too much high level Ruby version and a too much C-like version.
> In D a simple way to implement a tape is with two dynamic arrays, one represents all the cells on the right to the starting position, and the other array is used "inverted",
> to represent all the cells on the left of the right position. There are faster solutions, but this is enough for the purposes of Rosettacode.

The Universal Turing Machine is working. I've only tested
with the given tables. I'll try some more tomorrow.

I couldn't get the AA's to nest the way they do in Ruby, so
I had to do it differently.

This task seemed like a good candidate for using an invariant,
but the loop in the run method already checks the state on
every iteration, so I'm not sure what you could check except
to see if all the fields have been initialized perhaps.

It was a fun task.

http://dpaste.dzfl.pl/3caa52e7

February 16, 2013
Jos van Uden:

> The Universal Turing Machine is working.

There are many different ways to solve this Task in D. You can write a very strongly typed Ada-like program, or a weakly typed Ruby-like program. Both have advantages and disadvantages (as years pass I am leaning more toward a stronger static typing, despite I like Python). Your version is more toward the weakly typed end of the spectrum (but not as much as Ruby).

I am now reading your code.

- - - - - - - - - -

This is bad:

void move(in int dir) {
    final switch(dir) {
        case UTM.left: left(); break;
        case UTM.right: right(); break;
        case UTM.stay: stay(); break;
    }
}


"final switche" was introduced in D to increase safety making the code more strongly typed, but there you are relying on a DMD bug, and that piece of code is the opposite of safe. A correct D compiler must refuse your code:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


I have rewritten it like this:

void move(in int dir) {
    switch(dir) {
        case UTM.left:  left();  break;
        case UTM.right: right(); break;
        case UTM.stay:  stay();  break;
        default: assert(0);
    }
}


If you want to write a stronger typed code you can give a name to that enum, and then it's a good idea to use a final switch. But then the associative array "rules" must have Tuples (or structs) as values.

- - - - - - - - - -

> I couldn't get the AA's to nest the way they do in Ruby, so
> I had to do it differently.

I will take a look at this later. Maybe it's a known AA bug.

- - - - - - - - - -

> This task seemed like a good candidate for using an invariant,
> but the loop in the run method already checks the state on
> every iteration, so I'm not sure what you could check except
> to see if all the fields have been initialized perhaps.

Seems good to do, but maybe a pre-condition is enough.

- - - - - - - - - -

Instead of using toString() maybe it's better to add a printTape, and let run() return nothing. I have also converted UTM to a struct, because for this little program it doesn't need to be a class (and there is no need of new).

- - - - - - - - - -

I am not so fond of the D idiom of using general Exceptions, I'd like to use a bit more variety of Phobos-defined exceptions. But in this little program I think using two basic Exception is acceptable.

- - - - - - - - - -

The two casts in your code are bad, generally in D you don't cast to mutable or to immutable, because it's dangerous and unclean. So I will (try to) remove them:


this(ref TuringMachine tm) {
    this.tm = cast(immutable)tm;
    this.head = TapeHead(this.tm);
}

void run() {
    if (this.halted)
        throw new Exception("Machine already halted.");
    auto state = cast()this.tm.initialState;

- - - - - - - - - -

Maybe later I'll write more comments.

Bye,
bearophile
February 16, 2013
> Instead of using toString() maybe it's better to add a printTape, and let run() return nothing. I have also converted UTM to a struct, because for this little program it doesn't need to be a class (and there is no need of new).

I meant the opposite, sorry:

printTape() ==> toString()

Bye,
bearophile
February 16, 2013
On 5-2-2013 20:45, Jos van Uden wrote:
 
> By the way, I think 'Qznc' may want to have a look at 'The dining
> philosophers':
>
> http://rosettacode.org/wiki/Dining_philosophers


 

February 16, 2013
A first revision, do you like the toString?

http://codepad.org/qhH2XpMx

- - - - - - - - - - -

The modified code contains still an enum that gets converted to char and then to int. I am not going to write code like that in my own "production code" :-)

- - - - - - - - - - -

To improve this type soup a bit I suggest to introduce one or more alias for the types of states, etc, like:

alias State = char;

and then use it/them.


static struct TuringMachine {
    char[] symbols;
    char blank;
    char initialState;
    char[] haltStates, runningStates;
    char[][string] rules;
    char[] input;
}

static struct TapeHead {
    const char[] symbols;
    const char blank;
    char[] tape;
    size_t index;
...

- - - - - - - - - - -

Bye,
bearophile