World: r3wp
[!REBOL3]
older newer | first last |
BrianH 13-May-2011 [8607] | Yes, I am sure. The different pattern of behavior was why Carl added ++ and --, since he needed something like this for mezzzanine code. |
Geomol 13-May-2011 [8608] | My viewpoint is, that ++ isn't the speedy native, many people would expect. When using ++ on a series, a new series is created. So ++ take one series and produce two, one is the original, which is incremented, the other is the return value, which is the old series position. This isn't very effective from a performance perspective. If my NEXT function was implemented in the current NEXT native, it didn't have to produce another series, if called with a word. This will mean good performance. |
BrianH 13-May-2011 [8609] | ++ doesn't create a new series, it just increments the index of the reference to the same series. |
Geomol 13-May-2011 [8610x2] | Same could be done with many other natives, if they were improved to also take words as arguments. |
It does create a new series: >> b: [a b c] == [a b c] >> same? ++ b b == false (I know, it's the same area of memory, but we have two set of series variables to work on that memory.) | |
BrianH 13-May-2011 [8612] | A series reference fits into a value slot, so returning a reference to the same position doesn't take any more space than returning a reference to a different position. This means that there is nothing to be gained by losing the information. |
Geomol 13-May-2011 [8613x2] | Are you saying, e.g. an integer value take up the same amount of memory as a series ref.? Doesn't sound very effective, but you could be correct. :) |
(Remember a series need info about the area, the head, tail, position.) | |
BrianH 13-May-2011 [8615x2] | ++ and -- return a reference to the previous position in order to lower the need for local temporary variables to save the previous position when you need to. Returning it means that information is not lost. Technically, since ++ and -- are modifying functions they don't need to return anything at all. The only reason they return that information is because it's valuable. |
Yes, an integer takes up the same space as a series ref (though the series itself takes additional space). Though in R3 currently integers are 64bit and series refs are a 32bit pointer and a 32bit offset, so it's not as much of a waste as in R2 where integers are 32bit. For both though, the value slot is 128bit anyways. This is the price you pay for using variants. | |
Geomol 13-May-2011 [8617x2] | This is from R2: >> next b == [b c] >> stats/series == [34304 26141 7434 231 498 497 406] >> next b == [b c] >> stats/series == [34304 26145 7444 231 484 483 409] >> ++ b == [a b c] >> stats/series == [34304 26151 7454 231 468 467 412] >> ++ b == [b c] >> stats/series == [34304 26157 7464 231 452 451 415] You see, NEXT increment BLOCKS (2nd number) by 4 each time. ++ increment it by 6 each time. So ++ take up more memory. |
I think, you assume too much, my young padawan! ;) | |
BrianH 13-May-2011 [8619x2] | In R2, ++ and -- are mezzanines which I wrote, not natives. You are assuming too much :) |
The R2 versions are optimized for R3 compatibility, not for efficiency. They are still efficient for mezzanine implementations of that behavior. | |
Geomol 13-May-2011 [8621] | :) Touchˇ! |
BrianH 13-May-2011 [8622] | On the other hand, I really don't know how to interpretet the results of R2's STATS function, so I'm taking your word for it that the series are created by the ++ calls. Which numbers tell you this? |
Geomol 13-May-2011 [8623] | Got it. Series are 32 bit pointer and 32 bit offset. So no additional space is wasted by having ++ return as it does. |
Henrik 13-May-2011 [8624] | SAME? must work from the same index in the same series: == [a b c] >> same? a next a == false |
Geomol 13-May-2011 [8625x3] | Henrik, yes. I'm trying to point out, that an additional index is created. |
Brian, do ? stats in R2. I read it, as the /series refinement show BLOCKS as the second number. | |
And a block here is a series index. Two blocks can share the same mem area for the actual content of the series. | |
BrianH 13-May-2011 [8628] | The area, head, tail and such attributes of a series are in the series itself, not in the reference to the series. This is good because series references are copied every time they are passed to a function - REBOL is strictly pass-by-value. All return values are copied too. |
Geomol 13-May-2011 [8629] | Makes sense. So the additional mem for the series ref. is on the stack (or whatever data structure is used), and if that area is reused between additional computations, no mem is wasted by ++. Correct? |
BrianH 13-May-2011 [8630] | >> stats/series == [16384 11618 4590 25 151 150 199] >> a: [1 2 3] == [1 2 3] >> stats/series == [16384 11623 4601 25 135 134 202] Only one of those is the new block - the rest are overhead of either the STATS function or of the REPL loop itself, or runtime overhead, or call overhead, or assignment overhead. I'm starting to think that STATS/series isn't very useful. |
Geomol 13-May-2011 [8631] | Yes, stats/series eat 3 blocks each time, it's called. |
BrianH 13-May-2011 [8632x2] | No mem is wasted by ++ that isn't also wasted by NEXT. |
AFAICT, that's no mem at all. | |
Maxim 13-May-2011 [8634x2] | when I look at the extensions model, the references to series are just pointers to a series payload. but the start, *is* part of the reference, not the series data. since values are 128 bits, you can have the pointer to the series and its head in the same value. |
hope this makes sense. | |
BrianH 13-May-2011 [8636x4] | Of course ++ and -- allocate error! values to trigger if they are called incorrectly, and the R2 version does a REDUCE as part of that error triggering call. But that's not the normal case. |
Maxim, a series reference only contains a pointer to the internal series structure and either a pointer to the offset or a 32bit index (Carl could say which). The internal series structure could have a pointer to the start of the series, or it could be a header of the series data itself, depending on which is better for memory allocation. What you see in extensions are marshalled values, not regular R3 stack frames or other value slots. | |
Command call frames are not made up of 128bit values, afaik, they are 64bit unions. | |
As for value slots, not all datatypes use all 128 bits. 32 bits are used for flags, and the payload could be 32 bits (as in char!), 64 bits (series, integer, decimal) or up to 96 bits. The rest is wasted space. The value slots need to be the same size so you can set one of them to a different value without moving the rest in the block if that value is of a different type. | |
Maxim 13-May-2011 [8640x2] | yep. but we don't have the xtra information which links the data in the core, we only get the data. in the extensions, we get a some sort of internal reference to the series and the index. this is how I see it working in the core too. there is ample room for this info in 128 bits. |
so we don't need to be really concerned about the serie *reference* being copied, anytime we play with a value, this happens anyways... as you said, argument calling copies them (lit-word probably refers instead). | |
BrianH 13-May-2011 [8642x3] | Yup, but it's not in that 128 bits because it would cause problems with duplicated data that would need to be updated. The information kept in the value slot is limited for a reason. |
Value slots are copied really often. Everything in them is a potential aliasing problem. | |
Strangely enough, port! values in R3 only use 32 bits for a pointer to the internal port structure. Everything else needs to go into the port structure itself, or else we'd get aliasing problems. We don't even get an offset integer for ports, because of the port model cleanup where all ports are now like R2's direct ports. | |
Geomol 13-May-2011 [8645] | Who knows, what it would take to make REBOL 64 bit? |
BrianH 13-May-2011 [8646] | Well, the value slots would need to be bigger if we want to have both 64bit pointers and 64bit series sizes. If we just had 32bit series sizes then 128bit would be plenty (remember the 32bit flags means that we only have 96 bits for the payload). We could also have 32bit handles to series, adding a layer of indirection, and then have a limit on the number of series, not the size. We already have 64bit integers. |
Geomol 17-May-2011 [8647] | Is it possible to bind a function's body to a new context in R3? In R2, it can be done with bind second :f new-context |
Ladislav 17-May-2011 [8648x2] | Yes |
As follows: f: make function! reduce [spec body] bind body new-context | |
Geomol 17-May-2011 [8650x2] | How? |
ok | |
Ladislav 17-May-2011 [8652] | So, I suppose it is a safety measure: without having the function body available, you cannot do it. |
Geomol 17-May-2011 [8653x2] | I get some errors (under OS X): >> bind 'body o ** Script error: body is not in the specified context >> bind [body] o == [body] >> f 1 ** Script error: a has no value My f, body and o are defined this way: >> f: func [v] body: [v + a] >> o: context [a: 1] |
Hm, I did it wrong, I think, but still doesn't work with: bind body o | |
Ladislav 17-May-2011 [8655] | Still wrong |
Geomol 17-May-2011 [8656] | :) I need a language without BIND! |
older newer | first last |