Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search

[REBOL] Re: Antwort: Re: WYSIWYG programming

From: holger:rebol at: 25-Oct-2000 10:33

On Wed, Oct 25, 2000 at 02:52:45PM +0100, [Sharriff--Aina--med-iq--de] wrote:
> Very important thread, it is very helpful that so many people on the list > take such matters into consideration. Its just strange that RT seems very > silent about this issue...
As mentioned before, this is because we are extremely busy. I'll make an attempt at a response though. In any case, this should be considered my personal opinion only. It does not represent the official position of REBOL Technologies. Carl, e.g., is much more of an expert in programming languages than I am, and may see some things differently, or place different emphasis. First of all, I consider most of what Ladislav mentioned to be the result of switching pain , difficulties when switching from one language to another one, and adjusting to a different way of thinking. It is easy to keep using paradigms that are common in C or Pascal when switching to REBOL (paradigms such as "code", "variables", "execution" etc.), instead of switching to the REBOL way of thinking. This sometimes gets people into trouble. From the terminology Ladislav used I suspect that this may be the case here, too. See below. Switching pain is not unique to REBOL. It happens almost any time someone switches from any language to any other language. If you ever had to switch from Modula/Pascal to C you probably found that 'a:=""' does not simply become 'a=""', and that in C "if(a=1)" may not do what you want :-). It would be very nice to have "quick quides" such as "REBOL for C programmers", REBOL for Modula programmers or even "REBOL for PERL programmers" (ouch!), which briefly explained the major paradigm differences and specific things to watch out for, e.g. knowing that in REBOL "a: []" does NOT mean "copy an empty block to the variable 'a'". Or the fact that in REBOL arithmetic evaluation is left-to-right, without precedence rules. We may eventually provide such guides, but, you know, limited time... Maybe someone out in the community could write a first draft. I agree with Joel that, in order to become really adept at REBOL, you have to understand some of its concepts (values, references, NO variables !, blocks, contexts, words etc.), but then that is true for any language. Try programming in C without knowing what a pointer is, how to use it, what the difference between a global, a static, an auto or an extern declaration is, or what you need to do to handle strings (doing memory management yourself etc.). In comparison REBOL seems a lot easier, but even with REBOL, if you don't know what words, references, contexts or blocks are you will eventually run into road blocks (no pun intended). Interestingly enough, from our experience users who have never used other languages before often have FEWER problems adjusting to REBOL's way of thinking than experienced programmers. That's probably because experienced programmers tend to skip forewords and introductory chapters in manuals (the "I know that already" syndrome), and don't even realize until much later that they are stuck with a way of thinking that does not fully apply and that tends to make things more difficult for them. To me, this whole issue is about collecting information on what particular areas cause problems for users which backgrounds, and presenting/distributing this information in a way that makes it easier for users to adjust. Now about the particular discussion regarding "self-modifying code" (shudder), and a slight attempt at "re-education" :-). First of all, I appreciate Ladislav's attempt at explaining those "gotchas". I don't fully agree with his explanation or interpretation though :-), for several reasons. Ladislav seems to apply terms that are not really appropriate, such as "self-modifying code" (or even just "code"), "executed code", "code in execution" etc. This is not the REBOL way of thinking, and in some situations it may even make issues more difficult to understand. In REBOL everything is data, so you never have "self-modifying code". A block of data may get evaluated, and in the process even modified, but you start off with data and end up with data. This may seem like unnecessary emphasis on terminology (and I am usually not a stickler for terminology), but you will see the benefits in a minute... Part of the confusion results from a misunderstanding exactly what a: [] means. Some users may intuitively think that a ":" in REBOL is similar to a ":=" in Pascal/Modula, and that "a: []" means "create the variable 'a' and initialize it to an empty block". If they find that the same part of their script later reads a: ["text"] they may assume that something "modified their code", and that "if the statement is executed again the variable 'a' is now assigned to a different value". That is NOT the case. It is incorrect thinking that is leading to a misinterpretation of what is happening. Here is what a: [] really means: First keep in mind, that both the "a:" and the "[]" are within another block, i.e. they are just pieces of data. That means the "[]" is a block that exists before the function is even evaluated. The block was created when the script was first loaded, and at THAT time the block is created empty. When "a: []" is evaluated, a reference from the word "a" to the block following the a: is created. That is ALL that happens. No data is copied, no data is initialized. The effect is that, from that point on, evaluating the word "a" returns the block a is referencing, regardless of its value. That block starts off being empty, but, as with any other block, its value can change. The fact that the block is located inside of another block, which just happens to be a function body, makes no difference. REBOL does not enforce the block to be "constant". If you create a reference to it and then change the block through the reference -- then the block will get changed, even if it was defined inside of a function body. This is not "self-modifying code", but simply "data being modified", which is what programming is all about. The "code" is still the same. When evaluated it creates a reference from the word "a" to the block following the "a:" and it does that same thing every time. The contents of the block may have changed, but it is still the same block, so the evaluation still does the same thing and will always create the same reference. If you really want to compare this to something in other programming languages, then compare it to something like the following in C: char data[16]="abc"; void f(void) { char *a=data; printf("%s\n",a); strcat(a,"1"); } The first time you call the function it prints "abc", the next time "abc1", then abc11 etc., eventually it crashes :-). No self-modifying code here either. Observe how the "a=data" pointer assignment (somewhat similar to reference in REBOL, not 100% though) executes the exact same code every time the function is called. Not strange behavior at all. You could even put the "abc" into the function and make "a" static. Same effect. We need pointers and string manipulation here to "emulate" what REBOL does. That's because "variables" behave differently than "references".
> 2) The current state of REBOL is beginning to remind me of the state > of FORTH when I last used it seriously (mid-80s). One issue that > hindered the growth and acceptance of FORTH was the fact that one > had to understand most of its language-level concepts in terms of > implementation details; to effectively use the language, one had > to understand ALL of the way that ALL of the core was built. I'd > hate to see REBOL suffer the same marginalization.
I don't think users need to know any implementation details of REBOL. The main stumbling block seems to be a conceptual misunderstanding what a "reference" or value is, e.g. compared to a "variable". Knowing how REBOL internally represents a series or a word would not help.
> To use REBOL control structures reliably, one MUST first > understand the significance of copying, deep copying, function > definition, and contexts. I worry about whether this cost is > so high as to prove prohibitive to entry-level REBOL users.
Ladislav suggests deep copying everything. I don't think that is necessary or appropriate (from a performance point of view). Just as you do not want to fork() lots of processes in C only because there is a static variable somewhere in your code. You just need to think about what behavior you want, and what it means in terms of references to data items. Using the example code1: [ i: 0 while [(i: i + 1) <= 5] [ block: [] insert block "text" ] block ] Here "block: []" means "Create a reference to a block embedded in the function body." (the block following "block:"). At the end of the function "block" means evaluate block and return the result , which just happens to be a reference to a block embedded in the function body, because that is what you set the word "block" to. This may not be what you want though. Not only is evaluating "block: []" inside of the while loop redundant (because the reference never changes, so you can just as well do it only once, before the loop, making the code more readable and efficient), but you are also returning a reference to an item inside of your function. The caller would not be free to manipulate it without causing side effects, and different callers would get references to the SAME item every time. THAT is why you should use "copy". "block: copy []" really gives you a NEW empty block, not a reference to an existing block. It means "use the following (empty) block as a template to give me a reference to a new empty block". It is somewhat like the new operator in C++. If it makes things easier to understand, consider "copy []" to be a constructor for a new empty block. Same thing regarding empty strings (or any series in general). Also, always keep in mind that "a: []" creates a reference, but does not copy any data and does not create any new "object"/"entity". That kind of thinking should explain REBOL's behavior quite nicely, without resorting to wild copy/deep workarounds for "self-modifying code" :-). -- Holger Kruse [holger--rebol--com]