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

World: r3wp

[!REBOL3 Proposals] For discussion of feature proposals

Ladislav
12-Nov-2010
[340]
I wanted to invent as a simple example as possible, but I oversimplified, 
obtaining something, that may not be easily justifiable
BrianH
12-Nov-2010
[341x3]
It's cool. Your point was made, and the disadvantages of definitional 
break that you hadn't gotten around to adding to the page yet are 
stated above in that big message.
Btw, have you seen the source that would be used to implement definitional 
return? It would help to know whether they were catchable for debug/test 
purposes.
Debug/test needs a standard way to catch everything, but afaict there 
is no way to do so with definitional return. The same would go for 
the others if they were definitional, but that is less likely for 
the reasons given above. We might just have to live with not being 
able to catch definitional return - it should be easy to control 
the test environment so its return functions don't propagate into 
the test code, so that probably won't be a problem, at least for 
returns.
Ladislav
12-Nov-2010
[344x2]
Loops are also defined lexically,

 - yes, as far as loops with variables are considered, the loop variables 
 are definitional, not dynamic
For variable-less loops the situation is different: not using "private 
variables" they are neither definitional nor dynamic
BrianH
12-Nov-2010
[346x3]
Yup. But I was mostly referring to the standard way the loop functions 
are used. Most loops are mostly made up of nested blocks and such, 
with very little direct DO calls to other blocks by name.
DO (or IF, or ALL, ...) of a block by name tends to only show up 
in advanced code. That code tends to be critical, and we usually 
can't afford to make it non-working, but not many people do that 
level of hand-optimization of their code, mostly because their code 
isn't that speed or size critical, or they don't know how (or they 
don't like that technique). On the other hand, PARSE rules called 
from loops are often referred to by name and are moved physically 
outside of the loops that call them for really good reasons, some 
of which I mentioned above.
Carl uses the manual CSE trick a lot - I learned to do so from him 
:)
Ladislav
12-Nov-2010
[349]
{Ladislav, your definitional throw in the "Definitional CATCH/THROW 
mezzanine pair" section of your page isn't recursion-safe, because 
MAKE function! does a modifying BIND rahter than a non-modifying 
BIND/copy. } - I know that, but, since it is just an example, and,since 
it can be asily updated to copy, I wrote it this way. I can add copying, 
though
BrianH
12-Nov-2010
[350]
Cool. It's a good hack, and it does a good job of illustrating the 
overhead of the definitional throw approach.
Ladislav
12-Nov-2010
[351]
The only difference would be to replace the (block) by (copy/deep 
block)
BrianH
12-Nov-2010
[352]
Right. COPY/deep is expensive for large code blocks, worse than BIND/copy 
(depending on the code). Copy overhead is a big deal.
Ladislav
12-Nov-2010
[353]
If it is more expensive, then there is a question, whether we should 
not have a less expensive variant...
BrianH
12-Nov-2010
[354]
Especially for CATCH. The more useful CATCH is (measured in levels 
skipped) the more code you need to copy.
Ladislav
12-Nov-2010
[355]
(my note was realted to the bind/copy refinement)
BrianH
12-Nov-2010
[356]
The BIND/copy overhead is inherent in definitional scoping, except 
for function and closure creation where it is only a BIND, which 
was happening anyway. That is why definitional return is cost effective
Ladislav
12-Nov-2010
[357x10]
Bind/copy may be inherent, but my not was a reaction to: "COPY/deep 
is expensive for large code blocks, worse than BIND/copy" - which 
may not be desired
Regarding the above suggested example:

a: [break]
b: [while a]


That is really interesting, because if you really test it, you shall 
find out, that it does not break out from WHILE
(it breaks out from A, and there is nothing WHILE can do except A)
c: [3 a]
is similar
you can make sure as follows:
d: [while [a]]
...which proves, that break breaks out from A actually, i.e. from 
the lexically closest construct
Update to the

http://www.rebol.net/wiki/Exception_proposals

article. Changes:


