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.
9 Answers
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()andfun!()()shorten tofun(assuming there is no variablefun).fun(par)shortens topar.fun(assumingparhas no property/methodfun, as well asparnot being an expression like5+2).fun!(T)()shortens tofun!Tfun!(T)(par)shortens topar.fun!T(assumingparhas no property/methodfun)
And with objects:
new cls()shortens tonew cls(More JavaScript anyone?)obj.fun()andobj.fun!()()shorten toobj.funobj.fun!(T)()shortens toobj.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.
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. ;)
D has type inference and an auto keyword. If the object is not int, then auto is probably shorter.
- \$\begingroup\$ Does
autowork when building an associative array with theKeyType[ValueType]syntax? \$\endgroup\$Alex A.– Alex A.2016-02-27 23:30:14 +00:00Commented Feb 27, 2016 at 23:30 - \$\begingroup\$ @AlexA.
auto asd = ["a":1, "b": 2];works, but sinceKeyType[ValueType]would go in the place of theautokeyword, I don't know if that will always work with types for which literals can't be constructed \$\endgroup\$cat– cat2016-02-27 23:39:03 +00:00Commented Feb 27, 2016 at 23:39 - \$\begingroup\$ @AlexA.
auto arr = ["a": true, "b": 6];works, the keys and values must be of compatible types \$\endgroup\$cat– cat2016-02-28 16:43:58 +00:00Commented Feb 28, 2016 at 16:43
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
- \$\begingroup\$ It's those dots \$\endgroup\$CalculatorFeline– CalculatorFeline2016-02-28 01:25:51 +00:00Commented Feb 28, 2016 at 1:25
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.
- \$\begingroup\$ Can you use
char*in place ofstringto save a byte? \$\endgroup\$Alex A.– Alex A.2016-02-28 01:36:20 +00:00Commented Feb 28, 2016 at 1:36 - \$\begingroup\$ @AlexA.
function D main parameters must be main() or main(string[] args)moreover,charis literally one character,char*is a pointer to literally one character andchar[]is an array of character literals (strings are different). D != C || C++ \$\endgroup\$cat– cat2016-02-28 01:40:22 +00:00Commented Feb 28, 2016 at 1:40 - 1\$\begingroup\$ OIC. Never used D, just guessing. \$\endgroup\$Alex A.– Alex A.2016-02-28 01:41:43 +00:00Commented Feb 28, 2016 at 1:41
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.
- \$\begingroup\$ Function templates for golfing the types?
T f(T)(T a,T b){return a + b}should infer T as int inf(5);\$\endgroup\$fede s.– fede s.2016-05-05 19:35:29 +00:00Commented May 5, 2016 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– cat2016-05-05 19:48:39 +00:00Commented May 5, 2016 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.– fede s.2016-05-05 19:52:44 +00:00Commented May 5, 2016 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– cat2016-05-05 20:01:30 +00:00Commented May 5, 2016 at 20:01
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.
Like C/C++, main can be int or void, but void main(){} will always be shorter than int main(){return my_func_returning_int;}.
- \$\begingroup\$ If the question ask to output an integer wouldn't
int main(){return output}be shorter? \$\endgroup\$Andreas Louv– Andreas Louv2016-02-28 01:44:28 +00:00Commented Feb 28, 2016 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– cat2016-02-28 01:45:07 +00:00Commented Feb 28, 2016 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– cat2016-02-28 01:45:40 +00:00Commented Feb 28, 2016 at 1:45
- 3\$\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\$Andreas Louv– Andreas Louv2016-02-28 01:48:08 +00:00Commented Feb 28, 2016 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– cat2016-02-28 01:50:23 +00:00Commented Feb 28, 2016 at 1:50
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.