r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3]

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!
Ladislav
17-May-2011
[8657]
>> f: make function! reduce [[v] body: [v + a]]
>> o: context [a: 1]
== make object! [
    a: 1
]

>> bind body o
== [v + a]
Geomol
17-May-2011
[8658]
Isn't that the same as my last attemp?
Ladislav
17-May-2011
[8659]
NO
Geomol
17-May-2011
[8660]
:) Need to think.
Ladislav
17-May-2011
[8661]
you *have to* use MAKE FUNCTION!
Geomol
17-May-2011
[8662]
Because FUNC do copy/deep. hmm is this smart?
Ladislav
17-May-2011
[8663x2]
yes
you are protected when using FUNC, while you are allowed to do what 
you want when knowing what you are doing
Geomol
17-May-2011
[8665x2]
What if ... this is radical, but try go with me ... what if block's 
content wasn't bound to any context, when the block is made? And 
then the content is just bound to a context, when and if the block 
is being evaluated (or compiled if a language does that) the first 
time. Doing it this way, words are treated just like any other value 
within the block. They don't hold any other meaning than the words 
themselves. What would the consequences be?
The same could be done with functions, as the function body is just 
a block of data, which may or may not be evaluated (or compiled).
Ladislav
17-May-2011
[8667x2]
What would the consequences be?

 - I do not know, you did not give me enough specifications to be 
 able to guess.
But, my guess is, that if done carefully, such a "change" would be 
indiscernible from the current behaviour.
Geomol
17-May-2011
[8669]
An example:

blk: [a + b]
f: func [blk /local a b] [a: 1 b: 2 do blk]
f blk

If this would work, what other consequences would that have?
Gabriele
17-May-2011
[8670]
Geomol, you want Scheme.
Geomol
17-May-2011
[8671x2]
Gab, doesn't Scheme have such syntax, we don't like?
Seem to have all the paranthesis, Lisp have.
Ladislav
17-May-2011
[8673x2]
This needs some thought, Geomol. Actual example:

f1: closure [/local a][a: 1 [a]]
f2: func [blk /local a][a: 2 do blk]
f3: func [blk /local a][a: 3 do bind blk 'a]

>> f2 f1
== 1

>> f3 f1
== 3
Now tell us, how your preferred code achieving the same result should 
look like.
Geomol
17-May-2011
[8675x2]
I wouldn't have closure, but use object instead (or context, as I 
call them), if that functionality is wanted. And block content isn't 
bound to start with, so if I write:

>> f1: [a]
>> f2: func [blk /local a] [a: 2 do blk]
>> f2 f1
== 2


because 'a' inside f1 is bound to local 'a' in f2, when evaluated. 
If I want another 'a', I could write:


>> context [a: 1 set 'f1 compile [a]]	; f1 will be a block, [a], 
where the 'a' is bound to 'a' in the context
>> f2 f1
== 1

and the last result could be achieved:

>> f3: func [blk /local a] [a: 3 do compile blk]
>> f3 f1
== 3


Calling f3 will be slower, as blk is recompiled each time. This language, 
I illustrate, isn't REBOL, but another with many similarities to 
REBOL, but with a compile function. Maybe kinda the same could be 
achieved in REBOL, if the binding rules was changed, and "compile" 
in my examples above was changed to a "rebind" function.
I need to think it through, if other unwanted consequences is the 
result of this. I'm just wondering, why it's designed as it is in 
REBOL.
Ladislav
17-May-2011
[8677x2]
I wouldn't have closure

 do I understand correctly, that you do want the programmers to enjoy 
 the benefits of having closures?
err, "do not want" is what I wanted to write
Geomol
17-May-2011
[8679]
Well, if function variables is needed, after the function is finished, 
then it can be achieved by putting the function in a context, and 
have the local vars be vars in the context instead. It's simpler, 
I think, to program.