www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Chaining std.algorithm

reply John Carter <john.carter taitradio.com> writes:
So I have an array of data...
 struct romanSystemData {
   string digit;
   uint   value;
   ulong  regionIndex;
   ulong  previous;
};

immutable romanSystemData romanSystem[] = [
   {"" ,    0, 0, 0},//0
   {"I",    1, 0, 0},//1 8-7
   {"V",    5, 1, 1},//2 8-6
   {"X",   10, 1, 2},//3 8-5
   {"L",   50, 3, 3},//4 8-4
   {"C",  100, 3, 4},//5 8-3
   {"D",  500, 5, 5},//6 8-2
   {"M", 1000, 5, 6} //7 8-1
];

I'm happy I can use this look up table ...

assert( 10 == find!"(a.digit == b)"( romanSystem, "X").front.value);

Now I'm sure I can use std.algorithm map to convert say a string of
characters "IVXLCDM" into an array [1,5,10,50,100,500,1000]

but somehow D template instantiation syntax is flumoxing me.

When I try use find in map!"find!""" dmd whinges like crazy at me.

How do you nest these things?


-- 
John Carter
Phone : (64)(3) 358 6639
Tait Electronics
PO Box 1645 Christchurch
New Zealand

-- 

------------------------------
This email, including any attachments, is only for the intended recipient. 
It is subject to copyright, is confidential and may be the subject of legal 
or other privilege, none of which is waived or lost by reason of this 
transmission.
If you are not an intended recipient, you may not use, disseminate, 
distribute or reproduce such email, any attachments, or any part thereof. 
If you have received a message in error, please notify the sender 
immediately and erase all copies of the message and any attachments.
Unfortunately, we cannot warrant that the email has not been altered or 
corrupted during transmission nor can we guarantee that any email or any 
attachments are free from computer viruses or other conditions which may 
damage or interfere with recipient data, hardware or software. The 
recipient relies upon its own procedures and assumes all risk of use and of 
opening any attachments.
------------------------------
Dec 15 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/15/2013 08:42 PM, John Carter wrote:

 So I have an array of data...
   struct romanSystemData {
     string digit;
     uint   value;
     ulong  regionIndex;
     ulong  previous;
 };

 immutable romanSystemData romanSystem[] = [
     {"" ,    0, 0, 0},//0
     {"I",    1, 0, 0},//1 8-7
     {"V",    5, 1, 1},//2 8-6
     {"X",   10, 1, 2},//3 8-5
     {"L",   50, 3, 3},//4 8-4
     {"C",  100, 3, 4},//5 8-3
     {"D",  500, 5, 5},//6 8-2
     {"M", 1000, 5, 6} //7 8-1
 ];

 I'm happy I can use this look up table ...

 assert( 10 == find!"(a.digit == b)"( romanSystem, "X").front.value);
The rule is to look for a range (e.g. an array) to be the first argument that is passed to a function. Then, take that parameter out and apply the function to it as if the function is a member function of that range. This is called UFCS (universal function call syntax). For example, since romanSystem is the first argument to the function call find!"(a.digit == b)", write it like this: romanSystem.find!"(a.digit == b)"("X")
 Now I'm sure I can use std.algorithm map to convert say a string of
 characters "IVXLCDM" into an array [1,5,10,50,100,500,1000]

 but somehow D template instantiation syntax is flumoxing me.

 When I try use find in map!"find!""" dmd whinges like crazy at me.

 How do you nest these things?
The good thing is, find and many other std.algorithm functions return ranges themselves. So, when passing those ranges as first arguments to other functions, the same rule applies: foo!F(bar!B(myRange, 'b'), 'f'); becomes (applying the rule from inside out in two steps): 1) foo!F(myRange.bar!B('b'), 'f'); 2) myRange.bar!B('b').foo!F('f'); Ali
Dec 15 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/15/2013 09:46 PM, Ali Çehreli wrote:

 On 12/15/2013 08:42 PM, John Carter wrote:
  > Now I'm sure I can use std.algorithm map to convert say a string of
  > characters "IVXLCDM" into an array [1,5,10,50,100,500,1000]
The following program works. Note that 'result' is a lazy range. You can apply .array to it to convert it to an array eagerly. import std.stdio; import std.algorithm; import std.array; import std.range; struct romanSystemData { string digit; uint value; ulong regionIndex; ulong previous; }; immutable romanSystemData romanSystem[] = [ {"" , 0, 0, 0},//0 {"I", 1, 0, 0},//1 8-7 {"V", 5, 1, 1},//2 8-6 {"X", 10, 1, 2},//3 8-5 {"L", 50, 3, 3},//4 8-4 {"C", 100, 3, 4},//5 8-3 {"D", 500, 5, 5},//6 8-2 {"M", 1000, 5, 6} //7 8-1 ]; void main() { auto result = "IVXLCDM" .map!(a => romanSystem .find!(data => data.digit.equal([ a ])) .front.value); assert(result.equal([1, 5, 10, 50, 100, 500, 1000])); } The following code maintains the digits as chars (instead of strings), which simplified the code a little bit: immutable romanSystemData romanSystem[] = [ {'\0', 0, 0, 0},//0 // <-- digits are char {'I', 1, 0, 0},//1 8-7 // ... ]; Simpler than data.digit.equal([ a ]): auto result = "IVXLCDM" .map!(a => romanSystem .find!(data => data.digit == a) .front.value); Ali
Dec 15 2013
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Monday, 16 December 2013 at 06:07:00 UTC, Ali Çehreli wrote:
 .find!(data => data.digit.equal([ a ]))
Use `std.range.only(a)` instead of `[a]` to avoid allocating GC memory.
Dec 19 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/19/2013 03:45 AM, Jakob Ovrum wrote:
 On Monday, 16 December 2013 at 06:07:00 UTC, Ali Çehreli wrote:
 .find!(data => data.digit.equal([ a ]))
Use `std.range.only(a)` instead of `[a]` to avoid allocating GC memory.
Thanks. That is the second time I see 'only'. Hopefully, it will stick this time. :) Ali
Dec 19 2013
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 16 December 2013 at 04:45:40 UTC, John Carter wrote:
 When I try use find in map!"find!""" dmd whinges like crazy at 
 me.
First of all, you'd need to use: map!`find!""` , since you are nesting strings. As you wrote it, it looks like: map!"find!" ~ "" See the difference ? Second, unfortunately, "find!pred" is not a standalone template. The signature is: find(pred, Range, Args...) If you write "just" "find!pred" dmd doesn't find your match. This is, IMO, a limitation and I am currently working on improving the situation. To work around this, you need to make a "full" call. Use the lambda syntax, as suggested by H.S. Teoh.
Dec 16 2013