Difference between revisions of "Useful Workarounds"
(Created page with "It is sometimes necessary to find workarounds to bugs, compiler limitations and language design issues. Some common use-cases which require workarounds are: __FORCETOC__ == s...") |
|||
Line 28: | Line 28: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Where "ResultType" is the return type of "myDelegate." | Where "ResultType" is the return type of "myDelegate." | ||
+ | |||
+ | A less powerful, more efficient alternative is: | ||
+ | <syntaxhighlight lang="D"> | ||
+ | import std.range; | ||
+ | import std.traits; | ||
+ | import std.typecons; | ||
+ | import std.parallelism; | ||
+ | |||
+ | static auto magic(T)(T tup) | ||
+ | if (isTuple!T && isCallable!(typeof(tup[0])) && T.Types.length > 1) | ||
+ | { | ||
+ | return tup[0](tup[1 ..$]); | ||
+ | } | ||
+ | |||
+ | static auto magicInput(D,R...)(D d, R r) | ||
+ | if (isCallable!D && allSatisfy!(isRandomAccessRange,R)) | ||
+ | { | ||
+ | return repeat(d, zip(r).length).zip(r); | ||
+ | } | ||
+ | |||
+ | auto result = taskPool.amap!(magic)(magicInput(myDelegate,inputRange)); | ||
+ | </syntaxhighlight> | ||
=== reduce === | === reduce === | ||
The workaround for reduce is to replace: | The workaround for reduce is to replace: |
Latest revision as of 08:16, 25 March 2014
It is sometimes necessary to find workarounds to bugs, compiler limitations and language design issues.
Some common use-cases which require workarounds are:
std.parallelism amap & reduce
Due to Issue 5710, you cannot use delegates with amap and reduce. This essentially limits amap & reduce to taking free functions as template parameters.
amap
The workaround for amap is to replace:
import std.parallelism;
auto result = taskPool.amap!(myDelegate)(inputRange);
With:
import std.range: chunks, zip;
import std.parallelism;
auto result = new ResultType[inputRange.length];
auto chunkSize = taskPool.defaultWorkUnitSize(inputRange.length);
auto inputChunks = inputRange.chunks(chunkSize);
auto outputChunks = result.chunks(chunkSize);
foreach (ioChunk; outputChunks.zip(inputChunks).parallel(1))
{
auto inputChunk = ioChunk[1];
auto outputChunk = ioChunk[0];
foreach (i,input; inputChunk)
outputChunk[i] = myDelegate(input);
}
Where "ResultType" is the return type of "myDelegate."
A less powerful, more efficient alternative is:
import std.range;
import std.traits;
import std.typecons;
import std.parallelism;
static auto magic(T)(T tup)
if (isTuple!T && isCallable!(typeof(tup[0])) && T.Types.length > 1)
{
return tup[0](tup[1 ..$]);
}
static auto magicInput(D,R...)(D d, R r)
if (isCallable!D && allSatisfy!(isRandomAccessRange,R))
{
return repeat(d, zip(r).length).zip(r);
}
auto result = taskPool.amap!(magic)(magicInput(myDelegate,inputRange));
reduce
The workaround for reduce is to replace:
import std.parallelism;
auto result = taskPool.reduce!(myDelegate)(seed,inputRange);
With:
import std.range : chunks, frontTransversal, zip;
import std.algorithm : reduce;
import std.parallelism;
auto chunkSize = taskPool.defaultWorkUnitSize(inputRange.length);
auto inputChunks = inputRange.chunks(chunkSize);
auto partialResults = (new ResultType[inputChunks.length]).chunks(1);
foreach (ioChunk; partialResults.zip(inputChunks).parallel(1))
{
auto inputChunk = ioChunk[1];
auto partialResult = ioChunk[0];
partialResult[0] = reduce!(myDelegate)(seed, inputChunk);
}
auto result = partialResults.frontTransversal.reduce!(myDelegate);
Where "ResultType" is the return type of "myDelegate."