10
\$\begingroup\$

What general tips do you have for golfing in D? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to D (e.g. "remove comments" is not an answer). Please post one tip per answer.

\$\endgroup\$
1
\$\begingroup\$

Look, no parens!

D's functions and template functions can be called as values, methods (won't help), and properties.

I can't believe no one has said this yet. I'll list the ones that save bytes:

  • fun() and fun!()() shorten to fun (assuming there is no variable fun).
  • fun(par) shortens to par.fun (assuming par has no property/method fun, as well as par not being an expression like 5+2).
  • fun!(T)() shortens to fun!T
  • fun!(T)(par) shortens to par.fun!T (assuming par has no property/method fun)

And with objects:

  • new cls() shortens to new cls (More JavaScript anyone?)
  • obj.fun() and obj.fun!()() shorten to obj.fun
  • obj.fun!(T)() shortens to obj.fun!T

One final thing, use old versions. It allows you to use deprecated features that shorten your code. That said, best advice: D isn't good for code-golf. It is a great language, just not for code-golf.

\$\endgroup\$
  • \$\begingroup\$ Accepting for now :) \$\endgroup\$ – cat Dec 27 '16 at 16:56
  • \$\begingroup\$ Yeah, good to know there's still fans of D here. \$\endgroup\$ – Zacharý Dec 27 '16 at 22:38
1
\$\begingroup\$

D is JavaScript.


Obviously not. But, when dealing with float, double and real, nan is a value which must be handled, and, as specified by IEEE 754, NaN does not compare equal with itself.

writeln(double.nan == double.nan); // false

Meaning,

writeln(value!=value); // only true for nan

is way shorter than

import std.math;
writeln(isNaN(value));

Obviously, always use math.isNaN for real code. ;)

\$\endgroup\$
0
\$\begingroup\$

D has type inference and an auto keyword. If the object is not int, then auto is probably shorter.

\$\endgroup\$
  • \$\begingroup\$ Does auto work when building an associative array with the KeyType[ValueType] syntax? \$\endgroup\$ – Alex A. Feb 27 '16 at 23:30
  • \$\begingroup\$ @AlexA. auto asd = ["a":1, "b": 2]; works, but since KeyType[ValueType] would go in the place of the auto keyword, I don't know if that will always work with types for which literals can't be constructed \$\endgroup\$ – cat Feb 27 '16 at 23:39
  • \$\begingroup\$ @AlexA. auto arr = ["a": true, "b": 6]; works, the keys and values must be of compatible types \$\endgroup\$ – cat Feb 28 '16 at 16:43
0
\$\begingroup\$

D is great at method chaining, but:

str.toLower.strip().split("").sort();

is the same as

sort(split(strip(str.toLower),""));

and usually the non-chained one is shorter, which I just realised, which lets me shorten my answer to Manage Trash So :D

\$\endgroup\$
  • \$\begingroup\$ It's those dots \$\endgroup\$ – CalculatorFeline Feb 28 '16 at 1:25
0
\$\begingroup\$

Like C/C++, main can be int or void, but void main(){} will always be shorter than int main(){return my_func_returning_int;}.

\$\endgroup\$
  • \$\begingroup\$ If the question ask to output an integer wouldn't int main(){return output} be shorter? \$\endgroup\$ – andlrc Feb 28 '16 at 1:44
  • \$\begingroup\$ @dev-null if the question asks for a full program writing an integer to stdout then import std.stdio;void main(){write(7);} is what's needed. I doubt a question would mandate the program return a number because many languages can't set return codes \$\endgroup\$ – cat Feb 28 '16 at 1:45
  • \$\begingroup\$ @dev-null however, yes, in that case that it should not be written to stdout but returned, it would be shorter \$\endgroup\$ – cat Feb 28 '16 at 1:45
  • 2
    \$\begingroup\$ Usually you are allowed to return / output the most convenient way for your language. But I guess D only support exit codes from 0-255? \$\endgroup\$ – andlrc Feb 28 '16 at 1:48
  • \$\begingroup\$ @dev-null actually, POSIX only supports exit codes up to 255. I don't know about Windows, but on Unix / Linux an exit code over 255 wraps around, because of overflow. \$\endgroup\$ – cat Feb 28 '16 at 1:50
