March 05, 2013
Jos van Uden:

> It depends on how you interpret it. The task describes two actions:
> display and append. The question is: does the last sentence refer to
> the append action or to both display and append. I choose to think it
> refers to the append action because that makes more sense.

OK.

- - - - - - - - - - - -

> As for http://rosettacode.org/wiki/Simple_database
>
> You removed the struct that I used to encapsulate the functions.
>
> Aren't these functions now exposed to other modules? I wanted
> them to only be callable from main. The input validation relies
> on that.
>
> At first I had declared them all private, but then I thought it
> would be convenient to put a struct around them and declare it
> private. Maybe there's a better way.

D isn't a pure OOP language, it thankfully supports free functions. Generally structs and classes shouldn't be used if they are not useful (this is well known in the Python community). A struct with just static methods is essentially a namespace. In D modules are namespaces, so there is less need to wrap static functions in a struct.

In this case of the Simple database Task I think this is not a module to be imported, because it has a main. It's a complete program (like other hundreds of D Tasks in Rosettacode) and it's not meant to be imported. So I think wrapping everything in a struct in this case is useless, it just increases the indenting.

Do you agree?

- - - - - - - - - - - -

Extra note: in Rosettacode there are also few tasks meant as modules to be imported and used. They have the main wrapped like this:

version (task_name_main) {
    void main() {
    }
}


Unfortunately in D there is no built-in way to make a module that has a main() when it's compiled as "main module" (or when it's compiled as stand alone) and masks its main() when it's imported by another module. This is done in Python with the "if __name__ == __main__:" idiom. Some people say that a similar idiom is ugly, but it's far better to have such not nice looking but standard idiom, than having nothing and using a nonstandard version() like that.

Bye,
bearophile
March 05, 2013
Jos van Uden:

> Another consideration, I just remembered, was that it avoided
> creating global variables.

Right, that's important, but every rule should be followed with a grain of salt.

First of all in this program there are no global variables, just a global immutable, filename. Global immutables cause far less troubles than global variables.

(In my opinion hard-coding the file name like that is not nice, but for this little program it's acceptable).

And second, this is a very small program. What's bad in a 100_000 lines long program is sometimes acceptable in a 73 cloc lines long program...

Bye,
bearophile
March 05, 2013
On 5-3-2013 1:20, bearophile wrote:
> Jos van Uden:
>
>> It depends on how you interpret it. The task describes two actions:
>> display and append. The question is: does the last sentence refer to
>> the append action or to both display and append. I choose to think it
>> refers to the append action because that makes more sense.
>
> OK.
>
> - - - - - - - - - - - -
>
>> As for http://rosettacode.org/wiki/Simple_database
>>
>> You removed the struct that I used to encapsulate the functions.
>>
>> Aren't these functions now exposed to other modules? I wanted
>> them to only be callable from main. The input validation relies
>> on that.
>>
>> At first I had declared them all private, but then I thought it
>> would be convenient to put a struct around them and declare it
>> private. Maybe there's a better way.
>
> D isn't a pure OOP language, it thankfully supports free functions. Generally structs and classes shouldn't be used if they are not useful (this is well known in the Python community). A struct with just static methods is essentially a namespace. In D modules are namespaces, so there is less need to wrap static functions in a struct.
>
> In this case of the Simple database Task I think this is not a module to be imported, because it has a main. It's a complete program (like other hundreds of D Tasks in Rosettacode) and it's not meant to be imported. So I think wrapping everything in a struct in this case is useless, it just increases the indenting.
>
> Do you agree?

I'm not attached to the struct, but it doesn't feel right to have these
functions publicly accessible. It's a matter of good coding practice.

If I import a module these functions are exposed.


March 05, 2013
Jos van Uden:

> but it doesn't feel right to have these
> functions publicly accessible. It's a matter of good coding practice.
>
> If I import a module these functions are exposed.

I think you can't import this module, because it has a main().

But if you fear that, then I've added "private" to all global identifiers:
http://rosettacode.org/wiki/Simple_database#D

Bye,
bearophile
March 05, 2013
> But if you fear that, then I've added "private" to all global identifiers:
> http://rosettacode.org/wiki/Simple_database#D

I have removed "private" again, because it's bad to program compromises.
This is a complete program, it's not a module, and it's not imported. No need for private things.

Bye,
bearophile
March 05, 2013
On 5-3-2013 2:05, bearophile wrote:
>> But if you fear that, then I've added "private" to all global identifiers:
>> http://rosettacode.org/wiki/Simple_database#D
>
> I have removed "private" again, because it's bad to program compromises.
> This is a complete program, it's not a module, and it's not imported. No need for private things.

// this shouldn't happen

test.d

import simdb;

void fun() {
    auto db = load();
    // etc
    store(db);
}

March 05, 2013
On 5-3-2013 11:45, Jos van Uden wrote:
> On 5-3-2013 2:05, bearophile wrote:
>>> But if you fear that, then I've added "private" to all global identifiers:
>>> http://rosettacode.org/wiki/Simple_database#D
>>
>> I have removed "private" again, because it's bad to program compromises.
>> This is a complete program, it's not a module, and it's not imported. No need for private things.
>
> // this shouldn't happen
>
> test.d
>
> import simdb;
>
> void fun() {
>      auto db = load();
>      // etc
>      store(db);
> }

That can't happen. I really mean:

test.d
 void fun() {
     auto db = load();
     // etc
     store(db);
}

simdb.d

import test;

fun();
 

March 05, 2013
Jos van Uden:

>> // this shouldn't happen
>>
>> test.d
>>
>> import simdb;

If I try to compile something like that my dmd gives me a duplicated main error, or something similar.


> I really mean:
>
> test.d
>  void fun() {
>      auto db = load();
>      // etc
>      store(db);
> }
>
> simdb.d
>
> import test;
>
> fun();

Do you mean that the load and store functions are "private" and should only be called by other functions in the module? (If this is true, then it's enough to mark as module-private those two functions).

Bye,
bearophile
March 05, 2013
On Tuesday, 5 March 2013 at 13:12:49 UTC, bearophile wrote:
> Jos van Uden:
>
>>> // this shouldn't happen
>>>
>>> test.d
>>>
>>> import simdb;
>
> If I try to compile something like that my dmd gives me a duplicated main error, or something similar.

Sorry, that was a wrong example.

>> I really mean:
>>
>> test.d
>> void fun() {
>>     auto db = load();
>>     // etc
>>     store(db);
>> }
>>
>> simdb.d
>>
>> import test;
>>
>> fun();
>
> Do you mean that the load and store functions are "private" and should only be called by other functions in the module? (If this is true, then it's enough to mark as module-private those two functions).

Yes, but I think it would be best to put a private modifier
around the entire code, except main.

private {
  ...
}
March 19, 2013
I was just looking at the Rosetta code for prime decomposition and it seems bugged to me, wanted to make sure as you seem to be the one coordinating these things:

http://rosettacode.org/wiki/Prime_decomposition#D

This will potentially return a 1 in the list of primes which is a bug as 1 isn't prime.