World: r3wp
[Rebol School] Rebol School
older newer | first last |
BrianH 4-Jan-2009 [1228x3] | This was a backport mezzanine, and for backports the compatibility with R3 is key. You have to do some extra work when writing mezzanine functions that you don't have to do with one-off functions. |
The /into option only ended up adding the overhead of 2 compares (the unless and either, no overhead in the foreach), and one head when taken. The rest of the added code either reduced overhead (preallocation of the output), dealt with errors (like treating any word as an error), or handled compatibility fixes (the if value? stuff). | |
What is the major speed regression? | |
Gregg 4-Jan-2009 [1231] | I don't think it's good that /INTO changes the result to return the tail. |
BrianH 4-Jan-2009 [1232x5] | I am still debating that. It doesn't return the tail, actually, it returns the point after the insert, which if not the tail you otherwise can't know from the outside. The /into option is meant to be usable for chaining. You already have the point of insertion in the form of the reference you passed. You can get the tail and head easily. The only bit of info you can't get is the position after the insertion. |
The /into option is not just for MAP. It is intended to be added to a lot of series generating functions. The point of it is to allow those functions to optionally use INSERT semantics, so that we can make it easier to use buffers in a lot of places for memory savings. It's part of an overall strategy to reduce the memory overhead of REBOL code. INSERT semantics were chosen because INSERT is the most basic function here. CHANGE and APPEND can be implemented with INSERT (and REMOVE, HEAD and TAIL), but not so easily the other way. | |
If you are going to retrofit one series function onto all of the series generation functions, INSERT is the most general. | |
You would tend to use FOO/into using a different usage pattern than FOO. | |
The real benefits come from adding the /into option to REDUCE, COMPOSE, MOLD and FORM. We might add LOAD/into as well, but it remains to be seen whether it provides enough benefit there. | |
Gregg 4-Jan-2009 [1237x2] | I understand. I just think it's bad design to have the same function return a different location in the series based on a refinement. Whether they return the head, tail, or point of change, consistency is the thing. |
Unless, of course, the refinement is called /TAIL or something. :-) | |
BrianH 4-Jan-2009 [1239x4] | It doesn't return the tail. |
Strangely enough, the consistency here will be consistency of the /into option across multiple functions. | |
The /into option follows INSERT semantics. It doesn't return the tail, it returns the point after the insert, for chaining. | |
You already have the start of the insert, and you can get the head and tail. | |
Gregg 4-Jan-2009 [1243] | Again, I understand. And it may be that having /INTO available everywhere--with consistent behavior--will not be a problem. Carl's call. |
BrianH 4-Jan-2009 [1244] | Carl called for this already - that's why I'm doing it :) |
Gregg 4-Jan-2009 [1245] | My point is that it's often hard to remember subtle details like this, and it can screw you up. |
BrianH 4-Jan-2009 [1246x2] | Well, if it works consistently for a dozen functions, you'll find it easier to remember :) |
And then you can just say "use /into" and you will know how it works, regardless of the function. | |
Graham 4-Jan-2009 [1248x2] | Looks like this group has been hijacked! |
Ok, I am going to ask my question too. I have to run a report where I collect data from a number of different functions. Each of the functions runs asynchronously. So, one might return data before another. Not that the order matters. But the user can select from 1 to say 6 data functions/sources. Now since these functions are async, I have to use callbacks to deal with the data once it arrives. What would be the best way of programming this? At the end of this, I then need to do something with the collected data .... ie. generate a graph. | |
Steeve 4-Jan-2009 [1250] | Brian, your last function is 2 time slower (on big series) just to avoid the collision with the 'result var and because you don't want 2 distinct foreach blocks (one for /into, one for default). You also forget to pre-insert void spaces when using the /into option, so that your implementation is incoherent with your initial statement of the need to avoid memory overhead Actually, It's your choices (not the best ones to my mind) so i don't follow you. Finally, i don't see the interest to have not the fastest implementation of map in R2 just to have a strict retrocompatibilty with R3. |
Graham 4-Jan-2009 [1251x2] | Each of those functions I am referring to has their own parameter list. |
I could construct a block of functions, a block of parameters, and a data variable . and feed them to the first function, gradually removing them from the blocks and passing them in the callbacks? | |
Steeve 4-Jan-2009 [1253] | Graham, your functions could append their results in a global result block, so that you just need to loop and wait into that one ? |
Graham 4-Jan-2009 [1254x4] | What happens if the functions fail? I could end up waiting for a while .... |
Ordinarily if I had a couple such functions, I would just call one in the callback of the other. | |
Just that here I don't know how many functions I need to call in advance. | |
OTOH, I have done what you have suggested before .. which is basically turning an async function into a synchronous one by waiting till it finishes by use of a flag of some type. | |
BrianH 4-Jan-2009 [1258] | Steeve, the function was not added for the /innto option, it was added for unset! skipping, which needs to be done all the time. |
Steeve 4-Jan-2009 [1259] | the result stack could receive some messages too, to know the current status (your flag), you could throw errors in the result stack too |
BrianH 4-Jan-2009 [1260] | Good idea about preallocating for the /into option though., |
Steeve 4-Jan-2009 [1261] | Brian, is the R3 map function dealing with unset! values too ? |
BrianH 4-Jan-2009 [1262] | Yes. |
Steeve 4-Jan-2009 [1263] | ok |
BrianH 4-Jan-2009 [1264x2] | It's not retrocompatibility with R3: R3 is the future, so it's forward compatibility. If it's not forward compatible with R3, it won't get added as a mezzanine to R2. That is a major difference between writing mezzanines and just writing fuunctions. |
I really do want to make it fast though, because slow functions don't get used in optimal code. This is why most of the loop functions from R2 have been converted to natives: The non-native loop functions were getting optimized out of R2 code. | |
Steeve 4-Jan-2009 [1266] | so you could use 2 differrent foreach blocks |
BrianH 4-Jan-2009 [1267] | How would that help? |
Steeve 4-Jan-2009 [1268] | faster when using default map |
BrianH 4-Jan-2009 [1269] | The foreach block isn't affected by the /into option, so the code would be the same. |
Steeve 4-Jan-2009 [1270] | not the same implementation than with /into |
BrianH 4-Jan-2009 [1271] | How so? |
Steeve 4-Jan-2009 [1272x2] | you don't need to use a result var by default, remember |
IIRC, insert tail [], is faster than result: insert result | |
BrianH 4-Jan-2009 [1274x2] | No, you use tail instead, which is slower. The increase in overhead comes from the if value? stuff. |
There is not that much difference between insert tail and res: insert res (ignoring caching issues, tail is faster). The if value? stuff is the big hit though. | |
Steeve 4-Jan-2009 [1276] | hum... |
BrianH 4-Jan-2009 [1277] | That is not optional though. You might find it interesting that I did break compatibility by not backporting a bug :) |
older newer | first last |