

Hidden treasure in the D standard library - nkurz
http://nomad.so/2014/08/hidden-treasure-in-the-d-standard-library/

======
thinkpad20
I'm curious how D implements memoizing an arbitrary function. To memoize
something, you need to be able to check if it's being called with the same
arguments. But to do that, you need a definition of "same" (i.e., an
equivalence relation). For example, if the argument is a dictionary, is it
considered the same argument only if the pointer is the same, or if the keys
and values are the same, assuming a recursive definition of "same"? Also, you
need a way to store computed values, using the arguments as keys, which for
efficiency would require either an ordering (for a tree) or hashing (for a
hash table) on the arguments. Multiple arguments would further complicate
things. How does this get automated? And for some things, memoization wouldn't
make sense (for example, with function arguments in higher-order functions).
Sensible defaults would take care of most of these things, but it makes me
wonder how they chose to address these things. And is the memo recreated each
time the (outer) function is called, or is it stored for the duration of the
program? Also, how does the type system play with this? What's the type of
`memoize!`?

~~~
andralex
1\. Sheer comparison for equality is used. (It is user definable.) For e.g.
built-in hashes, contents must compare equal.

2\. The store is a hashtable.

3\. Multiple arguments are grouped in a tuple - no major complication.

4\. Where memoization doesn't make sense you'll get a compile-time error
because e.g. comparison for equality is't defined. At least most of the time
:o).

5\. The memory is thread-local.

6\. memoize takes the name of the memoized argument and creates a distinct
type for each memoized function.

TL;DR: business as usual

~~~
delluminatus
> 1\. Sheer comparison for equality is used. (It is user definable.) For e.g.
> built-in hashes, contents must compare equal.

Wow, so if you compare aHash == anotherHash, it doesn't just compare the
references, it actually examines both hashes for content equivalence? That's
fairly unconventional, but probably convenient sometimes.

~~~
andralex
Affirmative. Use "aHash is anotherHash" to compare references.

------
Shorel
Memoization is one the most useful things I learned about in Common Lisp. Glad
to see it in D.

It allows the program to have recursive algorithms with the performance of
optimized for loops.

~~~
blt
Memoization is pretty easy to implement yourself without any special language
support. It's cool to make it part of the standard library but it's not like
some magic sauce. Especially given that D always uses hash tables. In the
Fibonacci example given, a simple array would have much, much better
performance.

~~~
repsilat
> In the Fibonacci example given, a simple array would have much, much better
> performance.

When I looked at the output of the hash function in Python for integers a few
weeks ago it looked like the identity function was being used. You'll still
have greater complexity than an array, but I'm not sure how much greater.

------
Zardoz84
I recommend try std.parallelism. I did a test with a n Body simulator and runs
very well on a 15 core machine with a speed up around x13-14 over the serial
version.

[https://github.com/Zardoz89/nBodySim](https://github.com/Zardoz89/nBodySim)

------
tonysuper
The "flag" example could be easily replaced with named parameters. Seems a bit
unnecisary to add a new type for that purpose, unless I'm missing something.

~~~
asterite
You are not missing anything: named parameters would have been a much nicer
choice, but I think they don't want to make the language more complex.

~~~
EvenThisAcronym
Are there any plans to add named arguments a la C# or Python in the future?

~~~
renox
Currently 'the plate is full': D is full of features and many of them are not
finished/polished so I doubt that they will add such kind of feature in the
near future..

------
pyed
Haskell has treasures.

