AltME groups: search
Help · search scripts · search articles · search mailing listresults summary
world | hits |
r4wp | 5907 |
r3wp | 58701 |
total: | 64608 |
results window for this page: [start: 56601 end: 56700]
world-name: r3wp
Group: Core ... Discuss core issues [web-public] | ||
Endo: 17-Mar-2011 | Why FORMing a datatype! removes the ! char? We cannot get it back to datatype without adding a ! to the end: to-datatype to-word form integer! ;not working to-datatype to-word join form integer! "!" ;ok is this a bug, if it is by-desing what is the reason to remove "!"? | |
Endo: 17-Mar-2011 | yes MOLD is better use, thank you. I just curious about why FORM removes ! char. I think it prevents to manually remove ! char in this kind of situations: a: 5 reform [a "is an" type? a] >> 5 is an integer | |
Geocaching: 17-Mar-2011 | Hello Just a basic question: when creating or resetting a string! or a block!, should we do a: "" b: [] or is better to do a: copy "" b: copy [] I tend to do the second way... Does it make a difference? If yes, which way is better. Thanks | |
Ladislav: 17-Mar-2011 | This is the difference: >> my-code-a: [a: "" append a #"x"] == [a: "" append a #"x"] >> do my-code-a == "x" >> my-code-a == [a: "x" append a #"x"] >> my-code-b: [b: copy "" append b #"x"] == [b: copy "" append b #"x"] >> do my-code-b == "x" >> my-code-b == [b: copy "" append b #"x"] | |
Geocaching: 17-Mar-2011 | The bahaviour of my-code-a is confusing... What could be the point to do a: "" then? | |
Ladislav: 17-Mar-2011 | E.g. if you want such a behaviour, i.e. if the effect is desired. | |
Group: !REBOL3 Proposals ... For discussion of feature proposals [web-public] | ||
Ladislav: 9-Nov-2010 | not possible to get accepted as a mezzanine because...not possible for a regular programmer to come up with a workaround like this" - why, then, was my CLOSURE constructor accepted? | |
BrianH: 9-Nov-2010 | That was a backport, Ladislav. R2 has more lax standards. We are trying to cut back on that in R3, but R2 is a lost cause. | |
Andreas: 9-Nov-2010 | The disadvantage is that we don't have a function constructor which does not rebind return in the function body. | |
BrianH: 9-Nov-2010 | Agreed, Andreas. I was just saying that a spec option is a better solution to that problem than new datatypes. | |
Andreas: 9-Nov-2010 | Which was meant to imply that we have neither a constructor for closure! nor for function! nor for any other user-definable function type :) | |
BrianH: 9-Nov-2010 | One of the goals of the native changes in R3 is to cut down on the need for arcane workarounds in regular REBOL code. For every arcane workaround that you might see in a mezzanine, you will see the same workaround need to be done over and over again in user code. Usually badly. There have been a host of native changes to make regular REBOL code easier to write and read and cleaner to look at. We even got more of these in the last 3 releases. | |
BrianH: 9-Nov-2010 | Btw, Ladislav, thanks again for the CLOSURE constructor. If you hadn't come up with that great a solution then R2 likely wouldn't have gotten closures at all, and none of the other fake datatypes would have made it in either, which would have been a real tragedy if we missed out on the typeset! stuff. | |
BrianH: 9-Nov-2010 | Strangely enough, when I backported CLOSURE to R2 I had forgotten that you had written a version, but what I came up with ended up being the same code, exactly. So I attribute it to you through my unconscious :) | |
BrianH: 9-Nov-2010 | It is clear *once you accept the idea of dynamic scope*, which is an inherent part of the semantics of all dynamic escape functions. And that limitation is listed as a disadvantage in the same model. | |
BrianH: 9-Nov-2010 | Disadvantage: "Some people seem to question or have trouble understanding dynamic return as a concept, let alone its benefits." | |
BrianH: 9-Nov-2010 | It's a *real* disadvantage. | |
Andreas: 9-Nov-2010 | Definitional scope is a a major part of what makes REBOL usable at all. Like it or not. | |
BrianH: 9-Nov-2010 | I prefer the "Definitional return with an option to not redefine RETURN and EXIT, dynamic return as a fallback" model because it is the most useful. But I would be willing to accept the "Definitional return with an option to not redefine RETURN and EXIT, no dynamic return" model if it becomes the community consensus - it would mean fewer bug reports, at least from users unfamiliar with REBOL, particularly R2. | |
Andreas: 9-Nov-2010 | If you write a USE using the definitional return option it is transparent to both dynamic and (foreign) definitional returns. The caller of USE can therefore decide freely whether to use dynamic or definitional return in a code block passed to USE. | |
Andreas: 9-Nov-2010 | Namely "Dynamic return with a definitional return option". It only solves the issue by requiring pervasive cooperation. Which, in reality, is of course no solution. | |
Andreas: 9-Nov-2010 | In the first model you have a clear separation of concerns: mezzanine-level functions handling foreign code must use definitional return. Callers need not care. | |
BrianH: 9-Nov-2010 | 3 would be less confusing if it didn't use the return: option to specify definitional return. The conflated option with return type is part of what makes it confusing, and the rest comes from bad option naming and having the interactions between the two semantic models be less clear. 4 is a little less confusing because RETURN is more consistent, but it is also less useful for the same reason. | |
BrianH: 9-Nov-2010 | If given a choice I would prefer only a single return type, dynamic or definitional. Definitional would be better, but we could work with either, as long as they have their version of the [throw] option. That means 6 or 1. | |
Andreas: 9-Nov-2010 | 3 has a few advantages listed which are at least on the borderline to being wrong. That obviously hampers the discussion of 3. | |
Andreas: 9-Nov-2010 | Make that: "3 has a _dis_advantage listed, which is borderline wrong." | |
BrianH: 9-Nov-2010 | There, 3 and 4 have been tweaked to be a little better. 3 (and 4 transitively) could use another couple disadvantages listed, but the ones there may be sufficient. | |
Maxim: 10-Nov-2010 | ok, I've read the whole exceptions document and a few (very old!) tickets at least 3 times now. I'll start by being honest and saying that some of this is going a bit deep into some details and I'm pretty sure that I'm not graping all implications. The background for all the discussion hasn't "sinked in" yet, so its a bit hard to be totally conclusive about my evaluation thus far. this being said... when I arrived at 5, i.e. "Definitional return only, with an option to not redefine RETURN and EXIT", it suddently starts making sense overall. 6. seems to be redundant and maybe even harmfull if we keep THROW dynamic. This is scaled with CC#1744 "fixed" and a wider use of THROW, encouraged, since it now allows custom escape/exception modeling by non guru-level Rebolers (and by guru I mean one of 3-4 rebolers on the earth... maybe not even including Carl ;-). this means, that return does one thing, throw does another. they become two completely different things, clear and conscice in all code. the only real issue I have is that we seem to loose return in parse, but if we keep throw dynamic, then that is moot, and we can just use THROW instead. In fact, woudn't that be preferable, since its more accurate? we are pre-empting the parse return and providing our own... which is what throw should be doing ... its more consistent overall. so go ahead rip my arguments appart... it will only help me understand this completely. :-) | |
BrianH: 10-Nov-2010 | So the "return from PARSE rules" thing will only be a problem for R2-style code. Once we do all the other tricks to make it R3-style, we get proper behavior for free :) | |
BrianH: 10-Nov-2010 | Oh, and BREAK/return works in the parens in PARSE rules in R3 - it's a drop-in replacement for most uses of RETURN in those same parens. | |
BrianH: 10-Nov-2010 | Here is Ladislav's Exception proposals page: http://www.rebol.net/wiki/Exception_proposals Everybody who has a proposal chime in! | |
Gregg: 11-Nov-2010 | I made some notes here and there, but can't seem to make time to really think deeply about all this. Consider these thoughts lightly --- The FOREACH trick is clever, but it makes me wonder if things are a bit inverted. Should there be a core binding func that does that service *for* FOREACH and other funcs that need that behavior. Even though it's temporary, should this: if set-word? first words be this: if find words set-word! (behavior alterations and 'values being modified ignored due to temp status of func) TRY/EXCEPT doesn't read particularly well to me, because 'except sounds like you're leaving something out, rather than catching the error. | |
Ladislav: 11-Nov-2010 | Re: "things are a little bit inverted" - yes, I think so, now, the problem may be, that Carl hesitated (maybe still does?) to give us such "low level stuff" | |
Maxim: 11-Nov-2010 | I also think that Carl hesitates to give us lower-level constructs. This has been the historic case, BUT, now that a lot of people are actively contributing and actually producing working concepts, ports, prototypes and stuff, Carl is slowly realizing how usefull it is for *him* to open up on the lower levels of REBOL. the exception/return/throw discusission going on is a good example of this active participation of the community. Obviously, not everyone is willing or able to participate, but in such deep discussions, there is rarelly a huge mass of people anyways. | |
Maxim: 11-Nov-2010 | I really hope that brian, Ladislav and Carl will get together in a possibly heated discussion about all of this. the difference in mindsets is a perfect setup to get the best overall solution. | |
Ladislav: 11-Nov-2010 | For an even more interesting thing - a definitional catch/throw pair (which can be ported to R2) see the Exception_proposals article. Advantage: you do not have to use any name, yet, only the right throw is caught. | |
Maxim: 11-Nov-2010 | yes that is interesting, but /name is usefull for some code patterns like named exceptions. thing is that currently, catch withouth /name does make that impossible afaik. if we built a mezz which re-threw them, afaik, that would change the context and thus make context sensing impossible... though your skill in this type of low-level manipulations might (will? ;) prove me wrong. | |
Maxim: 11-Nov-2010 | ok, what would be the advantage of using a dynamic catch/throw, if any? | |
Ladislav: 11-Nov-2010 | but, sure, you may get a different answer if you ask some fans of dynamic constructs | |
Maxim: 11-Nov-2010 | ok, so its just less complicated to build mezz code with dynamic returns, but that means dropping a few possibilities with definitional ones? | |
Maxim: 11-Nov-2010 | ok, so its easier cause its managed by the core, but that means you can't play around with it within the mezz... is that a better appraisal? | |
Maxim: 11-Nov-2010 | R3 >> probe reduce dynamic [] 3 ** Script error: i word is not bound to a context ** Where: reduce ** Near: reduce dynamic [i i i i] 3 >> probe reduce definitional [] 3 [3 2 1 0] == [3 2 1 0] | |
Ladislav: 11-Nov-2010 | I could show you a similar example with CATCH/THROW, but it would require more code | |
Ladislav: 11-Nov-2010 | Dynamic variables in R3: they are "not bound to a context" when the function is not running. | |
Ladislav: 11-Nov-2010 | (that formulation is a bit unfortunate, meaning, that I would not have used it, but, in essence, it means: "don't ask what the value of dynamic variable is, when the function is not running") | |
Maxim: 11-Nov-2010 | wow, I think you've just illustrated a big part of the issue and you should add the above to your exceptions page. | |
Maxim: 11-Nov-2010 | it does a better job at explaining the underlying issue than the R3 error page IMHO. | |
Maxim: 11-Nov-2010 | I find that the above is a good intruction which makes the "Exception Marker Scoping" more understandable in detail. its not exactly the same, since the error document talks about unwinds, but I feel that the above helps me understand *why* the unwind does what it does. | |
BrianH: 11-Nov-2010 | I really need to fill in the Exceptions page with the real differences and advantages of dynamic and definitional scoping. There are advantages that either has that the other does not. It would be a real loss to not have both in different circumstances. The different circumstances being definitional for returns and dynamic for breaks and throws. | |
Maxim: 11-Nov-2010 | with the above example, I'm thinking about the past discussions and they are starting to make sense in a new light :-) | |
BrianH: 11-Nov-2010 | I have discussed a new page organization strategy for the Exceptions page with Ladislav. As time permits, I will try to reorganize. It will make these issues much more clear. | |
BrianH: 11-Nov-2010 | its just less complicated to build mezz code with dynamic returns - Depends on the code. Some obscure but important things are impossible if you have dynamic returns. Some less-obscure things aren't even defined as a concept if your returns are definitional.. | |
Ladislav: 11-Nov-2010 | A description of the difference between the definitional and dynamic return: *the dynamic return returns to the dynamically closest function (i.e. to the function that was called as the last one) *the definitional return returns to the definitionally closest function (i.e. to the function that was defined as the last one and contained the return in question) | |
Maxim: 11-Nov-2010 | lad, what I mean is that the illustration of the variable issues above helps us realize that there even *is* a dynamic vs definitional distinction. it then allows us to more fully understand the return issues. you might be surprised that I never even realized there where dynamic variables, in the way you present it above. Even if I've grown to understand binding pretty deeply. | |
Maxim: 11-Nov-2010 | in a sense... you can say that I might even begin to understand your guru code now ;-) | |
BrianH: 11-Nov-2010 | Fortunately, functions are built with nested blocks, though that is partly enhanced in R3 by tasking issues. And while loops are also build with nested blocks, BREAK also applies to PARSE, which relies on dynamic scope (and yes, I can point you to mathematical proofs of this, though there's no point), so we still need dynamic BREAK. Dynamic THROW is just a good idea because of all the capabilities that would give us. | |
Ladislav: 11-Nov-2010 | but, nevertheless, there isn't any reasonable defnition of dynamic versus definitional concepts in the article, so I take that as a hint | |
BrianH: 11-Nov-2010 | Absolutely right, Ladislav. There needs to be such a definition, or at least a comparison. I was going to add one. | |
BrianH: 11-Nov-2010 | This would be part of the issues section, so it would be mostly prose. This is part of a strategy to remove most of the prose from the other sections, so there will be more room for examples. | |
Maxim: 11-Nov-2010 | btw, the dynamic variable, just solved a long standing binding problem riddle I had with classed based instantiation of objects in R2. when I had talked to Carl about it at the last devcon, even he couldn't explain it... so its a very nice thing to get "out in the open". | |
Andreas: 11-Nov-2010 | With parse being a dialect on it's own, BREAK in PARSE can be separate from BREAK in loops. So that's not really an argument to keep dynamic BREAK (for loops). | |
BrianH: 11-Nov-2010 | Yes there is: Definitional breaks redefine BREAK to a definitional function, and PARSE relies on BREAK being dynamic because PARSE is inherently and necessarily dynamic and doesn't rebind anything in the parens, nor should it. For that matter, PARSE rules can be reassigned in their productions, so PARSE can't even rely on the rules being the same thing the next time round. | |
Andreas: 11-Nov-2010 | Point is: the behaviour of BREAK in PARSE is not a strong argument at all when considering the behaviour of BREAK in loops. | |
Andreas: 11-Nov-2010 | BREAK in PARSE was added as a nice hack, but it certainly is not the primary functionality of BREAK. | |
BrianH: 11-Nov-2010 | The behavior of BREAK in PARSE is the main reason we can get away with dropping dynamic return. It's a tradeoff - you get dynamic break or dynamic return. | |
BrianH: 11-Nov-2010 | It is becoming abundantly clear that there is more and more need for a comparison section that shows the strengths of dynamic vs. definitional, because people seem to not understand that there are ceratin classes of code and algorithms (parsing, for instance) that can't be expressed with strict lexical scoping. You are giving up a lot when you go definitional, so that better stuff not be as important in the context where you do it. | |
Andreas: 11-Nov-2010 | Would we have a WITH-DYNAMIC we wouldn't need anything else. | |
BrianH: 11-Nov-2010 | It is only because of tasking issues though - otherwise losing dynamic return would be a big deal. | |
BrianH: 11-Nov-2010 | There are some advantages to definitional return as well, so it's a net plus. | |
BrianH: 11-Nov-2010 | Yes, based on varying levels of information. My statement is objective. It is all a tradeoff, and I have not at any point tried to hide the upsides and downsides of both approaches. | |
BrianH: 11-Nov-2010 | And I can use those same proofs to apply to other algorithms with similar characteristics, and *know* that you gain some abilities with definitional scope, and lose others. This is why I know that Ladislav's DO-ALL is a loop, and so not wanting BREAK to apply to it is more of an opinion than something inherent in its nature. But that doesn't mean that the need for that is less. | |
BrianH: 11-Nov-2010 | And yes, I would be satisfied with THROW being dynamic and the rest not. But my *bare minimum* requirement for accepting that is to fix THROW so it actually works properly, and in many ways it doesn't at the moment (all with tickets), and in one way it could work better (also with a ticket). | |
Maxim: 11-Nov-2010 | I've just reread a few things and I now truely understand the deeper intricasies of this whole discussion... (finally ;-) | |
BrianH: 11-Nov-2010 | Please don't take my mentioning of downsides as being a statement of opinion or some kind of taking sides. I only mention them because they are real, and must be considered when picking a certain strategy. Both approaches have plusses and minuses. If you want to make a rational choice then you need to know the issues - otherwise you are just being a fanboy. For instance, I picked the definitional side for returns, without the need for a fallback to dynamic, because of a rational evaluation of the algorithmic style of R3's functions. And it wasn't until I remembered that the tasking issues had already removed the advantages that dynamic scoping has over lexical scoping - we just can't do that stuff as much anymore, so it doesn't matter if we don't try. The same goes for loops, but to a lesser extent - loops aren't affected as much by tasking issues so we can still do code that would benefit from dynamic breaks, but it still might be a worthy tradeoff to avoid needing an option (since we have no such option). But for THROW, especially THROW/name, there are things that you can do with dynamic throw that you *can't* do with definitional, and those things would have great value, so it's a rational choice to make the tradeoff in favor of dynamic. | |
BrianH: 11-Nov-2010 | Well it comes down to this: Functions are defined lexically. Though they are called dynamically, they aren't called until after they have already been bound, definitionally. But as a side effect of tasking, those bindings are stack-relative, and those stacks are task-local. But random blocks of code outside of functions are bound to object contexts, and those are *not* task-local. So that means that the old R2 practice of calling shared blocks of code is a really bad idea in R3 if any words are modified, unless there is some kind of locking or synchronization. This means that those blocks need to be moved into functions if their code is meant to be sharable, which means that at least as far as RETURN and EXIT are concerned, they can be considered lexically scoped. The advantage that we would get from being able to call a shared block of code and explicitly return in that block is moot, because we can't really do that much anymore. This means that we don't lose anything by switching to definitional code that we haven't already lost for other reasons. At least as far as functions are concerned, all task-safe code is definitional. Loops are also defined lexically, more or less, and the rebinding ones are also task-safe because they are BIND/copy'd to a selfless object context that is only used for that one call and thrown away afterwards. And most calls to loops are task-safe anyways because they are contained in functions. However, the LOOP, FORALL, FORSKIP and WHILE loops do not rebind at the moment. We actually prefer to use those particular loops sometimes in R3 code because they can be more efficient than *EACH and REPEAT, because they don't have that BIND/copy overhead. Other times we prefer to use *EACH or REPEAT, in case particular loop fits better, or has high-enough repetitions and enough word references that the 27% overhead for stack-local word reference is enough to be more than the once-per-loop BIND/copy overhead. Since you don't have to move blocks into *loops* to make them task-safe, you can use blocks referred to by word to hold code that would be shared between different bits of code in the same function. This is called manual common subexpression elimination (CSE), and is a common optimization trick in advanced REBOL code, because we have to hand-optimize REBOL using tricks that the compiler would do for us if we were using a compiled language. Also, PARSE rules are often called from loops, and they are frequently (and in specific cases necessarily) referred to by word instead of lexically nested; most of the time these rules can be quite large, maximizing BIND/copy overhead, so you definitely don't want to put the extensive ones in a FOREACH or a closure. Switching to definitional break would have three real downsides: * Every loop would need to BIND/copy, every time the loop is called, including the loops that we were explicitly using because they *don't* BIND/copy. * Code that is not nested in the main loop block would not be able to break from that loop. And code that is nested in the main loop would BIND/copy. * We can in theory catch unwinds, run some recovery code, and send them on their way (hopefully only in native code, see #1521). Definitional escapes might be hard or impossible to catch in this way, depending on how they are implemented, and that would mean that you couldn't recover from breaks anymore. The upside to definitional break would be that you could skip past a loop or two if you wanted to, something you currently can't do. Another way to accomplish that would be to add /name options to all the loop functions, and that wouldn't have the BIND/copy overhead. Or to use THROW or THROW/name. The situation with THROW is similar to that of the non-binding loops, but more so, still task-safe because of functions. But CATCH and THROW are typically the most useful in two scenarios: * Escaping through a lot of levels that would catch dynamic breaks or returns. * Premade custom escape functions that might need to enforce specific semantics. Both of these uses can cause a great deal of difficulty if we switched to definitional throw. In the first case, the code is often either broken into different functions (and thus not nested), or all dumped into a very large set of nested code that we wouldn't want to BIND/copy. Remember, the more levels we want to throw past, the more code that goes into implementing those levels. In the second case definitional throw would usually not work at all because the CATCH and the THROW would contained in different functions, and the code that calls the function wrapping the THROW would not be nested inside the CATCH. So you would either need to rebind every bit of code that called the THROW, or the definitional THROW would need to be passed to the code that wants to call it like a continuation (similar concept). Either way would be really awkward. On the plus side of dynamic (whatever), at least it's easy to catch an unwind for debugging, testing or recovery purposes. For that matter, the main advantage of using THROW/name as the basic operation that developers can use to make custom dynamic escape functions is that we can build in a standard way to catch it and that will work for every custom escape that is built with it. The end to the arms race of break-through and catch. | |
BrianH: 11-Nov-2010 | #1521 is a critical issue btw. We use that facility in DO, for instance. | |
BrianH: 11-Nov-2010 | Yes, that 27% is a measured number, not made up. Not measured recently, but there haven't been any changes in R3 since then that would affect it. | |
BrianH: 11-Nov-2010 | Wouldn't it be great if it was just a matter of opinion? | |
BrianH: 11-Nov-2010 | Definitional (whatever) depends on a BIND to do its work, deep, usually BIND/copy. And that only works on words that are physically in the blocks that you bind, or in blocks that are nested in those blocks, etc. Another block that is outside the block you are binding and referred to by name won't be bound. That is the limit of the definitional approach. | |
BrianH: 11-Nov-2010 | Note that the definitional BIND that functions do when created is *not* a BIND/copy, it modifies. Same thing with closures when they are created, though they also do something like a BIND/copy every time they are called. | |
BrianH: 11-Nov-2010 | 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. Otherwise, nice work :) | |
Maxim: 11-Nov-2010 | btw, for throw/catch, I agree 100%, even after I now, fully understanding the topic. If we lost dynamic throws, trying to make it work *as* a dynamic system is not pragmatic and AFAIK prone to many strange problems, especially if we try to create our own code patterns and would need to decipher cryptic mezzanine code which does some magic. the way I see it, definitional throw/catch really doesn't scale well and doesn't work especially well in collaborative programming if there are multiple trap points with different catch setups. I can see ways this can be a problem, especiallly when code IS NOT bound on purpose like in liquid which uses a class-based model, *specifically* because it allows me to scale a system by at least three orders of magnitude. liquid builds nodes on the fly and generally re-organizes processing on the fly. one system might be building the setup, while another, later will execute it. with definitional throw, this is impossible to make work. | |
BrianH: 11-Nov-2010 | Definitional * has one advantage over dynamic: You can see it in the source. When the program runs the scope is actually dynamic, but you have to use your imagination or a debugger to see it. | |
Ladislav: 12-Nov-2010 | Brian wrote: "BREAK also applies to PARSE, which relies on dynamic scope (and yes, I can point you to mathematical proofs of this, though there's no point)" - I *must* correct this! Parse break is: - neither dynamic - nor definitional it is a third kind: parse break is lexical Here is why: 1) It is stated in the documentation, that "parse break is a keyword", i.e. it it lexically defined to be a keyword of the dialect 2) it is stated in the documentation, that it "breaks out from the nearest loop", which is true, but it the lexical sense again | |
Maxim: 12-Nov-2010 | AFAICT its not lexical since it will properly return to any rule which uses a referenced sub rule via a world as well as a sub-block | |
Ladislav: 12-Nov-2010 | Not to mention, that (break) is not a parse construct, it is actually foreign to parse | |
BrianH: 12-Nov-2010 | Blocks don't have to be nested a: [] b: [a] Not nested, dynamic scope. | |
BrianH: 12-Nov-2010 | The BREAK keyword does not break out of the nearest loop lexically, it breaks out of the nearest in the (PARSE equivalent of the) call chain. It is dynamic in scope, which can easily be demonstrated with ANY, SOME or WHILE with a named rule with a BREAK in it, instead of an inline block. | |
BrianH: 12-Nov-2010 | If you call a rule through a name, you are using dynamic scope. If the rule is inline then it is lexical scope. | |
BrianH: 12-Nov-2010 | You can not refer to structures by name in lexically scoped constructs, when those names are resolved at runtime. Well, you can, but then that becomes a dynamically scoped flow construct. For instance: a: [break] b: [while a] The word 'a is in the lexical scope of b, but the contents of a are in its dynamic scope only if b is used as a parse rule at runtime and a is still assigned that value. So even though the break is a keyword, the scope to which it breaks is the while, which is in b. | |
Ladislav: 12-Nov-2010 | ... I know that Ladislav's DO-ALL is a loop, and so not wanting BREAK to apply to it is more of an opinion than something inherent in its nature. - I was afraid, that the DO-ALL was not a fortunate choice! My original problem with the property illustrated by DO-ALL occurred when I Implemented my PIF (now called CASE for the newcomers), which was not meant to catch any breaks, as is immediately obvious. | |
BrianH: 12-Nov-2010 | It was just a caveat, not a criticism. | |
Ladislav: 12-Nov-2010 | 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 | 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. | |
BrianH: 12-Nov-2010 | 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. | |
BrianH: 12-Nov-2010 | Carl uses the manual CSE trick a lot - I learned to do so from him :) | |
Ladislav: 12-Nov-2010 | {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 | Cool. It's a good hack, and it does a good job of illustrating the overhead of the definitional throw approach. | |
BrianH: 12-Nov-2010 | 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 | If it is more expensive, then there is a question, whether we should not have a less expensive variant... |
56601 / 64608 | 1 | 2 | 3 | 4 | 5 | ... | 565 | 566 | [567] | 568 | 569 | ... | 643 | 644 | 645 | 646 | 647 |