World: r3wp
[Rebol School] Rebol School
older newer | first last |
Steeve 2-Jan-2009 [1062] | i forget the :vars trick, damn... |
Janko 2-Jan-2009 [1063] | at the end you two will have just map: func [ ] [ ] and it will work :) |
Steeve 2-Jan-2009 [1064] | shame on me |
BrianH 2-Jan-2009 [1065x2] | map: func [ {Evaluates a block for each value(s) in a series and returns them as a block.} 'word [word! block!] "Word or block of words to set each time (local)" data [block!] "The series to traverse" body [block!] "Block to evaluate each time" ] [ foreach :word data reduce [:append [] to-paren body] ] |
Try it :) | |
Janko 2-Jan-2009 [1067] | I can just say wow to both |
Steeve 2-Jan-2009 [1068] | that's good |
BrianH 2-Jan-2009 [1069] | Add a [throw] attribute and it will be good enough for a mezzanine :) |
Steeve 2-Jan-2009 [1070] | as i said before Janko, just some instructions, ;-) |
Janko 2-Jan-2009 [1071] | very cool, this would deserve another blogpost |
BrianH 2-Jan-2009 [1072] | I'll post it to DevBase in the R2 section. |
Steeve 2-Jan-2009 [1073x2] | the trick about the no need of an intial copy [] when we use foreach is so cool |
so rebolish | |
Janko 2-Jan-2009 [1075] | and I just wrote the code with double map instead of double foreach and it looks much more elegant ... no collector values no explicit returning then , it would be great if this would be in rebol IMHO |
BrianH 2-Jan-2009 [1076] | Not too much overhead compared to native MAP. We could cut down on memory overhead by preallocating the destination. |
Janko 2-Jan-2009 [1077] | that part [] and to-paren is something I still need to explore and I need to get better understanding of :word 'word .. etc |
Steeve 2-Jan-2009 [1078x2] | Brian, how much would you size the preallocating ? |
half of the intial serie length ? | |
BrianH 2-Jan-2009 [1080] | map: func [ {Evaluates a block for each value(s) in a series and returns them as a block.} 'word [word! block!] "Word or block of words to set each time (local)" data [block!] "The series to traverse" body [block!] "Block to evaluate each time" ] [ foreach :word data reduce [:append make block! either word? word [length? data] [divide length? data length? word] to paren! body] ] |
Steeve 2-Jan-2009 [1081] | humm, really accurate |
BrianH 2-Jan-2009 [1082] | That expression is faster than the reallocations for large data. |
Steeve 2-Jan-2009 [1083] | agree |
BrianH 2-Jan-2009 [1084] | map: func [ [throw] {Evaluates a block for each value(s) in a series and returns them as a block.} 'word [word! block!] "Word or block of words to set each time (local)" data [block!] "The series to traverse" body [block!] "Block to evaluate each time" ] [ foreach :word data reduce [ :append make block! either word? word [length? data] [divide length? data length? word] to paren! body ] ] |
[unknown: 5] 2-Jan-2009 [1085] | I would change the append to insert tail just because it is faster. |
Steeve 2-Jan-2009 [1086] | yep, agreed too |
BrianH 2-Jan-2009 [1087] | Yeah, I forgot that append is mezzanine in R2 :( |
Steeve 2-Jan-2009 [1088] | even shorter with a to-block instead of either: foreach :word data reduce [ :insert :tail make block! divide length? data length? to-block word] to paren! body ] |
BrianH 2-Jan-2009 [1089] | to-block has block copy overhead, but yeah. |
Steeve 2-Jan-2009 [1090x2] | it's just for intialisation... ;-) |
*during | |
btiffin 2-Jan-2009 [1092] | /me quietly files into the lecture hall and sits down as a crowd gathers ... |
BrianH 2-Jan-2009 [1093x2] | I'll profile to see which is faster. We already have block creation overhead with the reduce and to-paren. |
Actually, as overhead goes the to-block would be minimal in comparison :) | |
[unknown: 5] 2-Jan-2009 [1095x2] | But I would go with the more efficient code in that situation since it would be a mezz |
We can care less how long the code is in a mezz as long as it performs at the optimum. | |
Steeve 2-Jan-2009 [1097] | Brian, i wonder what will be the overhead if map was a mezzanine in R3 (you should test that too) ? |
BrianH 2-Jan-2009 [1098x2] | Since the profiling functions are better in R3, I am comparing the differences there. |
The either is faster. | |
[unknown: 5] 2-Jan-2009 [1100x2] | pick is usually faster than either when eithers first argument is logic based. |
which in this case it is | |
Steeve 2-Jan-2009 [1102] | ahah, i was thinking about pick too |
BrianH 2-Jan-2009 [1103] | Yes, but we have to calculate. Let me check that too. |
Steeve 2-Jan-2009 [1104] | but in that cas we have to pre-calculate length? data |
[unknown: 5] 2-Jan-2009 [1105x2] | Yes, I agree, alwasy profile - never assume |
at least when building mezzanines. | |
BrianH 2-Jan-2009 [1107] | I still want to backport the profiler to R2. |
Steeve 2-Jan-2009 [1108] | length? pick reduce [[1] data] word? word but there is an overhead too |
BrianH 2-Jan-2009 [1109] | Here's the fastest version for R2: map: func [ [throw] "Evaluates a block for each value(s) in a series and returns them as a block." 'word [word! block!] "Word or block of words to set each time (local)" data [block!] "The series to traverse" body [block!] "Block to evaluate each time" ] [ head foreach :word data reduce [ :insert :tail make block! either word? word [length? data] [divide length? data length? word] to paren! body ] ] |
Janko 2-Jan-2009 [1110] | btw: python was recieving criticism because guido made it more and more awkward to use functional programming , which wasn't handeled that well previoulsly either. The way you added a powerful (with variable number of params) map that looks like native in other languages really speaks something about a language. Interestingly this article about python also mentions REBOL http://lambda-the-ultimate.org/node/2302 |
BrianH 2-Jan-2009 [1111] | Interesting to see how much optimization expands the code, isn't it? |
older newer | first last |