0
\$\begingroup\$

D, as a multiparadigm (Object Functional) systems programming language, seems to embrace TIMTOWTDI, or There Is More Than One Way To Do It.

Case in point, writing the program's argv:

import std.stdio, std.array, std.algorithm;

void main(string[] args) {
    for(int i=0;i<args.length;writeln(args[i++])){};

    foreach(a;args)writeln(a);

    each!writeln(args);
}

Note the C-style for-loop requires {} as the empty block and will not accept a semicolon or nothing as a blank statement, in this case. Usually, or ; are no-ops.

\$\endgroup\$
  • \$\begingroup\$ Can you use char* in place of string to save a byte? \$\endgroup\$ – Alex A. Feb 28 '16 at 1:36
  • \$\begingroup\$ @AlexA. function D main parameters must be main() or main(string[] args) moreover, char is literally one character, char* is a pointer to literally one character and char[] is an array of character literals (strings are different). D != C || C++ \$\endgroup\$ – cat Feb 28 '16 at 1:40
  • 1
    \$\begingroup\$ OIC. Never used D, just guessing. \$\endgroup\$ – Alex A. Feb 28 '16 at 1:41
0
\$\begingroup\$

D has a few types of C#-style lambda expressions, which can be assigned and stand alone:

(int a,int b)=>a*b;

auto a=(int a,int b)=>a*b;

However, unlike C#, the signature's types are still needed because D doesn't have Haskell-level type inferencing.

https://dlang.org/spec/expression.html#Lambda

\$\endgroup\$
  • \$\begingroup\$ Function templates for golfing the types? T f(T)(T a,T b){return a + b} should infer T as int in f(5); \$\endgroup\$ – fede s. May 5 '16 at 19:35
  • \$\begingroup\$ @fedes. Hello, friend! Yes, you are exactly correct (but I think/hope "untyped" lambdas will be shorter than typed function expressions). \$\endgroup\$ – cat May 5 '16 at 19:48
  • \$\begingroup\$ Ah, ofc! When I decide to take yet another look on D, who do I find? :D I objectively declare you have good taste on languages \$\endgroup\$ – fede s. May 5 '16 at 19:52
  • \$\begingroup\$ @fedes. Aw, why thank you! :P that implies you do too (but I haven't spent enough time in front of Smalltalk, yet anyways :) ) \$\endgroup\$ – cat May 5 '16 at 20:01
0
\$\begingroup\$

Calling a function on an object with no other arguments

reverse(x);

can nearly always be shortened to

x.reverse;

to shave a byte or more.

This is because the . makes the LHS an implicit first argument, and templating lets us choose the right function for the args.

\$\endgroup\$
  • \$\begingroup\$ Dots are good? This is confusing... \$\endgroup\$ – CalculatorFeline Mar 3 '16 at 3:14
  • \$\begingroup\$ @CatsAreFluffy when there are no args. When there's another argument, the x.reverse(y, z) is longer because of the dot \$\endgroup\$ – cat Mar 3 '16 at 14:37
  • 1
    \$\begingroup\$ x.reverse(y,z) and reverse(x,y,z) have the same byte count. \$\endgroup\$ – Zacharý Nov 8 '16 at 21:13
  • \$\begingroup\$ @ZacharyT Uh, yeah... \$\endgroup\$ – cat Nov 8 '16 at 21:36
  • \$\begingroup\$ Were you comparing x.reverse(y, z) to x.reverse? \$\endgroup\$ – Zacharý Nov 8 '16 at 21:44
0
\$\begingroup\$

If the question requires a full program, the module declaration is surprisingly unnecessary.

*cough* Java, anyone? *clears throat* Actually, D's module system is older than Java's.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.