D as a prototyping language (for C/C++ projects)

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Feb 26 13:26:25 PST 2013


On Tue, Feb 26, 2013 at 10:01:59PM +0100, Jacob Carlborg wrote:
[.[..]
> Return the date from two days ago:
> 
> Ruby on Rails:
> 2.days.ago
> Date.today
> Time.now
> 
> D:
> Clock.currTime - 2.days
> // Not sure how to do the other two in D
> 
> This is not that bad but it's a bit less intuitive. Here we also
> have shortening of "current" which just saves three characters, for
> no reason.

I find the Phobos version more readable, actually. Writing "2.days.ago"
is all neat and clever and everything, but the logician in me protests
at what all those '.'s are referring to, and they do. Code is not
English, and when it pretends to be English, it makes me suspicious that
something is subtle going on that I'm not aware of. And when I'm coding,
that's something I don't like -- I need to have the assurance I know
exactly what's going on. And yes I can learn to parse "2.days.ago"
eventually, but it's just additional mental load for only superficial
convenience.

But YMMV.


> I think it's mostly std.algorithm that is the problem.
> 
> * reduce - The "reduce" function is really weird. It can't be used as
> a property. The signature is:
> 
> reduce!(fun)(seed, range)
> 
> When it should be:
> 
> reduce!(seed, fun)(range)
> 
> And:
> 
> reduce!(fun)(range, seed)

IMHO this is just bikeshedding. I actually find Phobos' order more
intuitive (to me anyway), because the function you're reducing on,
ideally, should be inlined, so it makes sense to pass it as a
compile-time parameter, and the seed value is what you start with, so it
makes sense to have it appear as the first parameter.

But I can see where UFCS will fail to kick in here, which makes it a bit
annoying, I suppose. But reduce was designed before UFCS made it into
DMD.


> * No algorithm functions for associative arrays.

Yeah that area needs some work.


> * tap - Ruby has a really nice function, "tap". In D it would look like:
> 
> T (func, T) (T t)
> {
>     func(t);
>     return t;
> }
> 
> You can do things like:
> 
> Foo foo ()
> {
>     return (new Foo).tap!((f) {
>         f.x = 3;
> 	f.y = 3;
>     });
> }
[...]

Couldn't you use map for this purpose?


On Tue, Feb 26, 2013 at 10:04:50PM +0100, Jacob Carlborg wrote:
> On 2013-02-26 20:52, H. S. Teoh wrote:
> 
> >Do you have any specific examples?
> 
> Some more:
> 
> isBlank and the opposite isPresent. These exists in Ruby on Rails,
> this is my D version:
> 
> https://github.com/jacob-carlborg/mambo/blob/master/mambo/core/core.d
[...]

Unfortunately, on this point I have to disagree.

I find !isBlank much better. Generally, I prefer a more minimal API, but
I suppose people coming from Ruby might expect a more "rich" kind of API
design (caveat: I don't know Ruby). Having too many ways of stating the
same thing makes me wonder if there's some subtle bug lurking somewhere.
What if isPresent is not 100% equivalent to !isBlank? And I don't mean
just hypothetically; I've seen cases of libraries where bugs cause two
supposedly-opposite functions to be not exactly opposite, and then code
starts to depend on the buggy behaviour, causing hidden bugs later when
the code gets fixed, etc.. A lot of unnecessary problems when you could
have just written !isBlank in the first place.

Now, I used to be a Perl fanatic, so I totally understand TIMTOWTDI and
all that, but I think having a separate function just to encode !isBlank
is a bit too extreme.  The language has boolean operators for a reason,
after all.


T

-- 
If you look at a thing nine hundred and ninety-nine times, you are
perfectly safe; if you look at it the thousandth time, you are in
frightful danger of seeing it for the first time. -- G. K. Chesterton


More information about the Digitalmars-d mailing list