- description of Dynamic versus Definitional return with example 
(the one from the Carl's article is used)

- I am still not sure, whether I should put in the description of 
dynamic versus definitional variables, so, Max, if you think you 
know how would you like it to look, go ahead an put it in
Also, I adjusted the implementation of the definitional Catch/Throw 
pair in R2-like variant to:


- use FUNC instead of MAKE FUNCTION! to have the body (deep) copied
- unset 'throw for localization purposes
BrianH
12-Nov-2010
[367x2]
Yeah, that break thing, I forgot: An interesting thing about PARSE 
was revealed during the course of implementing the parse proposals. 
It turns out that what most people (including me) thought about PARSE 
was wrong. ANY, SOME and WHILE aren't the only loops in PARSE for 
BREAK to break out of: Every rule is a loop. Even rules that don't 
have any iteration or repetition are effectively a LOOP 1. This means 
that while the *scope* of the BREAK operation in PARSE is definitely 
dynamic in its implementation (this also came out in discussions 
with Carl, though it doesn't use the unwind method), it is (afaik) 
impossible to construct a working example of BREAK that demonstrates 
this. I would love it if you could figure out how to write example 
code to prove this, Ladislav, since I've just been taking the author's 
word for it.
It doesn't matter for R2 and R3's implementations of PARSE, but it 
might matter for someone who wants to make a compiler for the PARSE 
dialect (which is at least theoretically possible). That would be 
a really cool project :)
Ladislav
12-Nov-2010
[369]
I guess, that it may be implemented dynamically, but, the way it 
is implemented, makes it indiscernible from lexical. And, finally, 
what matters most is not the implementation, but the behaviour.
BrianH
12-Nov-2010
[370]
Dynamic scope and lexical scope have a lot of overlap. Being different 
in kind doesn't necessarily make them different in practice :)
Ladislav
12-Nov-2010
[371]
So, if the BREAK in Parse actually always breaks out from the lexically 
closest block containing it, the behaviour is lexical, at least that 
is what I think the definition is about.
BrianH
12-Nov-2010
[372]
Of course, that is what makes it possible to consider changing to 
definitional return. If it was too different in practice, it wouldn't 
be an option, too much code would break and too much of the understanding 
of developers would break too.
Ladislav
12-Nov-2010
[373]
...and, the biggest disadvantage of the dynamic return is the opposite 
- the fact, that knowing the lexically closest catching construct 
does not tell you, which construct will be the closest one at run 
time
BrianH
12-Nov-2010
[374]
PARSE operates on dynamic scope, but many of its constructs are affected 
by the closest thing that REBOL has to real lexical scope: nested 
structures. Basically, the only real lexical scope in REBOL is the 
kind you can get from an unbound LOAD. The rest is faked using "definitional" 
processes. And the definitional process is itself dynamic (though 
it is a one-way process, so its scope isn't bounded).
Ladislav
12-Nov-2010
[375]
Right, the main advantage of the definitional approach is, that it 
resembles the lexical case very well, where needed, and only in exceptional 
cases it looks differently
BrianH
12-Nov-2010
[376]
That is true, but not enough - the dynamic transparency proposal 
also has that quality. The main advantage that only definitonal return 
has is that it can do things that dynamic return can't, even with 
transparency. And it does so with almost no added overhead, because 
the functions were getting bound anyway. That is why I support it.
Ladislav
12-Nov-2010
[377x2]
Yes, that looks to me as the main argument to support the definitional 
return as well.
Nevertheless, as you mentioned above, the cost of binding may be 
prohibitive in cases when the block is supposed to be run only once 
(like in case of CATCH), which may indeed be the main reason, why 
to keep dynamic throw.
BrianH
12-Nov-2010
[379]
You don't lose anything that you haven't already lost for other reasons, 
and it is possible (in native code) to build in acceptable workarounds 
for its weaknesses, so there's no significant downside to definitional 
return (except the work Carl would have to do to implement it).
Ladislav
12-Nov-2010
[380]
In the case of BREAK (I mean the one used in the DO dialect now), 
the situation is 50:50, since loops would be bound once, done many 
times anyway, making any slow-down % much smaller, and due to the 
fact, that some loops (as you mentioned earlier too), need to bind 
their bodies anyway
BrianH
12-Nov-2010
[381]
The main reason to keep dynamic throw is that you would (practically) 
lose a lot of capabilities if you lost it; the reason you already 
lost those capabilities for functions don't apply to throws, so it 
would be a real loss.
Ladislav
12-Nov-2010
[382]
(and, that applies to the CONTINUE case as well)
BrianH
12-Nov-2010
[383]
I don't know how much R3 code you've had to optimize, but I've had 
to optimize it a lot. That BIND/copy overhead is significant. It 
takes a *lot* of loop reps to balance it out, more than most code 
needs to do by something like an order of magnitude. It's not 50:50.
Ladislav
12-Nov-2010
[384]
Well, but don't forget about the binding being done anyway, which 
makes the binding time actually negligible
BrianH
12-Nov-2010
[385x3]
Carl has mused that there might be a faster way to do BIND/copy in 
loops. It would be welcomed.
The binding time is *not* done anyway by all loops. It is only done 
by REPEAT and *EACH, and we now often avoid using those functions 
*because* they rebind. REPEAT and *EACH are mostly used for small 
loop code, because of that binding time *and memory use*, which is 
even more significant than time in a lot of cases.
Code optimized to R3's characteristics is *much* more efficient in 
R3 than code optimized for R2. And it look better too (that was one 
of the reasons for a lot of the native changes).
Ladislav
12-Nov-2010
[388]
Well, I do not hesitate to use Foreach or Repeat where appropriate
BrianH
12-Nov-2010
[389]
Nor do I.