[REBOL] Re: Storing/loading object functions
Hi, Volker wrote: If class: ... a more efficient way is to use a method-object, like faces do. then you have a-handler: context [ type: a-handler add: func [this increment] [this/value: this/value + increment] ; ^ note we pass 'this explicitely ] a-class: context [handler: a-handler a: none] a-object: make a-class [value: 5] a-object/handler/add a-object 3 the call-syntax is not very handy, but complete /view-styles are based on this system. Usually there is a dispatch-function, so that one can write ao-add: func[this incr][this/handler/add this 3] ao-add a-object 4 see 'do-face in /view, or 'show, which dispatches to face/feel/redraw and does some more work. An universal dispatcher can be written as follows: msg: func [ {simple message dispatcher} [throw] message [block!] ] [ use [this method call] copy/deep [ set [this message] do/next message method: first message message: next message if not path? method [method: to path! method] insert method 'this/handler call: make block! 2 + length? message insert/only call method insert tail call this insert tail call message do call ] ] Instead of writing: a-object/handler/add a-object 3 we can use the above dispatcher and write: msg [a-object add 3] -- Eurotel Data Nonstop - Neomezen pstup na internet ji od 799 K msn! http://www.eurotel.cz/site/cz/servicesAndTariffs/specialOffer.html?list=34995 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Millennium + 1 ...
The Millenium and the Rebol Counting Error. There was a dispute when the Second Millenium of our Julian/Gregorian calendar shall be celebrated. The Millenium in this case shall mean the day, that is two thousand years after the starting day of the calendar. The calendar documentation is stating, that the starting day has been assigned the date 1/1/1 A.D. According to that, the Second Millenium day shall have the date 1/1/2001 A.D. The architect of the Julian calendar used the date 1/1/1 A.D. as the starting date of the calendar. What did the calendar architect do, when he wanted to refer back in time? He used another calendar called the B.C. calendar, that counted the years backwards. The first year of the B.C. calendar was the year immediately preceding the first year of the A.D. calendar. We, knowing zero and the negative numbers, can use A.D. calendar even for the B.C. calendar dates. A conversion table: YEARCONVERTED TO A.D. ** 4 A.D. 4 3 A.D. 3 2 A.D. 2 1 A.D. 1 1 B.C. 0 2 B.C. -1 3 B.C. -2 4 B.C. -3 From the fact, that in Rebol (1/1/0001 - 1) ; == 31/12/ we can observe, that Rebol doesn't use the B.C. calendar, but it rather uses the A.D. calendar even for the days before the start of our calendar. This is simpler and more practical, than the ancient "calendar switching". Now about the Rebol Counting Error. Example: series1: skip [-2 -1 0 1 2] 3; == [1 2] Now we can ask what does the first place of our series contain. The answer is, that the first place of our SERIES1 contains the number 1: pick series1 1 What does the second place of our SERIES1 contain? It contains the number 2: pick series1 2 What does the place 1 B.S. i.e. the first place before the start of the SERIES1 contain? It contains the number 0. This place should be the place number 0 S. (i.e. the place number zero in the SERIES1), as everybody able to count backwards from 1 can find out. The problem is, that the Rebol designer is currently trying to convince us, that it is the place -1 S., as can be seen from: help pick pick series1 0 ; == none pick series1 -1 ; == 0 What do other Rebols think? 2-Jan-0001 - 1 == 1-Jan-0001 1-Jan-0001 - 1 == 31-Dec- So, those who claim 2001 as the start of the new millinnium are wrong, as there was a year 0. At least according to REBOL... (: -- Carl Read [EMAIL PROTECTED] -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with "unsubscribe" in the subject, without the quotes. -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with "unsubscribe" in the subject, without the quotes.
[REBOL] Re: [ANN] time-in-digits.r 1.3.0
Hi Ryan, the statement "within the same exact thousandth of a second" is not correct. The /precise refinement still can get only the system time, so the "granularity" of the time you can get depends on the operating system you use. Some values: OS Granularity Windows 95/98 55 ms Windows NT 10 ms The value for the granularity can be easily computed with my TIME-TICK function, that can be found in http://www.sweb.cz/LMecir/timblk.r Regards Ladislav Hooray! I have updated my 'time-in-digits function so that it can be used with the /precise refinement for 'now. I use 'time-in-digits exhaustively, because it can be used to create sequential session IDs over time and to create sequential file names over time. Because it can now handle the /precise refinement, it is very unlikely you will create the same session ID for multiple connections to a CGI interface (which was a possibility previously since more than one person might submit to CGI within the same exact second. Now there would only be a problem if more than one person might submit to CGI within the same exact thousandth of a second.) -Ryan REBOL [ Title: "Date and time in digits" Date:28-Dec-2000 Name:'time-in-digits Version: 1.3.0 File:%time-in-digits.r Author: "Ryan C. Christiansen" Email: [EMAIL PROTECTED] Owner: "Ryan C. Christiansen" Rights: "Copyright (C) Ryan C. Christiansen 2000" Tabs:4 Language: 'English Purpose: { Convert the date and time into a string of digits. } Comment: { Use this function to create a string of digits denoting the date and time. This is useful, especially for creating sequential session IDs. If used with 'now to create a file name, the newest file will always appear at the end of a directory. } History: [ 1.0.0 [12-June-2000 "posted to rebol.com" "Ryan"] 1.3.0 [28-Dec-2000 "updated for /precise refinement" "Ryan"] ] Category: [util 2] ] time-in-digits: func [ "Convert the date and time from 'now' into a string of digits." sun-dial [date!] "The current date and time from 'now'" ][ year: to-string sun-dial/year month: to-string sun-dial/month if (length? month) 2 [insert month "0"] day: to-string sun-dial/day if (length? day) 2 [insert day "0"] current-time: sun-dial/time hour: to-string current-time/hour if (length? hour) 2 [insert hour "0"] minutes: to-string current-time/minute if (length? minutes) 2 [insert minutes "0"] seconds: to-string current-time/second seconds-rounded: make integer! current-time/second either current-time/second = seconds-rounded [ whole-seconds: seconds partial-seconds: "000" ][ either seconds-rounded = 0 [ whole-seconds: "00" time-string: make string! (reform current-time) split-time: parse/all time-string "." partial-seconds: second split-time ][ either current-time/second = 0 [ whole-seconds: "00" partial-seconds: "000" ][ split-seconds: parse/all seconds "." whole-seconds: first split-seconds partial-seconds: second split-seconds ] ] ] while [(length? whole-seconds) 2][insert whole-seconds "0"] while [(length? partial-seconds) 3][append partial-seconds "0"] rejoin [year month day hour minutes whole-seconds partial-seconds] ] This appears to work until the thousandths-of-a-second value reaches either 1,000 or zero (not sure how REBOL is handling this, which is where the problem lies, I believe.) Probably goes from 999 and roll around to 0, or none. ** Script Error: Out of range or past end ** Where: time-in-digits ** Near: partial-seconds: second split-seconds while [(length? whole-seconds) 2] Probably 'whole-seconds is 'none ? I hope that helps! Andrew Martin ICQ: 26227169 http://members.nbci.com/AndrewMartin/ -- -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with "unsubscribe" in the subject, without the quotes. -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with "unsubscribe" in the subject, without the quotes. -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with "unsubscribe" in the subject, without the quotes.
[REBOL] Rebol von Neumann properties (RIP ifs-for-whomever cont.) Re:(3)
Hi, If I understand your use of the term "evolving language" correctly, back in the 70's we used the term "extensible language" for the same thing (or something quite similar). That term implied that the programmer could: * add new syntactical structures (notation), * add new control structures, * create new datatypes and associated operations, and that having done so, * the extended language would appear as a whole language, without obvious "seams" between the core language and the extensions, and * there should not be a significant performance penalty for using the extensions. Extensible Language seems perfect. I don't think, that an Evolving Language must be able to do something like: a: [append a [+ 1] 1] do a (a von Neumann property - Pure Self Modifying Code), but I do think, that an Evolving language must be able to do: a: create-a-translation-of something do a , which may be described as a von Neumann property of the language too, but this is a code I would like to describe as a provision to understand Something with new syntactic/semantic rules (a new dialect, if you like, but it might not be a new dialect, but a new stage of the original language evolution). I believe I understand the distinction you're drawing here, but I must confess that I don't yet grasp HOW to enforce it without either performance penalties or loss of introspection. For example, if I imagine something like active-thing: load-to-read-only-code data-representation do active-thing ALONG WITH the ability to introspect interesting-property: obtain-state active-thing selector then wouldn't I be able to do this altered-property: mutate interesting-property active-thing: load-to-read-only-code replace/all interesting-property altered-property do active-thing and be right back with self-modification, albeit at a severely lowered performance? Have I missed something? The performance subject is very questionable, IMHO. I would call your sample a WYSIWYG code. Let's try to compare it with Pure SMC like: a: [append a [+ 1] 1] do a Don't you see any difference? If I would like to do it in a WYSIWYG fashion, I would have to write: a: [append a [+ 1] 1] do copy a Let's compare the results: the first case: a: [append a [+ 1] 1] == [append a [+ 1] 1] do a == 1 do a == 2 do a == 3 do a == 4 do a == 5 do a == 6 do a == 8 the second one: a: [append a [+ 1] 1] == [append a [+ 1] 1] do copy a == 1 do copy a == 2 do copy a == 3 do copy a == 4 do copy a == 5 do copy a == 6 do copy a == 7 do copy a == 8 do copy a == 9 do copy a == 10 Regards Ladislav
[REBOL] Rebol Bug-List Re:
Hi, I don't understand, why your mail didn't get through (I received your previous mail normally). Hi, Ladislav. I'm replying through the Rebol list, because my ISP says: Quote This Message was undeliverable due to the following reason: Your message was not delivered because the return address was refused. The return address was '[EMAIL PROTECTED]' /Quote It seems your email service doesn't like me. :-( You wrote (directly to me): How about the bug list organization - all bugs in one file, or a file for every bug? One bug = one file. One file to list them, one file to describe them, and one file to link them all! :-) Apart from sounding like a line from Tolkien, it's a reasonable plan I believe. Suggestions Directories like this: /Core /View /Apache /Command Each of the above having: /New - This is for new bugs. /Fixing - Bugs being fixed (hopefully). /Fixed - For fixed bugs. [Your suggestions here.] How about /Patched? Andrew Martin ICQ: 26227169 http://members.nbci.com/AndrewMartin/ --
[REBOL] Rebol von Neumann properties (RIP ifs-for-whomever cont.) Re:
Hi Joel, I am sorry I wrote my previous post in a way you felt a need to apologize. The fact is, that I was sorry about it right after I sent it. I knew I wasn't totally right about the non-terminating issue. The only problem of your code WRT termination is, that it doesn't terminate for some trivial inputs, such as None supplied as the first argument. [...snip...] REBOL definitely offers expressive power far beyond the reach of most of the current crop of programming languages, and I find it interesting to see just how far that can go. [...snip...] REBOL (as a von Neumann language in the company of Lisp, PROLOG, etc.) gives us the ability to indulge in what I'll call "logical fractals" whose behavior is *SEVERELY* unobvious if we aren't aware of what we're getting into. Now, please hold that thought for a moment, while I draw in one other connection... In an essay (the ninth chapter of his book _Patterns_of_Software_, Rich Gabriel suggests four characteristics which a programming language must have to survive: * Languages are accepted and evolve by a social process, not a technical or technological one. * Successful languages must have modest or minimal computer resource requirements. * Successful languages must have a simple performance model. * Successful languages must not require users [to] have "mathematical sophistication." REBOL succeeds admirably on #2, and we're all working on #1 via this mailing list. #3 is more problematic. I've never seen an "official" model of REBOL semantics, but throughout my involvement with it I've been trying to come up with pieces of one (e.g., my earlier essays on SERIES! values). I still believe that there are many parts of REBOL that could be explained precisely and simply, but others that are not so clear. (Either in my poor head or in fact -- witness the differences in behavior when mutations are applied to BLOCK! versus LIST! values.) #4 is the most "dangerous" to REBOL, in that *EVERY* vNL of which I'm aware -- REBOL included -- requires at some point a fair bit of sophistication to understand, or at least to recognize when one is getting into deep waters. TYING IT ALL TOGETHER (at last!) I suspect that what we (computing folk in general) need before vNL languages in general -- and REBOL in particular -- will be widely accepted is the beginnings of a real grasp on "logical fractals" that let us use their power effectively and (mostly) safely. Of course, one approach is to say "Don't do that at all!" If I take that approach, I begin to wonder why I don't just stick to COBOL! OTOH, if I can begin to get a grip on when and how to use such "monsters" as: * mezzanine-level control constructs, * higher-order functions, * self-modifying, stateful values, * ...etc... I may be able to take advantage of REBOL's power -- using it more effectively -- and be able to explain/communicate its benefits more persuasively -- promoting its success more effectively. I do like the notion of an Evolving Language. That means a language, whose dictionary is easy to enlarge together with its syntactic/semantic rules. All those properties are present in natural languages, like English, etc. To enlarge a language there must be a possibility to speak about the language in the language. As Carl likes to underline, an Evolving Language must be its own metalanguage. I don't think, that an Evolving Language must be able to do something like: a: [append a [+ 1] 1] do a (a von Neumann property - Pure Self Modifying Code), but I do think, that an Evolving language must be able to do: a: create-a-translation-of something do a , which may be described as a von Neumann property of the language too, but this is a code I would like to describe as a provision to understand Something with new syntactic/semantic rules (a new dialect, if you like, but it might not be a new dialect, but a new stage of the original language evolution). Regards Ladislav
[REBOL] Ifs Re:(2)
Hi Joel, I am not glad, that I must disappoint you, but see the following example: a: 1 b: to paren! [to paren! [to paren! [to paren! [a: 0 - a ifs-for-dummies b [negative: ["Negative"] zero: ["Zero"] positive: ["Positive"]] == "Zero" I think, you should read Exception #5 for Word Evaluation of my Rebol/Core User's Guide Comments once again and hope, that this will be interesting even for others... Regards Ladislav P.S. My strong opinion is, that the best you can get is: signed-if: func [ {If positive do positive-block, zero do zero-block, negative do negative-block} [throw] condition [number! char! money! time!] positive-block [block!] zero-block [block!] negative-block [block!] ] [ either positive? condition [do positive-block] [ either negative? condition [do negative-block] [do zero-block] ] ] I am afraid, that Signed-if-for-dummies may become a victim of the GC bug and similar issues, when used recursively... - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Wednesday, October 11, 2000 11:20 PM Subject: [REBOL] Ifs Re: Hi, all... In honor of the newest REBOL book (and for those of us who can't count to three in proper order, such as myself! ;-) and inspired by the keywords feature of Common Lisp, I offer yet another ifs , which doesn't care in which order the actions are specified: a: 1 == 1 ifs-for-dummies a [positive: ["plus"] zero: ["zip"] negative: ["minus"]] == "plus" ifs-for-dummies a [zero: ["zip"] positive: ["plus"] negative: ["minus"]] == "plus" ifs-for-dummies a [negative: ["minus"] zero: ["zip"] positive: ["plus"]] == "plus" whether they are all specified: ifs-for-dummies a [positive: ["biggerthanzero"]] == "biggerthanzero" ifs-for-dummies a [negative: ["smallerthanzero"]] ifs-for-dummies a [zero: ["equaltozero"]] ifs-for-dummies a [zero: ["equaltozero"] positive: ["bigger, again!"]] == "bigger, again!" or whether the selector has unstable side-effects: a: 1 == 1 b: to-paren [a: 0 - a] == (a: 0 - a) ifs-for-dummies b [negative: ["minus"] zero: ["zip"] positive: ["plus"]] == "minus" ifs-for-dummies b [negative: ["minus"] zero: ["zip"] positive: ["plus"]] == "plus" ifs-for-dummies b [negative: ["minus"] zero: ["zip"] positive: ["plus"]] == "minus" ifs-for-dummies b [negative: ["minus"] zero: ["zip"] positive: ["plus"]] == "plus" This new candidate (which will run if evaluated, but not if elected), has a running mate: fortranif: make object! [ positive: [] negative: [] zero: [] selector: 0 compute: func [[throw] selexpr] [ selector: selexpr either positive? selector [ do positive ][ either negative? selector [ do negative ][ do zero ] ] ] ] and a campaign promise: ifs-for-dummies: func [[throw] selexp conseq [block!] /local actor] [ actor: make fortranif conseq actor/compute selexp ] (In case you're wondering, the news coverage of the US election campaigns hasn't affected me at all! "My fellow REBOLians...") -jn- "Coding at the speed of a dummy!" -- ; Joel Neely [EMAIL PROTECTED] 901-263-4460 38017/HKA/9677 REBOL [] print to-string debase decompress #{ 789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC B6F4F574CFC888342AC949CE74B50500E1710C0C2400}
[REBOL] Ifs Re:(4)
Hi, a stupid example: f: func [x [any-type!]] [1] b: to paren! [to paren! [:f]] ifs-for-dummies-who-play-with-fire b [positive: [print "positive"] negative: [print "negative"] zero: [print "zero"]] The result: zero == 1 Regards Ladislav [EMAIL PROTECTED] wrote: Hi Joel, I am not glad, that I must disappoint you, [...] Not at all! It's just that I, being a Bear of Small Brain, find it difficult to give up. I'm very appreciative of the feedback! I've forgotten the source, but recall the saying, "In science, a successful experiment teaches nothing, as only the expected result is obtained. One learns only when an experiment fails, providing a challenge for new thought." Thanks for the excellent teaching! but see the following example: a: 1 b: to paren! [to paren! [to paren! [to paren! [a: 0 - a ifs-for-dummies b [negative: ["Negative"] zero: ["Zero"] positive: ["Positive"]] == "Zero" I think, you should read Exception #5 for Word Evaluation of my Rebol/Core User's Guide Comments once again [...] Have done. and hope, that this will be interesting even for others... I also. Trying yet again, (I'm running the risk of keeping two distinct issues entangled here -- the get-to-the-bottom-of-a-strange-selector puzzle, and the object-for-named-parameters gimmick)... unravel: func [[throw] exp /local val] [ val: exp while [not any[ number? val char? val money? val time? val]] [ val: do val ] val ] signed-choice: make object! [ positive: [] negative: [] zero: [] selector: 0 compute: func [[throw] selexpr] [ selector: unravel selexpr either positive? selector [ do positive ][ either negative? selector [ do negative ][ do zero ] ] ] ] ifs-for-dummies-who-play-with-fire: func [ [throw] selexp conseq [block!] /local actor ][ actor: make signed-choice conseq actor/compute selexp ] After which I can conduct more experiments... c: [{[{[{"-1"}]}]}] == [{[{[{"-1"}]}]}] ifs-for-dummies-who-play-with-fire c [ positive: ["+"] negative: ["-"] zero: ["0"]] == "-" c: [{[{[{"1"}]}]}] == [{[{[{"1"}]}]}] ifs-for-dummies-who-play-with-fire c [ positive: ["+"] negative: ["-"] zero: ["0"]] == "+" c: [{[{[{"2 - 2"}]}]}] == [{[{[{"2 - 2"}]}]}] ifs-for-dummies-who-play-with-fire c [ positive: ["+"] negative: ["-"] zero: ["0"]] == "0" I am afraid, that Signed-if-for-dummies may become a victim of the GC bug and similar issues, when used recursively... I haven't had time to play with that issue, but will do so when I can. Thanks again! -jn-
[REBOL] Ifs Re:(6)
Well, the problem is, that you are trying to disobey the KISS rule. That rule means, that your signed-if-for-dummies should do one thing and do it well. I think, that it should execute the properly chosen block. It shoudn't try to evaluate its first argument at any price, because supplying it is a work for the caller IMO. I am pretty sure, that the code is much more "brittle" and cryptic, than the proper solution, which should work for useful first argument values and not for any garbage. E.g. your solution has the worst possible property of any algorithm: there are some inputs, for which the algorithm doesn't stop. Regards Ladislav Hi, Ladislav, That was severely subtle! (And AFAIAC sounded the death knell on the notion that REBOL is a simple language for non-programmers! ;-) [EMAIL PROTECTED] wrote: Hi, a stupid example: replace read previous-message-in-thread "stupid" "challenging" f: func [x [any-type!]] [1] b: to paren! [to paren! [:f]] ifs-for-dummies-who-play-with-fire b [positive: [print "positive"] negative: [print "negative"] zero: [print "zero"]] The result: zero == 1 Even knowing the dynamic, code=data=code=data... nature of REBOL, I hadn't thought of the possibility of supplying a value that totally changes the evaluation pattern of another bit of code. Of course, this creates a whole new level of threat models for trying to write defenses against potentially hostile external code. At any rate, the following mod seems to close the wormhole: signed-choice: make object! [ positive: [] negative: [] zero: [] selector: 0 compute: func [[throw] selexpr] [ selector: (unravel selexpr) either positive? selector [ do positive ][ either negative? selector [ do negative ][ do zero ] ] ] ] ...allowing... ifs-for-dummies-who-play-with-fire b [ positive: ["+"] negative: ["-"] zero: ["0"] ] == "+" ifs-for-dummies-who-play-with-fire b [ positive: ["+"] negative: ["-"] zero: ["0"] ] == "+" Thanks! -jn-
[REBOL] Open source project Re:(9)
Hi Rebols, ... With regard to the specifics of buglists, knowledge-bases, and specs: I'm for it. But help me out because I don't have the time or peoplepower to do everything for everybody. Like I said: I've been focusing on YOU for four years now. I've had no life, just you. Now, you've got to help me focus on REBOL the company. That is truly the most rewarding path to the future, for all of us. A REBOL as always, -Carl Sassenrath Founder CTO REBOL Technologies If I understood correctly, we should build a bug-list ourselves. I would like to help with that. Where should it reside?
[REBOL] generalities of addresses and values... Re:(4)
Hi, Joel wrote: At this point, one would need to do similar tests for all REBOL datatypes to completely answer your question. The description of copy (with respect to the /deep refinement) leaves the impression that anything under the series! pseudotype would be a "reference", however. For some info you can see: http://www.rebol.org/advanced/mutable.r and http://www.geocities.com/lmecir.geo/evaluation.html Regards Ladislav
[REBOL] Rebol/Core User's Guide
Hi List! Sorry for the length, but some may be interested, I hope... Variables: [Quote] A variable refers to a specific value only within a defined context, such as a block, a function, or an entire program. [End Quote] That seems to be in contradiction with: probe block [a a a] == [a a a] do probe first block a == 1 do probe second block a ** Script Error: a has no value. ** Where: do probe second block do probe third block a == 2 Words: [Quote] For example, -1 and +1 are numbers, not words. [End Quote] The following exceptions to the rule might be interesting: type? probe to word! "-1" -1 == word! type? probe to word! "+1" +1 == word! type? probe to word! "{" { == word! type? probe to word! "[test]" [test] == word! type? probe to word! "@#$%^," @#$%, == word! type? probe to word! { {} == word! type? probe to word! ":a" :a == word! type? probe to word! "a:" a: == word! type? probe to word! "a/v" a/v == word! type? probe to word! "'a" 'a == word! [Quote] Word Format word REBOL's Treatment Evaluates the word. This is the most natural and common way to write words. If the word holds a function, it will be evaluated. Otherwise, the value of the word will be returned. [End Quote] I see the following exceptions to this rule: 1) If the word holds a set-word, the corresponding word is set. 2) If the word holds a lit-word, the corresponding word is returned. 3) If the word holds a path, the path is evaluated and the result of the evaluation is returned. 4) If the word holds a lit-path, the corresponding path is returned. 5) If the word holds a paren, the paren is evaluated and the result of the evaluation is returned. 6) If the word holds a set-path, the corresponding path is set. 7) If the word is unset, an error occurs. Series: page 5-2 [Quote] A series is a set of values organized in a specific order. [End Quote] The problem with this definition is, that it is a little bit incorrect. The reason is as follows: Let's have two mathematical sets: {0} (a set containing zero) and {0,1} (a set containing zero and one). It is obvious, that these are different sets. As opposed to this, it is not a problem to have one Rebol series, that contains only zero and change it to contain both zero and one: series: [0] append series 1 series That is why the correct definition of the series should take into account, that a series is an ordered container used when we want to store/retrieve Rebol values. [Quote] The first position of the block is called its head. [End Quote] This is incorrect, as can be seen here: block: next [1 2 3 4] first block == 2 But: first head block == 1 I would use a little bit different definition: Every series has got a position (an integer number), that can be obtained as follows: index? series Series with position 1 is called head. [Quote] The last position is called tail. [End Quote] I would prefer a more consistent wording, e.g.: A series can have a subseries having a higher position. The smallest possible subseries of a series is a series with the highest possible position containing no elements, which is called its tail. The position of the tail is the length of the head series plus one. page 5-6 [Quote] Now the 'colors variable is resting at the tail of the block. ... print tail? colors false [End Quote] An error, IMO. It should be True. page 5-36 [Quote] Although 'str is a local variable, its string value is global. [End Quote] [My Favourite Wording] Although 'str is a local variable, initialized every time Print-it is evaluated, its string value is contained (or referenced?) in the body of Print-it and therefore persistent as long as Print-it exists, or at least as long, as its body references the string in question. [End My Favourite Wording] The main reason for suggesting the changed formulation is, that a sentence: "... string value is global..." Doesn't have any meaning a common user (e.g. me) could understand. (How can I tell a "global string" from "a local one"?) page 5-64 [Quote] Multiple variables can refer to the same series. [End Quote] The above wording underlines variables, but there are other means how to obtain a series (a function result, e.g. Next Series, an element of another series,...) [My Favourite Wording] Multiple Rebol series can be the subseries of the same head series. [End My Favourite Wording] Scope of Variables page 8-30 REBOL/Core User Guide Version 2.3 [Quote] For example, here is a signed if function that evaluates one of three blocks based on the sign of a conditional value: ifs: func [ "If positive do block 1, zero do block 2, minus do 3" condition block1 block2 block3 ][ if positive? condition [return do block1] if negative? condition [return do block3] return do block2 ] print ifs 12:00 - now/time ["morning"]["noon"]["night"] night [End Quote] The above definition doesn't work correctly, because it doesn't have the Throw attribute. [Corrected version] ifs:
[REBOL] Rebol strings (generalities of...)
A model of Rebol string implementation (written in Java): class RebolStringStorage { char [] storage; int storageLength; int stringLength; } class RebolString { int position; RebolStringStorage storage; } Regards Ladislav
[REBOL] Rebol strings (generalities of...)
Hi, when testing the properties of Rebol strings I came to: a: skip [1 2 3 4 5 6] 3 == [4 5 6] index? a == 4 b: head a == [1 2 3 4 5 6] remove back tail b == [] b == [1 2 3 4 5] remove back tail b == [] b == [1 2 3 4] remove back tail b == [] b == [1 2 3] remove back tail b == [] b == [1 2] index? a ** Script Error: Out of range or past end. ** Where: index? a which seems to be in accordance with the model proposed... Ladislav
[REBOL] Rebol/Core User's Guide Re:(2)
Hi Joel, I knew about that issue, but considered the Throw attribute as absolutely necessary in this case (the chapter follows the one describing Throw/Catch attributes AFAIR). You are right. To be correct, it should have been like this: ifs: func [ {If positive do block 1, zero do block 2, minus do 3} [throw] condition [number!] block1 [block!] block2 [block!] block3 [block!] ] [ either positive? condition [do block1] [ either negative? condition [do block3] [do block2] ] ] Regards Ladislav - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Wednesday, October 11, 2000 5:34 PM Subject: [REBOL] Rebol/Core User's Guide Re: Hi, Ladislav, I haven't finished thinking through all of your comments, but one issue jumped out at me so forcefully that I thought I'd go ahead and comment on it... [EMAIL PROTECTED] wrote: [...snip...] Scope of Variables page 8-30 REBOL/Core User Guide Version 2.3 [Quote] For example, here is a signed if function that evaluates one of three blocks based on the sign of a conditional value: ifs: func [ "If positive do block 1, zero do block 2, minus do 3" condition block1 block2 block3 ][ if positive? condition [return do block1] if negative? condition [return do block3] return do block2 ] print ifs 12:00 - now/time ["morning"]["noon"]["night"] night [End Quote] The above definition doesn't work correctly, because it doesn't have the Throw attribute. [Corrected version] ifs: func [ "If positive do block 1, zero do block 2, minus do 3" [throw] condition block1 block2 block3 ][ either positive? condition [do block1] [ either negative? condition [do block3] [do block2] ] ] print ifs 12:00 - now/time ["morning"]["noon"]["night"] morning [End Corrected Version] It's also incorrect because it assumes that successive uses of the argument calledconditionwill produce identical values! Consider this: a: 1 == 1 b: to-paren [a: 0 - a] == (a: 0 - a) ifs b ["positive"] ["negative"] ["zero"] == "zero" (simply demonstrating, once again, the severe subtlety of REBOL!) -jn- -- ; Joel Neely [EMAIL PROTECTED] 901-263-4460 38017/HKA/9677 REBOL [] print to-string debase decompress #{ 789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC B6F4F574CFC888342AC949CE74B50500E1710C0C2400}
[REBOL] Rebol/Core User's Guide Re:(4)
Hi Joel, you wrote: Hello again, Ladislav, [EMAIL PROTECTED] wrote: Hi Joel, I knew about that issue, but considered the Throw attribute as absolutely necessary in this case... Certainly! I've been reading a fascinating essay by Richard Gabriel on the power (and dangers!) of abstraction, and will likely mutter about that in a later post. You are right. To be correct, it should have been like this: ifs: func [ {If positive do block 1, zero do block 2, minus do 3} [throw] condition [number!] block1 [block!] block2 [block!] block3 [block!] ] [ either positive? condition [do block1] [ either negative? condition [do block3] [do block2] ] ] Well, I was as surprised as you will be by the following behavior: ifs: func [ [{If positive do block 1, zero do block 2, minus do 3} [[throw] [condition [number!] [block1 [block!] [block2 [block!] [block3 [block!] [] [ [either positive? condition [do block1] [ [either negative? condition [do block3] [do block2] [] [] ifs b ["positive"] ["negative"] ["zero"] == "positive" ifs b ["positive"] ["negative"] ["zero"] == "zero" ifs b ["positive"] ["negative"] ["zero"] == "positive" ifs b ["positive"] ["negative"] ["zero"] == "zero I had expected that the argument type check would barf on my little pathological case, but it didn't! You should read exception #5 for word evaluation of my Rebol/Core User's Guide Comments to understand the behaviour. The fact is, that Ifs really gets a number and there is no need to worry about any change during the Ifs evaluation in the case you supplied and, moreover, if Ifs is defined as above, no such bug is lurking behind the scenes. However, I accept fault for typing and hitting "Send" too quickly without explaining my interest in the issue of expressions with side effects. (So no-one has to backtrack in the thread, let me repeat the definitions and usage of a: 1 == 1 b: to-paren [a: 0 - a] == (a: 0 - a) b == -1 b == 1 b == -1 b == 1 for use below) I was actually wondering about allowing a more general type of argument, but writing ifs in such a way as to "freeze" the value with one evaluation, then re-use that frozen, evaluated-once-only value as often as necessary. I tried a little experiment with this variation: ifs: func [[throw] ce b1 b2 b3 /local cf] [ either positive? cf: ce [ do b1 ][ either negative? cf [ do b2 ][ do b3 ] ] ] ifs b ["positive"] ["negative"] ["zero"] == "positive" ifs b ["positive"] ["negative"] ["zero"] == "negative" ifs b ["positive"] ["negative"] ["zero"] == "positive" ifs b ["positive"] ["negative"] ["zero"] == "negative" ifs b ["positive"] ["negative"] ["zero"] == "positive" Aha! This captures the side-effects avoidance nicely. (I think I have permuted the argument list here, but that's irrelevant to the main point I'm pursuing, so I didn't bother to fix that inconsistency.) Notice that the above definition uses cryptic argument names. It also is simply selecting which of the three blocks todoas the chosen activity. Therefore, I expected it to be equivalent to the nicer ifs: func [[throw] cexp pblk zblk nblk /local cval] [ do either positive? cval: cexp [pblk] [ either negative? cval [nblk] [zblk] ] ] so you can imagine my surprise to obtain these results! ifs b ["positive"] ["negative"] ["zero"] == "zero" ifs b ["positive"] ["negative"] ["zero"] == "positive" ifs b ["positive"] ["negative"] ["zero"] == "zero" ifs b ["positive"] ["negative"] ["zero"] == "positive" ifs b ["positive"] ["negative"] ["zero"] == "zero" Well, it appears that do does NOT distribute over evaluation of its argument! Comments welcomed! -jn- -- ; Joel Neely [EMAIL PROTECTED] 901-263-4460 38017/HKA/9677 REBOL [] print to-string debase decompress #{ 789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC B6F4F574CFC888342AC949CE74B50500E1710C0C2400}
[REBOL] Ifs
Hi Rebols, in the case anybody would like to have an as correct and general as possible version of Ifs, here you are: ifs: func [ {If positive do positive-block, zero do zero-block, negative do negative-block} [throw] condition [number! char! money! time!] positive-block [block!] zero-block [block!] negative-block [block!] ] [ either positive? condition [do positive-block] [ either negative? condition [do negative-block] [do zero-block] ] ] Look out! It is necessary to write the arguments in correct order! Regards Ladislav
[REBOL] Re: [REBOL Helpdesk] assigned #4659
Hi Bo, Compare: Example #1: a: [1 2] remove back tail a b: skip a 2 index? b == 2 Example #2: a: [1 2] b: skip a 2 remove back tail a index? b ** Script Error: Out of range or past end. ** Where: index? b From that I am concluding, That Rebol behaviour is inconsistent, because both cases should yield the same result. My suggestion is as follows: old-index?: :index? index?: function [ {Returns the index number of the current position in the series.} series [series! port!] ] [result] [ if error? result: try [old-index? :series] [result: old-index? series: tail :series] result ] Now the result of Example#2: == 2 Andrew could enhance Rebol patches, I think. Regards Ladislav Ladislav, Do you see this as being a bug? If so, why? Also, what behavior would you rather have occur? Awaiting your answer! REBOL Support --
[REBOL] Bug? 'func not really 'func Re:(3)
Hi, [...snip...] I am confused as to why 'copy seems to be evaluating the words in the block it's given. And also why it doesn't show up until after the function is put together. BTW, here's a patch for 'function, to add 'throw-on-error around it, like 'does and 'func have: if not equal? second third :function [catch] [ function: func head insert/only at load mold third :function 2 [catch] compose/deep [ throw-on-error [ (copy/deep second :function) ] ] ] Andrew Martin Falling prey to hypos... ICQ: 26227169 http://members.nbci.com/AndrewMartin/ -- 1) Not Copy, but Func evaluates its spec block to get the datatypes supplied, instead of words. That is why you normally won't see the difference, but look: spec: [a [block!]] type? probe first second spec block! == word! f: func spec [] type? probe first second third :f block! == datatype! Load Mold converts the datatype back to word. 2) Your patch is not advisable in general. The reason: x: 1 y: 0 z: 4 u: 2 f1: does [x / y] f2: does [z / u] trial: func [blk [block!]] [ probe do blk ] trial [f1 f2] Normally yields ** Math Error: Attempt to divide by zero. ** Where: x / y , while transformed-trial: func [[catch] blk [block!]] [ probe throw-on-error blk ] transformed-trial [f1 f2] yields: ** Math Error: Attempt to divide by zero. ** Where: transformed-trial [f1 f2] , which may be useless for debugging. That is why error throwing is advisable sometimes, but sometimes it isn't. Have a look at For source as an example of balanced throwing, although the series bug I discovered still remains unrepaired. Regards Ladislav
[REBOL] polymorphic object/block VWord func - useful in decoding CGI's, etc. Re:
Hi Douglas, a useful function, IMHO. I would suggest a more "goal oriented" approach with the i-alt parameter: i-alt [unset! block!] ; the alternate code to execute ; example code to be executed as alternate case return either value? 'i-alt [do i-alt] [none] Regards Ladislav For your consideration: We are using a function called "vword" as (value of word in block or object) a safe, easy way to get unknown values out of blocks or objects. For instance: We store email/report templates in blocks, but can now safely skip any report details by leaving the items out of the template/blocks or providing a default value to use as a substitute. Another great use for "vword" is when decoding CGI gets or posts. You never really know what is in or out of CGI object, so vword is a safe way to interogate the object and get all the values. Try it out and let me know what you think. REBOL [] ;--- - vword: func [ { Test to see if a certain word is found in a block or object. If so, the value of the word is returned. (Hence, the name vword.) If not, then the alternate value will be used. If the word is not found and no alternate value is supplied, none is returned.} item [block! object!] "The item containing the word you wish to search for." i-word [word!]"The word / attribute you wish to search for." i-alt [any-type!]"The alternate value to use if the word is not found." /local ret ][ either block? item [ if none? ret: select item :i-word [ if (value? 'i-alt) [ret: i-alt] ] ][ either none? ret: in item :i-word [ if (value? 'i-alt) [ret: i-alt] ][ ret: get in item :i-word ] ] return ret ] ;--- - do %/e/scripts/rs/vword.r Script: "Untitled" (none) vword [a "APPLE" b "BANANA" c "CARROT"] 'd "DICED PEACHES" == "DICED PEACHES" vword [a "APPLE" b "BANANA" c "CARROT"] 'a "DICED PEACHES" == "APPLE" vword [a "APPLE" b "BANANA" c "CARROT"] 'b "DICED PEACHES" == "BANANA" vword [a "APPLE" b "BANANA" c "CARROT"] 'c "DICED PEACHES" == "CARROT" vword [a "APPLE" b "BANANA" c "CARROT"] 'e "DICED PEACHES" == "DICED PEACHES" vword [a "APPLE" b "BANANA" c "CARROT"] 'e == none print mold xo make object! [ a: "ABC" b: "BOY" ] vword xo 'a "alpha" == "ABC" vword xo 'c "alpha" == "alpha" vword xo 'c == none vword xo 'c "alpha" == "alpha" vword xo 'b "alpha" == "BOY" Douglas Vos - EDS/GM-BSU Webmaster e-Mail: mailto:[EMAIL PROTECTED]
[REBOL] Joel's technical essay/challenge
Hi, I recently suggested my Rt (Referentially transparent) function, but overlooked, that Joel wanted to have the first element of the path to be an object (or a general Rebol value), not a Rebol word. Here is my next trial: rt: func [ { a referentially transparent way to invoke a path on a given object/function/something Usage: rt [[object 'function 'refinement1 ...] arg1...] } [catch] blk [block!] ] [ do function [] [result1 result2 something] [ throw-on-error [ result1: do/next first blk something: first result1 result2: append copy ['something] reduce second result1 do head change/only copy blk to path! result2 ] ] ] ; Warning - although it seems to work, it is untested against the GC bug! ; (and my personal guess is, that it wouldn't survive) ; Joel's examples: bunchanums: [3 1 35 8 4 5 52 42 19 13 32 43 81 2 6 34 46] tally: make object! [ tot: 0 zero: does [tot: 0] up: func [/by n [number!]] [tot: tot + either by [n] [1]] down: func [/by n [number!]] [tot: tot - either by [n] [1]] now?: does [tot] ] ; example #1: use [evens odds] [ evens: make tally [] odds: make tally [] foreach num bunchanums [ rt [[either even? num [evens] [odds] 'up 'by] num] ] print ["evens:" evens/now? " odds:" odds/now?] ] { Result: evens: 226 odds: 200 } ; example #2: use [diffs] [ diffs: make tally [] foreach num bunchanums [ rt [[diffs either even? num ['up] ['down] 'by] num] ] print ["net sum:" diffs/now?] ] { Result: net sum: 26 } Regards Ladislav
[REBOL] Do/next error handling
Example #1 (correct): block: [1 / 0] do block Result: ** Math Error: Attempt to divide by zero. ** Where: 1 / 0 Example #2 (incorrect): block: [1 / 0] do/next block Result: ** Math Error: Attempt to divide by zero. ** Where: do/next block Regards Ladislav
[REBOL] Who is that grouch? -or- Fun with functions! Re:(10)
Hi, I am prepared to incorporate enhancements you suggest to http://www.rebol.org/advanced/highfun.r Cheers Ladislav BTW, an RT (Referentially Transparent) version of: object/function/refinement1/.../refinementN arg1 ...argN call can be written (using Refined from above URL) as follows: do refined get in object 'function reduce [ 'refinement1 ...'refinementN ] arg1 ...argN (ugly), or, more efficiently (using RT function defined below): rt: function [block [block!]] [blk] [ do head change/only copy block to path! reduce first block ] as: rt [['object 'function 'refinement1 ... 'refinementN] arg1 ... argN] (MUCH more sexy). Happy, Grouchy, and Dopey ;-) I don't think this has been mentioned in this thread yet. Ladislav created a number of the high level functions. Not sure how they stack up in light of the recent benchmarks. But they are worth a look. A set of higher order functions: Accum, Apply, Curry, Composition, Enum, Filter, Map, Mapper, Nargs, Refined http://www.rebol.org/advanced/highfun.r Cheers, Allen K Lazy.. --Snow White Carl, and REBOL dwarves, playing to peer review in a suburb near you!--
[REBOL] Who is that grouch? -or- Fun with functions! Re:(12)
Hi Joel, A set of higher order functions: Accum, Apply, Curry, Composition, Enum, Filter, Map, Mapper, Nargs, Refined http://www.rebol.org/advanced/highfun.r Well, actually, I do have one question (esp. to Ladislav and/or Allen) regarding style. I've noticed both of you using capital letters (e.g., in the list of HOFs above), but haven't figured out the convention by which one decides what is capitalized. Just curious... -jn- that is my "convention", that nobody else uses AFAIK, Allen just (as that lazy... suggests) copied a part of the file IMHO. I do it when speaking about Rebol values to distinguish them and the normal text. Example: a: either b= 1[5] [6] When refering to the code above I am trying to (as consistently as possible) use A as a name for the Rebol integer value stored in the Rebol word 'A (whether it is 5 or 6) as opposed to 'A, which denotes the Rebol word as such. That is why I speak about Refined (Rebol function) and 'Refined (Rebol word). My "convention" differs dramatically from Elan's, (maybe others use that too), because what I call A he usually denotes 'a and what I call 'A he usually denotes a (or A). I think, that from the above description is clear, that either mine, or his "convention" looks as being "inside out" or "upside down". When I wrote a HTML version of my http://www.geocities.com/lmecir.geo/contexts.html, I used a different "convention": I simply used a different font (Courier) for the same purpose instead of initial capital letters, which may be even more readable (I hope). Cheers Ladislav
[REBOL] Transpose Re:(3)
Hi, Andrew wrote: Why capitals? Here's the Transpose function again: Transpose: function [ [catch] "Transposes Matrices" Matrix [block!] ][ Results Width Height Column ][ Results: make block! Width: length? Matrix/1 Height: length? Matrix repeat Index Width [ Column: make block! Width foreach Row Matrix [ insert/only tail Column Row/:Index ] insert/only tail Results Column ] Results ] Note that every word that is defined here is in Title case. Also note that every common word that's in Rebol like 'insert, '/only, 'length? etcetera are in lower case. What's _important_ is signalled by the Title case words. [...snip...] I assume your [catch] was a faster way of addressing this same issue, by simply passing the error resulting from an empty argument list back to the caller. It's a whole lot simpler and catches the error earlier and it runs faster. Andrew Martin Look what happens when I go to sleep! :-) ICQ: 26227169 http://members.nbci.com/AndrewMartin/ -- I would say, that your source is (as long as :make, :block!, :length?, :repeat, :foreach, :insert, :tail are normal, unchanged natives) exactly equivalent to the same function not having [catch] refinement, because there is no Throw for it in the source. Cheers, Ladislav
[REBOL] Transpose Re:(5)
Hi, I don't think, that I can bring any theoretical reasons for preferring one style over the other. I tried both. I must admit, that I liked the style Andrew is evangelizing more and tried to use it exclusively. The difference (for me) has shown itself when I wrote a script having six-page listing. Then I found out, that the orientation in the script using enclosing bracket indentation worsened drastically (for me) against its RT approved version. That is why I am currently using the RT approved version and knowing, that there is a good reason for it. Cheers Ladislav - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, October 07, 2000 12:00 AM Subject: [REBOL] Transpose Re:(4) This is clearly one of those "you say tomato, I say ketchup" issues. Anyone who doesn't like ketchup on his steak (or steak under his ketchup) is welcome to skip this post entirely! -jn- [EMAIL PROTECTED] wrote: Rebol Crew wrote: The contents of a block are indented, but the block's enclosing brackets [] are not. That's because the brackets belong to the prior level of syntax as they define the block, but are not contents of the block. Also it's easier to spot breaks between adjacent blocks when the brackets stand out. I disagree with Carl's reasoning here, but I can cope with it. I prefer the better human readable style like this example: repeat Index Width [ Column: make block! Width foreach Row Matrix [ insert/only tail Column Row/:Index ] insert/only tail Results Column ] I've always understood INdentation as showing what was IN something else. Viewed strictly as a block (i.e. ignoring the fact that I think I know what some of those words mean...) the example above has this shape to my mind's eye (abbreviating a few places -- strictly for space -- and making explicit an enclosing block...): [*] /--^-\ repeat Index Width [*] /---^\ Column: make block! Width foreach Row Matrix [*] append Results Column /-^-\ append Results Column (Those hyphens, carets, asterisks, slashes, and backwardslashes are standing in for the nice pretty lines in my head...) The top level block contains 4 things -- three words and another block. That last block contains 11 things -- the eighth of which is another block. etc... Notice that the contents are UNDER the brackets -- [*] -- that mark the boundaries of the block. Of course, this horizontal layout is not going to work typographically, especially in email, as my lists get longer. So we can rotate it to run vertically. Unfortunately I don't have rotated brackets on my keyboard, so I'll just have to use the same old more-or-less-vertical ones: / repeat / Column: [ | Index | make *- Width | block! ] | [ | Width | *-- foreach \ ] | Row | Matrix | [/ append | *--- Results | ]\ Column | append | Results \ Column Notice that the contents of a block are still under the brackets that mark the block's boundaries (although logical "under" is now geometrically "to the right"). Of course all these overlapping columns of words and lines are a little cluttered (even though more compact) so let's try to declutter by putting contents between the boundaries of their blocks (but still INdenting to make it clear that they are INside the blocks): [ repeat Index Width [ Column: make block! Width foreach Row Matrix [ append tail Column Row/:Index ] append tail Results Column ] ] Now let's remember that we know what these "words" mean. If we do, we'll tend to think of bigger units, perhaps called "phrases", that group words into fewer, bigger chunks. If I do that, I'll have to keep the first word of a new phrase back at the same level that it had before I started "chunking", so I don't lose track of my levels. If one of these phrases includes a block, I may try to write it out all at once. but if it doesn't fit, I'll try to pull the open brace into the line with the rest of the phrase, but leave the content indented with the closing brace "outdented" back to its own level to make it clear that I've come back up/out a level in the structure. [ repeat Index Width [ Column:
[REBOL] Document bug - [catch] There's a catch! Re:
Hi, I am sure, I didn't explain the things as they should have been explained. Here is the example, how the code could look: Transpose: function [ [catch] "Transposes Matrices" Matrix [block!] ] [ Results Width Height Column ] [ throw-on-error [ Results: make block! Width: length? Matrix/1 Height: length? Matrix repeat Index Width [ Column: make block! Width foreach Row Matrix [ insert/only tail Column Row/:Index ] insert/only tail Results Column ] Results ] ] Now an example use: transpose [[1 2 3] [a b c] 3] ** Script Error: Cannot use path on integer! value. ** Where: transpose [[1 2 3] [a b c] 3] Cheers, Ladislav - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED] Sent: Saturday, October 07, 2000 2:00 AM Subject: [REBOL] Document bug - [catch] There's a catch! Joel wrote: I assume your [catch] was a faster way of addressing this same issue, by simply passing the error resulting from an empty argument list back to the caller. Andrew (mistakenly!!) wrote: It's a whole lot simpler and catches the error earlier and it runs faster. Ladislav wrote: I would say, that your source is (as long as :make, :block!, :length?, :repeat, :foreach, :insert, :tail are normal, unchanged natives) exactly equivalent to the same function not having [catch] refinement, because there is no Throw for it in the source. transpose [[1 2 3] [a b c] 3] ** Script Error: Cannot use path on integer! value. ** Where: insert/only tail Column Row/:Index Ladislav, you're right! I've read the manual on this part, Page 268, 8-26 Function Attributes, and it reads: quote If the [catch] attribute is specified, errors that are thrown within the function are caught automatically within the function but (continued on next page) at the point where the function was used. This is useful if you are providing a function library (mezzanine functions) and don't want the error to be displayed within your function, where where it was called: /Quote But it doesn't mention that this _only_ happens if 'throw is used in the body of the function or one of functions the function might call. I've sent this to feedback and docs @ rebol.com so they can fix it up. Andrew Martin Foolishly believing the documentation! :-) ICQ: 26227169 http://members.nbci.com/AndrewMartin/ --
[REBOL] Did you know? - 'Bind is stackable! Re:
Hi, Andrew wrote: Did you know? - 'Bind is stackable! I didn't - until I tried it. Have a look at the line: if all bind bind Filter 'File 'Header Unit: function ['Name [word!] Base-Directory [file!] Sub-Directory [file!] Filter [block!]] [Script Header] [ error? try [ if system/script/parent/header/File = %user.r [ set Name make object! [ Directory: file! Files: block! ] change-dir Base-Directory Name: get Name Name/Directory: Sub-Directory Name/Files: read Name/Directory change-dir Name/Directory foreach File Name/Files [ Script: load/header File Header: first Script if all bind bind Filter 'File 'Header [ do Script ] ] Name/Directory: join Base-Directory Sub-Directory ] ] ] Unit Patches %/C/Rebol/Patch/ %Patches/ [ Header/File = File Header/Patch = Header/Name ] Unit Enhancements %/C/Rebol/Enhancement/ %Enhancements/ [ Header/File = File Header/Enhancement = Header/Name ] BTW, 'Unit is my keystone building block for Patches, Enhancements for Rebol and Components and Plug-ins for Rebol applications, like RebMail. Note that the order of 'File and 'Header didn't matter. Which leads me to wonder if an enhanced version of 'bind that allows a block would be of interest to people or Rebol crew. Andrew Martin ICQ: 26227169 http://members.nbci.com/AndrewMartin/ http://members.xoom.com/AndrewMartin/ -- The order of 'File and 'Header didn't matter only because 'File context, 'Header context and the block bound aren't such, that there is a word e.g. 'Common such that 'Common is in the block and 'Common can be bound to both 'File context and 'Header context. In that case the results would differ. Regards Ladislav
[REBOL] a GC bug of the second kind Re:(6)
Hi, example code: word: use [a] [a: 11 'a] get word recycle get word CRASH! Ladislav - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Thursday, September 28, 2000 12:31 AM Subject: [REBOL] a GC bug of the second kind Re:(5) ptretter wrote: Just what is the GC bug? A bug that Rebol crew haven't fixed yet. :-) Unfortunately I've forgotten the example code that made Rebol crash. :-( Anyone? Andrew Martin ICQ: 26227169 http://members.nbci.com/AndrewMartin/ http://members.xoom.com/AndrewMartin/ --
[REBOL] Interleaving of strings question Re:
Hi, although your question has a little in common with Rebol, my answers are as follows: 1. It would be more precise to interleave each bit - ie. each binary digit - as the smallest unit of information 2. in that case the bit - sort yields: [0,0 2,2 1,5 5,1] 3. as you pointed out, the result of the sort doesn't depend on the representation, but on the comparison function, any suitable representation can do 4. your suggestion doesn't work, because you need close things in the terms of distance to remain close in the terms of sort. Your suggestion works only in the neighborhood of the 0,0 point Best regards Ladislav - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Monday, September 25, 2000 1:04 PM Subject: [REBOL] Interleaving of strings question I was thinking about the earlier postings about sorting coordinates by interleaving digits of the 2 axis values. The interleaving, it would seem, is to make the longitude as significant as the latitude, in terms of distance from other points. Ignoring the need to have the lat/long pairs stored that way for later processing, and ignoring stated expected values for the coordinates I thought: 1. Wouldn't it be more precise to interleave each digit? 2. In terms of a regular x,y system, even that would be incorrect sometimes. E.G.: [ 0,0 1,5 2,2 5,1 ] (a sorted set of simplified coordinates) isn't correct. 2,2 is closer to 0,0; 1,5 and 5,1 are the same distance from 0,0. 3. Could pairs or tuples be used? Answer: pairs didn't sort that way and I have no reason to assume sort would think of tuples as coordinates. 4. Wouldn't it be the least convoluted to have a /compare function for sort that understood that all components of the coordinate were equally significant? That way there's no manipulating the coordinates, and it should be the most precise. Would a Pythagorean type thing work, because it looks like simply summing the absolute differences between each coordinate component isn't right: 1,1 to 1,5 = 4 ((1-1)+(5-1)) 1,1 to 2,4 = 4 ((2-1)+(4-1)) yet 2,4 is closer to 1,1 than is 1,5. Until the real distance is needed, I don't think you'd have to take the square root of the sum (and how do you do that for 3-dimensions, does it become cubed and cube root - aha) (ABS(x1-x2) to the nth) + (ABS(y1-y2) to the nth) ... + (ABS(n1-n2) to the nth) Comments? Is this right? __ Do You Yahoo!? Send instant messages get email alerts with Yahoo! Messenger. http://im.yahoo.com/
[REBOL] a GC bug of the second kind
Jeff already signaled, that List! and Hash! datatypes are being fixed. I succeeded to track down the behaviour to the following: h: make hash! 0 insert h copy "0123456789" h recycle insert h copy "0123456789" CRASH! just in case you didn't know... Regards Ladislav
[REBOL] Compiler for Rebol ? Re:(8)
Well, let me throw in some thoughts. I think, that the debate started to look more abstract than I prefer. My comments are: 1) Rebol is IMHO designed with the runtime code accessibility in mind (inspired by Lisp), so I do not think, there's an easy way to convert that feature to its opposite. 2) I prefer the speed when compilation is considered, the source code protection is only a minor effect surely achievable by more direct means (discussed by Joel some time ago). 2a) When I look at the development in processor speeds (GHz looking as standard for year 2001 processors) and the neverstopping need to increase processor speeds, it is surely less preferable to write programs 100 or more times slower than C in some cases, so the speed is something any language including Rebol could use. 2b) Rebol with its mutable values used to store code radically differs even from Lisp, that uses immutable series for that AFAIK. That fact has immediate consequences - Self Modifying Code looks as standard - even some basic Rebol constructs are modifying, eg: 2ba) Use - modifies its (code) block argument (this causes even "unexpected" behaviour when recursive functions are called) and causes its code block argument very hard to compile when speed is the goal 2bb) Make object! - modifies its (code) block argument - see above 2bc) Bind - modifying, as opposed to Bind/copy, which behaves better 2bd) any mutables contained in the code aren't protected against change - no compilation advantage 2be) the code block can easily modify itself - a feature making compilation almost impractical Not trying to criticize, just to discuss the possibilities. What do you think? Ladislav - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, September 24, 2000 7:24 PM Subject: [REBOL] Compiler for Rebol ? Re:(7) [EMAIL PROTECTED] wrote: Right, thats my opinion too, but by using compile to hide the source we would loose the ability to acces code at runtime of compiled code. Coming from CommonLisp I think this would be very bad - we would give away a really important feature! I don't want to belabor this point unnecessrily (I probably have!), but I do NOT agree with casting this issue as a value judgement over an option which other languages provide the developer. If you (or your company) takes the policy position that you will never buy/license any software that comes without source, that's your right! (And if that means that you therefore can't use some products because they don't come with that option... well, you had the choice, so you get the consequences.) EQUALLY IMPORTANT IS THE DEVELOPERS RIGHT TO CHOOSE... If some developer creates a product for which he/she chooses not to distribute the source, that's his/her right! (And if that means that she/he loses some sales to people who require source as a precondition... well, she/he had the choice, so she/he gets the consequences.) EITHER WAY, that's what free markets are about. But to pre-empt EITHER the consumers' or developers' rights to choose how they will do business by creating a development environment (or a political environment or an economic one...) that gives all the rights of choice to one party (or by institutionalizing that party's choice so that it isn't even a choice any longer) is to prevent the market from working such things out on a case by case basis -- which I believe to be the fairest mechanism in the long run. Carl's support for MS operating systems doesn't keep me from using any of several varieties of Unix/Linux (except Debian, but that's another issue!), MacOS, etc. I never said something against this fact. You didn't, and I didn't mean to imply that you had. I was using the "choice of O/S" issue (which I think we all agree is a Good Thing) to try to illustrate why I think the "choice of distribution form" is also a Good Thing. _I_ would prefer using compilation (native, bytecode or whatever) for making the code more efficient and smaller. And I wholeheartedly support any steps which allow you that choice! But I do _not_ want to loose runtime accessibility to the code. And that, also, is your choice. You have a perfect right to make that a condition of doing business with you. However, I don't support making that a constraint on how everybody can conduct their affairs, when they are NOT doing business with you. That's THEIR choice! -jn-
[REBOL] Small admin/report benchmark Re:(3)
Hi Joel, You wrote: Ladislav's comes next (this is the second script he posted; the first one blew up on my box repeatedly). Confused, I expected the SECOND script (the script using Hash! datatype) to blow up - it looked to me like RT didn't succeed to implement of Hash! datatype reliably, or like there was another sign of the GC bug... Regards Ladislav
[REBOL] Small admin/report benchmark Re:(5)
Hi Andrew, no, that is not a bug for me (a feature). The real bug is, that you can use my Hash! ADS implementation for Joel's original password file (22 lines AFAIK), but it crashes Rebol (not error, simply crash, like GC bug) for his huge password file (360,448 lines ). If you are willing to test it, I would be very glad. Regards Ladislav Joel wrote: Ladislav's comes next (this is the second script he posted; the first one blew up on my box repeatedly). Ladislav wrote: Confused, I expected the SECOND script (the script using Hash! datatype) to blow up - it looked to me like RT didn't succeed to implement of Hash! datatype reliably, or like there was another sign of the GC bug... Are you thinking of the "sort-of bug" in objects where hash! datatypes, like sub-objects, aren't copied? Andrew Martin ICQ: 26227169 http://members.ncbi.com/AndrewMartin/ http://members.xoom.com/AndrewMartin/ --
[REBOL] How do I get the sort/compare func not to sort? Re:(2)
Hi, there is a help, but you must use a stable sorting algorithm, eg. my Merge-sort could do what you want (can send you my %msort.r privately). Regards Ladislav Based on the following: blk1 == [8 6 4 2 0 3 7 5 1 9] sort/compare blk1 func [a b] [a b] == [0 1 2 3 4 5 6 7 8 9] sort/compare blk1 func [a b] [a b] == [9 8 7 6 5 4 3 2 1 0] sort/compare blk1 func [a b] [(a // 2) (b // 2)] == [6 2 8 0 4 3 7 5 1 9] sort/compare blk1 func [a b] [(a // 2) (b // 2)] == [2 0 6 4 8 7 3 9 1 5] sort/compare blk1 func [a b] [(a // 2) (b // 2)] == [0 4 2 8 6 3 7 5 1 9] sort/compare blk1 func [a b] [(a // 2) (b // 2)] == [4 8 0 6 2 7 3 9 1 5] sort/compare blk1 func [a b] [true] == [1 5 2 9 7 6 8 4 0 3] sort/compare blk1 func [a b] [true] == [0 3 7 4 6 9 5 1 2 8] sort/compare blk1 func [a b] [true] == [2 8 6 1 9 4 3 0 7 5] I infer two things: 1) the comparison function should return true or false according to whether its two arguments are presented in the desired order or not, and 2) sort/compare uses an unstable sorting algorithm. That bit of jargon that means that the result is guaranteed to satisfy the comparison function between adjacent elements, but is there is NO guarantee that original ordering is preserved (even among elements that were properly ordered to begin with). We can test the second inference by creating a comparison that uses only part of the values, and see if the ignored portions remain in the same relative positions: blk: ["fe" "ca" "br" "ff" "cb" "bq"] == ["fe" "ca" "br" "ff" "cb" "bq"] sort/compare blk func [a b] [(first a) (first b)] == ["bq" "br" "ca" "cb" "ff" "fe"] sort/compare blk func [a b] [(first a) (first b)] == ["br" "bq" "ca" "cb" "fe" "ff"] sort/compare blk func [a b] [(first a) (first b)] == ["bq" "br" "ca" "cb" "ff" "fe"] sort/compare blk func [a b] [true] == ["cb" "ff" "br" "bq" "ca" "fe"] sort/compare blk func [a b] [(first a) (first b)] == ["bq" "br" "cb" "ca" "fe" "ff"] Notice that the function requires that strings be in order by their first letter only. In each of the first three uses, that property is clearly possessed by the result, but ordering (even original ordering) between strings with the same first letter gets fiddled arbitrarily. Using a compare function which always returns true basically lets the sort routine do whatever it wants. After that has happened, returning to the first-letter-only sort produces yet another ordering (in which two out of three pseudo-equal strings change ordering from the input). I'm out of ideas, except to say "don't sort to start with", but you didn't hear it from me! ;-) -jn- [EMAIL PROTECTED] wrote: Hello, Given, s: "abvde" sort/compare s func [a b][return 0] What can I exchange for the 0 return value such that the input is left unchanged? (and no, the answer is not "don't sort to start with" :-) I've tried -1, 0, 1. They all change the string! Anton.
[REBOL] Small admin/report benchmark Re:
Hi Joel, I didn't succeed to run your benchmark (not enough memory error occurred), so I modified it a bit: Rebol [] file: home/passwords.txt shells: copy make block! 5 countshell: func [sh [string!] /local shr] [ either none? shr: find shells sh [ append shells reduce [sh 1] ][ change shr: next shr 1 + shr/1 ] ] t1: now/time p: open/read/lines/direct file while [not error? try [line: first p]] [ countshell any [pick parse/all line ":" 7 "(none)"] ] foreach [sh n] sort/skip shells 2 [ n: to-string n while [3 length? n] [insert n " "] print [n sh] ] prin "Time1: " print now/time - t1 close p The results were: include/mult %smallad.r Script: "Untitled" (none) 196608 (none) 98304 /bin/bash 16384 /bin/false 16384 /bin/sync 16384 /sbin/halt 16384 /sbin/shutdown Time1: 0:00:11 Here is my second attempt, which works with the original file: REBOL [] include %ads.r file: home/smallad.txt shells: make-ads countshell: func [sh [string!] /local shr] [ associate shells sh 1 + associated/or shells sh [0] ] p: open/read/lines/direct file while [not error? try [line: first p]] [ countshell any [pick parse/all line ":" 7 "(none)"] ] shells2: sort to block! first shells foreach sh shells2 [ n: associated shells sh n: to-string n while [3 length? n] [insert n " "] print [n sh] ] close p The results are: 12 (none) 6 /bin/bash 1 /bin/false 1 /bin/sync 1 /sbin/halt 1 /sbin/shutdown For the small input file. Problem is, that for the huge file (%passwords.txt) an error (a GC fault?) occurs. Would anybody have time to test it? Regards Ladislav Here is %ads.r: Hi Rebols, here is my attempt to satisfy those who don't like objects for ADS implementation, those, who would like to have the fast searching capability, those, who would like to store in Any-type Rebol values and those who want to use only strings for keys. Rebol [ Title: "ADS" Name: 'Ads File: %Ads.r Author: "Ladislav Mecir" Email: [EMAIL PROTECTED] Date: 19/September/2000 ] make-ads: does [reduce [make hash! 0 make block! 0]] associate: function [ ads [block!] key [string!] value [any-type!] ] [index] [ either index: find first ads key [ index: index? index change at second ads index head insert/only copy [] get/any 'value ] [ insert tail first ads key insert tail second ads get/any 'value ] ads ] deassociate: function [ ads [block!] key [string!] ] [index] [ if index: find first ads key [ index: index? index remove at first ads index remove at second ads index ] ads ] associated: function [ ads [block!] key [string!] /or or-block [block!] ] [index] [ either index: find first ads key [ return pick second ads index? index ] [ if or [do or-block] ] ] - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Monday, September 18, 2000 6:16 AM Subject: [REBOL] Small admin/report benchmark Here's a small benchmark based on a fairly typical kind of sysadmin, file processing, or data reduction task. The timing results are given after the description of the problem and the code I used for timing. I'm including a sample data file and output so that anyone who wants to improve on my code can test his/her solution with the same data. Problem: Read through the colon-delimited file below (a copy of an /etc/passwd file, mangled for security purposes), and print a report tallying the distinct values in the 7th field (in this case, the field that identifies the default shell for each userID). Sort the results by the value of the field being tallied, and print the results in neat columns. == begin sample data file == ayxa:a:824:277:Zmgxoy "Uucl" Tmaam:/ibmg/rsrn:/bin/bash ciyp:x:8:72:jksi:/zfp/qnffy/drgn: grnfk:p:115:383:SNMKW hwxyzry:/evfk/tsmgt:/bin/bash guqkvtwn:o:2:2:blvbnjsg:/lbld:/sbin/shutdown kpsbwt:z:85:98:frwbqf:/zeu/bml/egtyin-mexi: kst:y:1:3:gsi:/opj: kvik:f:3:9:clnd:/bfje:/bin/sync lw:b:518:941:Nxpn "VAXVAzjzw" Muhxp:/esaq/jy:/bin/bash mmlmgxep:g:69:4:lnuytrat:/vvot: nnd:g:46:89:WQT Pcpu:/shrs/vzq: ospax:t:707:92:Lpojk bro Gokzfe:/qaqf/gaedx:/bin/bash pbubex:v:7:9:eworcq:/khuc: qpdd:l:39:19:qckl:/omg/clghd/szdr: rkuu:p:2:1:rusj:/ltnm:/sbin/halt sft:q:045:235:H Buya Gtdtre:/stj/W75/ot:/bin/false srimrg:c:19:41:Ybltzu:/: vgonz:n:86:051:oqufv:/hgo/awkxv: vqn:n:7:0:ant:/npy/hpm: wbci:s:2:5:pyiy:/xngl:/bin/bash wlzr:o:7:00:rqwe:/mxy/rkchz/lsfu: xao:c:21:50::/fgqu/orw:/bin/bash yf:d:1:6:ay:/xzb/njwes/kvd: === end sample data file === = begin sample output list = 12 (none) 6 /bin/bash 1 /bin/false 1 /bin/sync 1 /sbin/halt 1 /sbin/shutdown == end sample output list == Perl solution: A fairly typical Perl script to perform this task is
[REBOL] Essay on Associative Data Stores Re:
Hi Joel, two notes: 1) I think that some posts on ADS missed one very important point - the speed. The problem is, that Find (sequential search) may be a bottleneck for some apps. 2) Select may be less general than Select/only sometimes. Regards Ladislav
[REBOL] Associative Data Store Re:
Hi Andrew, there is a lot of cases, where your functions won't work as expected, eg.: blk: copy [] associate blk [2] 3 associate? blk [2] The other problem is, that your functions won't accept Any-type! values for Key/Value Regards Ladislav Here's an implementation for an Associative Data Store (ADS) that uses only two functions, doesn't require an object per ADS and can use any Rebol value as a key. Comment invited. Thanks to Gabriele for showing how to shorten the 'Associate? function. [ Rebol [ Title: "Associate" Name: 'Associate File: %Associate.r Author: "Andrew Martin" Email: [EMAIL PROTECTED] Date: 18/September/2000 ] Associate: function [Block [block!] Key Value] [Index] [ Index: find Block Key either none? Value [ if found? Index [ remove/part Index 2 ] ][ either found? Index [ change/only next Index reduce [Value] ][ append Block reduce [Key reduce [Value]] ] ] Block ] Associate?: function [Block [block!] Key] [Value] [ all [ Value: select Block Key first Value ] ] ] Andrew Martin ICQ: 26227169 http://members.ncbi.com/AndrewMartin/ http://members.xoom.com/AndrewMartin/ --
[REBOL] How do I dynamically extend an object! instance Re:(3)
Hi bobr, what are the results of the code below and which version of Rebol you use? -Ladislav At 09:09 PM 9/10/00 +0200, [EMAIL PROTECTED] wrote: Hi bobr, - can it be done without creating a new instance? No. ok here is my latest method for extending an object in-situ. the example hasnt been turned into a function and I hope I am not violating any storage but here goes... [ a: make object! [ addr: "417 howser st" name: "joyce haversham" ] wds: first a vals: second a append wds 'email append vals "joyce@someplace" probe a ] now this -looks- fine, you can save/probe/mold the object and read it back in with no problems. best of all no new object is instantiated so all references to a are updated as well. for some reason you cannot access the new items by a path. as soon as you type a/email there is an error. remove seems to be just as simple but I think I will stay away from it till I know exactly is going on with a/email and why the path doesnt work before I drop something out of the middle. ;# mailto: [EMAIL PROTECTED]
[REBOL] rebol weak points (i think) Re:(3)
Hi Rishi, I think, that you are missing only complications here. What you are saying is, that Math below is an instance of Object! datatype. You are right. You are saying, that you would prefer it to be a class. But classes in a lot of languages (except for C++, Java, ..., AFAIK) are instances of object datatype too. There is only a little other language classes could do for you and Rebol objects can't, IMHO. (You can even create a Rebol class hierarchy using Rebol objects, as I demonstrated.) Regards Ladislav no. The Math/Pie you have created is an instance variable not a static variable. It is associated with an instance of the class, not the class itself. A static variable means that there is a single copy of this variable associated with class itself. You do not need to instantiate a class to use static variable. For example: make-circle: make func [ radius /local blah-blah-blah /static num_circles ;let's say this is how you create static var. ] [ num_circles: num_circles + 1 ;this may not be correct but you get the idea... return make object! [ ;object code goes here ] ] small-circle: make-math(2) large-circle: make-math(100) print make-circle/num-circles ;this should hypothetically print out 2 print num-circles ;should print error Unfortunately, it would not make sense to add a static option the way I have done it since not all functions return objects. Anyway, the fact that rebol does not have static variables and static functions is no big deal. It was probably a concious decision not to include it. The main advantage of having static variables would be to prevent name collisions and to group variables/functions that act on a class (not an object) together for use in a more natural way. The main disadvantage of having static variables is that perhaps it is an unnecessary complication. But I don't think so. Maybe because I come from java/javascript background. I'm still wondering though if there is a way to have static variables that I don't know. Regardless, the main problem that I wonder about is if rebol is suited for modular programming where people reuse other people's functions/code. Since everything is either global or local, it seems as though it would be unnatural to use rebol in this way. Java has packages and stuff...perhaps I am not thinking straight and have too much java in my blood (which I have been doing to much of lately and finally got sick of all the abstractions that got in the way of doing simple stuff!!) Rishi - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, September 09, 2000 6:03 PM Subject: [REBOL] rebol weak points (i think) Re: Rishi wrote: Math.pi=20 Math: make object! [ [Pie: 20 [] Math/Pie == 20 Pie ** Script Error: Pie has no value. ** Where: Pie Andrew Martin ICQ: 26227169 http://members.xoom.com/AndrewMartin/ --
[REBOL] How do I dynamically extend an object! instance Re:
Hi bobr, you wrote: I have an existing dataase of saved objects which I wish to add fields to (IE add words:). I probably only want to add the words if I absolutely must in order to keep size down. I also may already have added a particular word to an object instance and dont wish to overwrite the value already associated with that word. Here is what I have so far. questions follow below. object-addword: func [ { add a word only if it is not already there, returns a new instance of the object examples myobj: object-addword myobj emailaddr dbrecord: object-addword/initial dbrecord areacode 978 } o [object!] "the object to have a word added" 'w1 [any-word!] "the word to add" /initial vdef [any-type!] "provide initial value for the word" /local mb "mini block" ] [ if not find (first o) w1 [ ; try to emulate: set/any in o w1 none mb: do rejoin [ {[} :w1 {: none ]} ] o: make o mb if initial [ set/any in o w1 vdef ] ] return o ] ; for discussion: - can this be written more succinctly yet not hardcode anything about the object? I would suggest the following: object-addword: func [ { add a word only if it is not already there, returns a new instance of object examples myobj: object-addword myobj emailaddr dbrecord: object-addword/initial dbrecord areacode 978 } o [object!] "the object to have a word added" ; I prefer not to use unevaluated/fetched arguments w1 [word!] "the word to add" /initial vdef [any-type!] "provide initial value for the word" ] [ if not find (first o) w1 [ o: make o reduce [to set-word! w1 none] ; because you declared vdef to be any-type!, this is the only way to set it error? set/any in o w1 get/any 'vdef ] return o ] Example: probe object-addword/initial make object! [] 'a () make object! [ a: unset ] The problem is, that even this is not general enough, as is explained below - can it be done without creating a new instance? No. - can a corresponding function for removing a word from an object be written without evaluating all the other words/elements? The general answer is no, IMHO, only special cases can be solved. There are two problems: 1. 'Self can be any-type! in Rebol. 2. There are problems with "complicated" datatypes, eg. functions I have tried several arrangements for the arguments and names for the function. I have settled on object-addword rcvrobj operand - are the precedents for putting the word operand first? - since, from context, you can tell which argument is the object and which is simply a word which may need to be added to the object, why not make the function figure out which argument is which type and do the right thing regardless of how it is called? can this be coded without resorting to second-level functions? It is feasible, if you don't use unevaluated arguments: object-addword: func [ [catch] o [object! word!] w [object! word!] ] [ if word? o [ set [o w] reduce [w o] ] if not object? o [ throw make error! reduce ['script 'expect-arg 'object-addword 'o object!] ] if not word? w [ throw make error! reduce ['script 'expect-arg 'object-addword 'w word!] ] ; ... ] - is a better name for the function possible? I have considered 'object+ and 'object+word as potential names. Is there a precedent that I have missed? ;# mailto: [EMAIL PROTECTED]
[REBOL] Trying to compose a block out of global and local bindings Re:(2)
Hi Elan, you wrote: letter2: func [b] [ foreach name ["Sue" "Sally"] [ print bind b 'name ] ] Here BIND directs REBOL to associate all words contained in 'b with the "closest" context that contains the symbol name. L: I would recommend to change the wording: {Bind associates all words contained in B (not in 'B, because in 'B is "contained" a block IMHO) with the context previously associated with the word 'Name (again, not Name, as you wrote) which is its second argument.} I am not sure I understand the term "closest" above, I would recommend to not use it here. Elan: Because 1. the context in which the BIND expression is being used is the block passed to foreach, and L: Again, a change suggested. I don't believe, that the block passed to Foreach is a context, sorry. This wording looks better: {The second argument of Bind is the word 'Name previously associated with the context Foreach created.} Elan: 2. a) because the first argument passed to foreach (foreach name ...) is an instance of the word name L: This doesn't make much sense to me too, the sentence: {'Name (the second argument of Bind above) is an instance of the Word! datatype} looks like a correct usage of the word "instance", but it doesn't say what you wanted. I would recommend to look at the previous suggestion. Elan: b) there therefore now exists an instance of the word name that is bound to foreach's context, L: Again a change necessary, IMHO: {There exists a word 'Name that is bound to a context Foreach created.} is the wording I prefer. Elan: 3. == therefore a) REBOL will identify foreach's context as the "closest" context in which 'name occurs. L: I think, that you switched the cause and the consequence here: the truth is, that the word 'Name above (the second argument of Bind) was bound by Foreach to the context it created and that is why "there exists a word 'Name that is bound to a context Foreach created". Elan: This is the context to which all words in the block b are now being bound, provided they are defined in foreach's context. b) Because of 3.a) the symbol name in the block b will be bound to the foreach context. (If the block b contained other words and some or all of these other words were also defined in the foreach context, then all these words would be bound to the foreach context as well. L: I don't like the use of the word "symbol" here. The meaning of it is defined in Rebol. I found the use of this word in Rebol with different meaning, than Rebol assigned to it ambiguous. Elan: Words that are not defined in the foreach context remain bound to whichever context they originated in, when the block b was formed, or they remain unset!, if they were never set to a value to begin with). L: Again a statement I would suggest to change: {Words that are not contained (whether defined or not is irrelevant) in the context Foreach created remain unchanged, while words, that are contained in the context Foreach created are replaced (in B) by their equivalents bound to the above context.} Elan: RESULT: name: "Bob" == "Bob" message: ["hi" name "welcome back"] == ["hi" name "welcome back"] letter2: func [b] [ [ foreach name ["Sue" "Sally"] [ [ print bind b 'name [ ] [] letter2 message hi Sue welcome back hi Sally welcome back Note that as a side-effect the symbol name in the message block remains bound to the value it was last associated with in the letter2 function: reduce message == ["hi" "Sally" "welcome back"] L: Yes, this effect can be considered a self-modification of the code presented, I think. Elan: If that should be relevant, i.e. you want to prevent the modification of the binding of the word name in the original message block, you can use bind/copy, which generates a duplicate of the block, before it binds it: letter2: func [b] [ foreach name ["Sue" "Sally"] [ print bind/copy b 'name ] ] letter2 message hi Sue welcome back hi Sally welcome back reduce message == ["hi" "Bob" "welcome back"] Note that the word used as foreach's first argument (foreach name ...) is not bound in the context of your letter2 function in which foreach is evaluated. It is bound in the context of foreach. L: A different wording: {Note that the word used as Foreach's first argument (foreach name ...) is not bound in the context of your Letter2 function. It is bound in the context Foreach created.} I would prefer not saying, that "...Foreach is evaluated in a context,...", because I don't know, what that should mean. To the contrary, I am pretty sure, that there are examples of Rebol code, for which you cannot find any "context they are evaluated in". Elan: Let us demonstrate that by collecting different instances of name into a block. We being with the global instance: names: [] == [] name: "This is the global instance of name." == "This is the global instance of name." insert tail names 'name
[REBOL] Trying to compose a block out of global and local bindings Re:(2)
Hi, SS wrote: I'll point out quickly that what you're trying to do is generally considered a bad programming practice, i.e. referencing a variable internal to a function from its argument. A caller shouldn't need to know about and shouldn't really have direct access to variables local to a function. I will however provide an example of how to do what I think you're trying to do and recommend that you rethink your approach in any case because this is almost as bad but I think it demonstrates that your problem was perhaps not one as much of scope but more of tokenization: letter2: func [b][foreach n ["sally" "sue"][print replace (copy b) 'name n]] greeting: ["hi" name "welcome back"] == ["hi" name "welcome back"] {I prefer not to overwrite REBOL words, like "form" from your example} == {I prefer not to overwrite REBOL words, like "form" from your example} name: "bob" == "bob" letter2 greeting hi sally welcome back hi sue welcome back FWIW, SS The self-modifying Bind-, or its non-self-modifying Bind/copy- variant approach really doesn't look preferrably to me. Here is an approach that looks different IMHO: letter2: func [b /local subst][ subst: func [name] reduce [:print b] foreach n ["sally" "sue"][subst n] ] greeting: ["hi" name "welcome back"] name: "bob" letter2 greeting What do you think? Ladislav On Thu, 7 Sep 2000 [EMAIL PROTECTED] wrote: letter2: func [b /local name] [foreach n ["sally" "sue"][ name: n print reform reduce b] ] form == ["hi" name "welcome back"] name == "bob" letter2 form hi bob welcome back hi bob welcome back ... the only problem is I was hoping that the loop values in letter2 would take precedence over the globally bound value of name and allow me to create a form letter of sorts. Could anyone help with this please? Get your FREE Email and Voicemail at Lycos Communications at http://comm.lycos.com
[REBOL] write does not return a value upon success. This is bad for try blocks Re:
Hi, try this: tries: 3 until [ set/any 'm try [write ftp://chuck:[EMAIL PROTECTED]/crossing/ndtd/user.r "hi there"] tries: tries - 1 any [tries = 0 unset? get/any 'm] ] Regards Ladislav I am writing a script that will try 3 times to write a file and then fail, however, I cant place a try block around the REBOL write statement because it does not return anything upon success, thus I get an error that the word is not bound: m: try [ write ftp://chuck:[EMAIL PROTECTED]/crossing/ndtd/user.r "hi there" ] connecting to: 170.16.15.136 ** User Error: Server error: tcp 530 Login incorrect.. ** Where: write ftp://chuck:[EMAIL PROTECTED]/crossing/ndtd/user.r "hi there" ; -- great: when write fails 'm is bound m: try [ write ftp://chuck:[EMAIL PROTECTED]/crossing/ndtd/user.r "hi there" ] connecting to: 170.16.15.136 ** Script Error: m needs a value. ** Where: m: try [write ftp://chuck:[EMAIL PROTECTED]/crossing/ndtd/user.r "hi there"] ; --- well this sucks. I cant get a return value upon success Get your FREE Email and Voicemail at Lycos Communications at http://comm.lycos.com
[REBOL] Trying to compose a block out of global and local bindings Re:
Hi, try this: letter2: func [b] [foreach name ["sally" "sue"][print bind/copy b 'name]] form: ["hi" name "welcome back"] letter2 form Regards Ladislav letter2: func [b /local name] [foreach n ["sally" "sue"][ name: n print reform reduce b] ] form == ["hi" name "welcome back"] name == "bob" letter2 form hi bob welcome back hi bob welcome back ... the only problem is I was hoping that the loop values in letter2 would take precedence over the globally bound value of name and allow me to create a form letter of sorts. Could anyone help with this please? Get your FREE Email and Voicemail at Lycos Communications at http://comm.lycos.com
[REBOL] Rolling your own ideal looper: does Repeat still have a bug? Re:(7)
Hi Elan, the problem has been solved by the function For2 (you can see it at the end of the mail). Your solution (I call it For1) differs here: for1 i a: [1 2] tail a 1 [print mold i] [1 2] [2] for2 i a: [1 2] tail a 1 [print mold i] [1 2] [2] [] Regards Ladislav Hi Galt, it appears I didn't got all the emails in this thread. So the problem may already be solved. you wrote: Ladislav, That is an impressive For function! your example of using a: [1 2] for s a tail a 1 [print s] as a test is very amusing bug, looks like an infinite loop on windows, just keeps printing newlines without ever ending. I guess you would rather see for s a tail a 1 [print s] 1 2 2 I think that that's reasonable. The patched for version below does that. If you source the for function you'll see why for behaves as it does. The patched version corrects this and the other observed oddities. The results of running the patched version: for s a next a -1 [print s] == none for s a next a 1 [print s] 1 2 2 for s a tail a 1 [print s] 1 2 2 for s a back tail a 1 [print s] 1 2 2 I added the following code to for: ;- the following line forces for to interpret ;- "tail of a series" as intended to mean "break at end of a series". if all [positive? bump tail? end ] [ end: back end ] ;- the following either any .. all .. combo catches errors resulting ;- from an end index that is higher than a start index with a ;- negative bump value, and also catches infinite loops that result ;- from passing an empty series either any [ empty? head end all [ if (negative? bump) [ op: :lesser?] op index? start index? end ] ] [ none ][ Note that I moved the expression if (negative? bump) [ op: :lesser?] into the all block of either's any block. The complete pathced for function follows: for: func [ "Repeats a block over a range of values." [catch throw] 'word [word!] "Variable to hold current value" start [number! series! money! time! date! char!] "Starting value" end [number! series! money! time! date! char!] "Ending value" bump [number! money! time! char!] "Amount to skip each time" body [block!] "Block to evaluate" /local result do-body op ][ if (type? start) (type? end) [ throw make error! reduce ['script 'expect-arg 'for 'end type? start] ] do-body: func reduce [[throw] word] body op: :greater-or-equal? either series? start [ if not same? head start head end [ throw make error! reduce ['script 'invalid-arg end] ] ;- the following line forces for to interpret ;- "tail of a series" as intended to mean "break at end of a series". if all [positive? bump tail? end ] [ end: back end ] ;- the following either any .. all .. combo catches errors resulting ;- from an end index that is higher than a start index with a ;- negative bump value, and also catches infinite loops that result ;- from passing an empty series either any [ empty? head end all [ if (negative? bump) [ op: :lesser?] op index? start index? end ] ] [ none ][ ;- we are dealing with a valid series while [op index? end index? start] [ set/any 'result do-body start start: skip start bump ] if (negative? bump) [ set/any 'result do-body start ] ] ] [ if (negative? bump) [op: :lesser-or-equal?] while [op end start] [ set/any 'result do-body start start: start + bump ] ] get/any 'result ] Just for kicks, I just tried this: for s a back tail a 1 [print s] 1 2 2 so that it stops at the last real position, and that seemed to work, althout the expression is more awkward and wordy! Your other example is this: for s a next a -1 [print s] 1 2 which I am not sure I get. This would never get to next a by skipping -1. Either you have a typo here, or I missed the point. If this were integers, it would look like for x = 1 30 step -1 for s a next a 1 [print s] 1 2 2 What is the proper behavior of for s a next a -1 [print s] ??? -Galt p.s. As far as the second-class vs. first-class values goes, I am inclined to agree with you. There are some fishy issues that don't seem entirely cooked. You are right to bring them up for discussion. So far, however, in the programs that have come up naturally in my use of Rebol, I haven't been banging into these issues alot. I have seen the errorhandling stuff e.g. try, disarm seems like it's more awkward than it should be. I could run smack into more of them at any moment, though! p.p.s. I think the desire to share
[REBOL] forall should have a refinement /then-reset Re:(3)
Hi, what about: forall: func [ "Evaluates a block for every value in a series." [throw] 'word [word!] {Word set to each position in series and changed as a result} body [block!] "Block to evaluate each time" /former /head /local fmr ][ if former [fmr: get word] while [not tail? get word] [ do body set word next get word ] if former [set word fmr] if head [set word head get word] ] Regards Ladislav Excellent question that I did not even think about!!! how about these two: forall/then-former ;- put back to state before loop forall/then-head ;- put back to head --- ; run this in your ; a href=http://www.rebol.comREBOL/a Interpreter! terrence-brannon: [ [EMAIL PROTECTED] perl-refugee myth-gamer ] perl-refugee: [ 'loved href perl discovery: (metaperl = rebol) 'hates href perl ] myth-gamer:http://www.bungie.net/bin/stats.pl?player=princepawn ; angles makes this a href instead of code! use ur imagination! href: func [U T] [ rejoin [ "a href=" U "" T "/a" ] ] perl: href http://www.perl.com "Perl" On Tue, 29 Aug 2000 12:06:01 joel.neely wrote: H... Reset to what? The position of the series just before the forall loop, or the beginning of the series? -jn- [EMAIL PROTECTED] wrote: I'm sure you've seen the REBOL idiom: forall line [ ... ] line: head line I would appreciate it if I could type: forall/then-reset line [ ... ] Get your FREE Email and Voicemail at Lycos Communications at http://comm.lycos.com -- ; Joel Neely [EMAIL PROTECTED] 901-263-4460 38017/HKA/9677 REBOL [] print to-string debase/64 decompress #{ 789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC B6F4F574CFC888342AC949CE74B50500E1710C0C2400} Get your FREE Email and Voicemail at Lycos Communications at http://comm.lycos.com
[REBOL] using find/only to match blocks Re:
Hi, find/only C [2 3 4] should work Supposedly find/only treats a series as a single value, but I am not sure how this is done. I was interested in find the place in a series at the place where a block is found: C: [ 1 [ 2 3 4] 5 6 ] find C "234" ; what I want to do find C [ 2 3 4 ] ; or this ... whatever works --- ; run this in your ; a href=http://www.rebol.comREBOL/a Interpreter! terrence-brannon: [ [EMAIL PROTECTED] perl-refugee myth-gamer ] perl-refugee: [ 'loved href perl discovery: (metaperl = rebol) 'hates href perl ] myth-gamer:http://www.bungie.net/bin/stats.pl?player=princepawn ; angles makes this a href instead of code! use ur imagination! href: func [U T] [ rejoin [ "a href=" U "" T "/a" ] ] perl: href http://www.perl.com "Perl" Get your FREE Email and Voicemail at Lycos Communications at http://comm.lycos.com
[REBOL] Dialling Out Re:
Hi, my copy of Windows 98 dials out whenever Rebol asks. No user intervention needed. It depends on the settings of Win 98 IMHO. Regards Ladislav - Puvodní zpráva - Od: [EMAIL PROTECTED] Komu: [EMAIL PROTECTED] Odesláno: 30. srpna 2000 10:08 Predmet: [REBOL] Dialling Out Hi I am a newcomer to REBOL and would like to use it to solve a particular programming problem. I have a stand-alone application, which is not attended by a user, which occasionaly needs to send or receive e-mails. Rather than programming all the code at a low level, REBOL seemed ideally suited to performing the network interaction processes through an application generated script and a CREATE_PROCESS call to REBOL.EXE My problem is that the machine does not have a permanent connection to the network, but needs to dial out when required. Does anyone have a suitable script, or a technique which can be used to get the machine to dial out a connection (using a connection defined in DUN) without requiring any user interaction? I woud have thought that this would be a very common requirement (most networking tools have the ability to dial out if they are not connected, although simply invoking DUN still requires a user confirmation) and I would suggest that it would be a very worthwhile enhancment to REBOL. Regards Justin * * Justin A. T. Halls* * Millennium Homes Project Manager * * Brunel Institute for Bioengineering * * Brunel University * * Kingston Lane * * Uxbridge * * Middx. UB8 3PH* * UK* * Tel. +44 (0)1895 271206 * * Fax +44 (0)1895 274608 * * e-mail: [EMAIL PROTECTED] * *
[REBOL] copy versus copy/deep Re:
Hi, The difference: a: [[1]] b: copy a c: copy/deep a change first a 2 probe a probe b probe c Regards Ladislav - Puvodní zpráva - Od: [EMAIL PROTECTED] Komu: [EMAIL PROTECTED] Odesláno: 28. srpna 2000 16:33 Predmet: [REBOL] copy versus copy/deep As my example below shows, there does not appear to a difference in handling nested blocks between copy and copy/deep a: [ 1 2 [ 3 [ 4 5 ] 6 ] 7 8 ] == [1 2 [3 [4 5] 6] 7 8] b: copy a == [1 2 [3 [4 5] 6] 7 8] b == [1 2 [3 [4 5] 6] 7 8] c: copy/deep a == [1 2 [3 [4 5] 6] 7 8] c == [1 2 [3 [4 5] 6] 7 8] b == [1 2 [3 [4 5] 6] 7 8] a == [1 2 [3 [4 5] 6] 7 8] Get your FREE Email and Voicemail at Lycos Communications at http://comm.lycos.com
[REBOL] Rolling your own ideal looper: does Repeat still have a bug? Re:(4)
Hi, being asked I try to explain my changes. 1. Thanks, Gabriele, I forgot to use one more Throw, but the original is needed too. I used Throw attribute to make sure, that any Return or Exit contained in code like: f: does [ideal-looper elem indx [1 2 3] [exit]] does what it should, ie. causes the exit of F. 2. Any-type! specification is needed, because a series in Rebol can contain even eg. Unset! values, in which case the function without the spec. wouldn't work. 3. For uses While anyway, so it is a shortcut. (see Source For, but look out! It still contains the series bug I reported to feedback.) The corrected version: ideal-looper: func [ [throw] 'element [word!] 'index [word!] series [series!] code [block!] /local f i ] [ f: func reduce [[throw] element [any-type!] index] code i: 1 while [i = length? series] [f series/:i i i: i + 1] ] Regards Ladislav Hello [EMAIL PROTECTED]! On 27-Ago-00, you wrote: l Hi, l just a small change: [...] Perhaps you meant: ideal-looper: func [ 'element [word!] 'index [word!] series [series!] code [block!] /local f i ] [ f: func reduce [[throw] element [any-type!] index] code i: 1 while [i = length? series] [f series/:i i i: i + 1] ] F is the function that should have the THROW attribute. Regards, Gabriele. -- Gabriele Santilli [EMAIL PROTECTED] - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[REBOL] Rolling your own ideal looper: does Repeat still have a bug? Re:(2)
Hi, just a small change: ideal-looper: func [ [throw] 'element [word!] 'index [word!] series [series!] code [block!] /local f i ] [ f: func reduce [element [any-type!] index] code i: 1 while [i = length? series] [f series/:i i i: i + 1] ] Regards Ladislav
[REBOL] context of a function Re:(11)
Hi, Galt: I generally find that most of my knowledge of other computer systems to gain insight into rebol is quite helpful and revealing. Even having the context to say, this is like scheme or logo in rebol, but that is like some other language, etc. is all helpful. So, yes, it is true that rebol is different in important ways from other languages and therefore you will have to gain a new understanding. But this notion that you would be better off starting from a point of total ignorance and then everything would be easy is patently absurd. When I have trouble with Rebol, if I was a less knowledgeable user I would probably just give up. Being able to make some guesses about possible causes or solutions is much better. So, the best way really, is for Rebol to tell us how it works inside. When you know how rebol lists really work, and string literals and contexts and words, then you understand rebol. Ignorance or innocence isn't much help. Obviously, one should try never to allow preconceptions and prejudice to inhibit understanding, and that is true of everything, not just Rebol. I am not a stupid person, even if I am not a genius. I only got this far with Rebol because I am doggedly persistent, not because I have the pleasantly uncluttered mind of an infant. I really like and respect you Andrew, and I appreciate all the work you have done for Rebol and the members of the list. I just didn't want to let this go by yet again... Now, this doesn't mean that I am anti-Rebol or want to be critical or whatever. We all love Rebol and want to use it as much as possible! I still don't know how forgetting everything I know is going to help me figure out just what the heck read-io really does and why timeouts don't seem to work as advertised for downloading big files... Andrew: I was hindered by my knowledge of other languages. Coming from a point of view of innocence, knowing only human languages, is better I feel. I disagree. The model that Rebol is based on is close to natural human language. Knowing that and knowing nothing of computer languages is the best way to learn Rebol. Rebol works literally as it is. Discussing in depth, contexts and how they work are almost meaningless, particularly when some parts of Rebol are still buggy and need to fixed. I thinking of the GC bug, hopefully that's fixed in the experimental builds. Change can be hard, but after the change, you wonder, what was the trouble? You're basically trying hard to learn the detail, without knowing rebol. Ladislav: Rebol differs from human languages in some respects. One of them can be found comparing Rebol Values vs. Human Values (see http://www.geocities.com/lmecir.geo/evaluation.txt). This may be a surprise for both experienced and inexperienced programmer, because that fact is hidden in other programming languages to some extent. Another difference can be found comparing the behaviour of Rebol (CQSB/DRP) functions with the behaviour of their Pure CQSB counterparts (see http://www.geocities.com/lmecir.geo/contexts.txt). A set of the differences can be found studying the behaviour of code - modifying functions like Repeat, Make Object!, Use, Foreach, ... The latter difference can be considered a bug, of course, but it is present in Rebol nowadays. My personal point of view is, that my previous experience with other programming languages helped me to understand Rebol and appreciate its advantages.
[REBOL] Bind speed.
Hi, my measurements are showing, that Rebol Bind is slower than it could be. In the case of your interest I can help with that. Regards Ladislav
[REBOL] context of a function Re:(5)
Hi Elan, I am not a native English speaker, but see some use for a terminological change: You wrote: {{ It is simple to determine which words are bound to the context of a function. We must do a little more work to determine whether an instance of the word a is bound to the context of the object or to the context of the function. }} I offer the following reformulation (the asterisks are marking the difference): {{ It is simple to determine whether a word *can be* bound to the context (of a function/object). We must do a little more work to determine whether a word *is* bound to the context (of the function/object). }} Regards Ladislav
[REBOL] A small security hole REBOL, and a huge one! Re:(3)
Hi, the following code was posted by me some time ago and the principle was sent to feedback too. Here it is again: protect 'secure system/error/script/type: "" system/error/script/expect-arg: [ ( change pick third :secure 3 reduce [word! block!] secure allow "I love you" ) ] change pick third :secure 3 reduce [unset! none!] ; the results are: secure throw ** : I love you. ** Where: secure throw secure [] == [net allow file allow] Regards Ladislav - Puvodní zpráva - Od: [EMAIL PROTECTED] Komu: [EMAIL PROTECTED] Odesláno: 21. srpna 2000 0:59 Predmet: [REBOL] A small security hole REBOL, and a huge one! Re:(2) Ladislav, Can you provide some example code that demonstrates this security hole. Paul Tretter -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Sunday, August 20, 2000 5:43 PM To: [EMAIL PROTECTED] Subject: [REBOL] A small security hole REBOL, and a huge one! Re: Hi Brian, the problem is, that even the natives are mutable, as can be seen in Mutable natives thread. Regards Ladislav I hate to be the bearer of bad tidings... First, the small security hole: I just found out that second returns the original code block when applied to a function value. This code block can then be changed, which changes the function without recreating it and reassigning it. This kind of change is invisible to the query and protect functions. This means that a script can add code to any of the mezzanine functions without you being able to tell. I don't know any easy way to protect the REBOL interpreter session from this kind of attack. I know that you should read untrusted code before you execute it on your system, but the WWReb is based on executing distributed code. The first and second functions were changed before to return a copy of the blocks when applied to object values. Is there some reason that second and third applied to function values returns the original? Memory efficiency, perhaps? Avoidance of deep-copying possibly cyclic structures? Can we count on this behavior in the future, or is it subject to change? It enables self-modifying code, for example. If we could count on this trick it would make things more interesting for advanced REBOL programmers. I don't see how adding modules will change this in any way. I don't see how you could prohibit changes in the inner blocks and parens referenced by the code without too much overhead. I guess the best way to secure REBOL is to use the launch function and run the script in a separate, secure interpreter environment. This brings me to my next discovery though... The big security hole: The new launch native! Right now, the launch native launches a new REBOL process with the command line arguments you pass as a parameter. Command line arguments just like those accepted on the command line of REBOL. This command line can include REBOL options, including "--nowindow --quiet --secure none", with no kind of security warning! Launch should be rewritten so that the command line options normally accepted by REBOL are passed as refinements to the launch native. The /secure refinement then needs to have the same restrictions that the secure native would have if called at the same point in the code. Any command line options in the argument any-string! should be ignored by the new REBOL process. This hole is such a major issue that I have Bcc'd this message to Feedback. Fortunately the launch native is only implemented in the experimental releases. Until this is fixed, don't ever run any untrusted code with an experimental REBOL if it has a working launch native (only /View so far)! Don't kill the messenger, please! :( Brian Hawley
[REBOL] context of a function - Enhancement request Re:
The best sollution would be to enhance "in" so you can not only get words out of object's context, but also out of functions context. f: func [a] [a] f 2 in :f 'a == a same? first second :f in :f 'a == true Good idea? Frank Sure, copy it to feedback, please. I prefer this to the 'Self idea. Moreover, I would like to have an option to create objects without 'Self if needed. (I wasn't the one who asked for 'Self.) Opinions? Regards Ladislav
[REBOL] Enhancement Request - Range! datatype Re:(10)
By accident, both Czech and Slovak "to" means English "it". Regards Ladislav Does "to" have any special meaning in Czechoslovakian (I hope I spelled that right), pekr? Probably the same as in Spaenglish ;-) (there are 2 (!) languages, one Czech and one Slovakian. You are from the U.S. , aren't you ?) Jean
[REBOL] problems with local vars??? Re:(10)
Hi, you can do: print read http://www.geocities.com/lmecir.geo/evaluation.txt to read my "Rebol Values vs. Human Values" and print read http://www.geocities.com/lmecir.geo/contexts.txt to read "Words, Bindings and Contexts" Regards Ladislav The result is not what I expect. How do we account for this behavior. probe :a "a" I thought the output would be "" Please explain this in more detail. -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Sunday, August 20, 2000 4:58 PM To: [EMAIL PROTECTED] Subject: [REBOL] problems with local vars??? Re:(8) Hi, no "Dialect" notion can help you with your problem. (My personal preferences are, that Rebol functions aren't "Rebol dialect", because I think that there is a difference between a Rebol code in a block and a Rebol function, which has got more attributes, than Rebol code - see my Rebol function model in Words, Bindings and Contexts thread.) Back to your problem. The difference you see can be visualised here: probe :a "a" a: 0 b: :a add :b 1 probe :a The results show, that there are differences between integers and strings in Rebol, Rebol strings are mutable (you can change them), while integers are immutable (you cannot change them). More can be found eg. in: www.rebol.org/advanced/mutable.r or in the Evaluation thread. Regards Ladislav second :f is different. It returns a "live" block of code (the body) with the contained words bound to the local frame of the function f. This block of code can be modified with and extended (with append etc. using 'bind if necessary) after the function is created. It seems clear that the interpreter executes the function by 'do-ing this body block. The original reason I originally questioned the relationship between functions and dialects in this thread was due to this "'do-ing the body block" concept. To make the question specific define a function f like this: f: func[/local x][x: {} append x "a" print x] My question then is, how are the first two values (x: {}) of the body block treated when the interpreter executes the function? In terms of purely executing the block, logically it seems, the first two values could be considered redundant, correct? A related issue (maybe), I don't know if it is been asked before. If I now use f, I get: f a f aa Compare this with another function g and its results: g: func[/local x][x: 0 x: add x 1 print x] g 1 g 1 Are these results related to the execution of a function or the interpretation of datatypes? Any enlightenment please? Brett.
[REBOL] Passing refinements to sub functions. Re:(2)
Hi, back from holiday. You might not notice, but Refined is a function defined in www.rebol.org/advanced/highfun.r It was my reaction to Michael's problem, but he pointed out, that he didn't want to use it because of its overhead... Regards Ladislav Rooting around Rebol sources as the official guide book recommends, I came across the following function (which would make my /refinements refinement unnecessary. Now to get it to work help refined USAGE: REFINED f refinements DESCRIPTION: Create a function doing the same thing as a function with given refinements does REFINED is a function value. ARGUMENTS: f -- (Type: any-function) refinements -- (Type: block) (SPECIAL ATTRIBUTES) catch - Original Message - From: "Brett Handley" [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, August 12, 2000 7:20 PM Subject: Re: [REBOL] Passing refinements to sub functions. Re: Thanks for your response Michael. Now that's an interesting idea. I think your approach is good at getting the refinements of the higher-function processed as a set, but it obscures what happens after that. My latest approach has been to use an additional refinement on the sub-function called /refinements. This has an argument of type block that contains pairs of refinement-name and refinement-value. Inspired by your work I produced this. main-func: function [/va /vb /vc][this-code refine-values r][ sub-func/refinements refinements-to-block :main-func va ] sub-func: function [/refinements refine-list][va vb vc][ do bind refine-list 'va print ["va:" va] print ["vb:" vb] print ["vc:" vc] ] refinements-to-block: function [ hi-func 'sample-refinement ][refinement-block][ refinement-block: copy [] foreach r first :hi-func [ if (refinement? r) and (r /local) [ append refinement-block to-set-word r append/only refinement-block to-paren bind reduce [to-word r] :sample-refinement ] ] compose refinement-block ] It results in this: main-func/vb/vc va: none vb: true vc: true Of course it doesn't handle any refinement arguments. Brett. - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Wednesday, August 09, 2000 1:35 AM Subject: [REBOL] Passing refinements to sub functions. Re: Well since I know you're thinking about asking for the solution I had come up with, I'll go all out and post it here. The actual solution to loop through the function items (refinements) is not much code, but is tedious and messy-looking. I feel like I'm going through alot of trouble to hide this and save a few characters in the "high-level" function, but the result is a little easier on the eye and made me learn about contexts and 'bind. ; Say you have a high-level function (main-func) with a list of refinements, and you want to pass all of these refinements to a lower-level function (sub-func). The bare parameter-passing code is: main-func: function [/va /vb /vc][this-code refine-values r][ this-code: make-code "main-func" "sub-func" bind this-code 'some-global bind this-code 'refine-values do this-code ] sub-func: function [param-list][va vb vc][ set [va vb vc] param-list print ["va:" va] print ["vb:" vb] print ["vc:" vc] ] ; Resulting in: main-func/va/vc va: true vb: none vc: true ; To support this you must define the following globally: some-global: none make-code: function [hi-func [string!] lo-func [string!]][code][ code: copy { refine-values: make block! [] foreach r first :hi-func [ if (refinement? r) and (r /local) [ append refine-values get bind to-word r 'refine-values ] ] lo-func refine-values } replace/all code "hi-func" hi-func replace/all code "lo-func" lo-func return(to-block code) ] - Michael Jelinek
[REBOL] problems with local vars??? Re:(8)
Hi, no "Dialect" notion can help you with your problem. (My personal preferences are, that Rebol functions aren't "Rebol dialect", because I think that there is a difference between a Rebol code in a block and a Rebol function, which has got more attributes, than Rebol code - see my Rebol function model in Words, Bindings and Contexts thread.) Back to your problem. The difference you see can be visualised here: a: "" b: :a append :b "a" probe :a a: 0 b: :a add :b 1 probe :a The results show, that there are differences between integers and strings in Rebol, Rebol strings are mutable (you can change them), while integers are immutable (you cannot change them). More can be found eg. in: www.rebol.org/advanced/mutable.r or in the Evaluation thread. Regards Ladislav second :f is different. It returns a "live" block of code (the body) with the contained words bound to the local frame of the function f. This block of code can be modified with and extended (with append etc. using 'bind if necessary) after the function is created. It seems clear that the interpreter executes the function by 'do-ing this body block. The original reason I originally questioned the relationship between functions and dialects in this thread was due to this "'do-ing the body block" concept. To make the question specific define a function f like this: f: func[/local x][x: {} append x "a" print x] My question then is, how are the first two values (x: {}) of the body block treated when the interpreter executes the function? In terms of purely executing the block, logically it seems, the first two values could be considered redundant, correct? A related issue (maybe), I don't know if it is been asked before. If I now use f, I get: f a f aa Compare this with another function g and its results: g: func[/local x][x: 0 x: add x 1 print x] g 1 g 1 Are these results related to the execution of a function or the interpretation of datatypes? Any enlightenment please? Brett.
[REBOL] Order of arguments to common words Re:
Interesting idea, Keith. Hi, I'm just wondering why this design choice was made: for pretty much any word that finds or picks, etc. a location out of a series, for example: print find "here and now" "and" blk: [red 123 green 456 blue 789] print select blk 'red 123 str: "REBOL" print pick str 2 E (all examples from the dictionary) the series is the first argument, and the index or the thing to find is the second argument. I'm just wondering why this is, because it seems like this makes it more confusing to string them together. For instance, with the way it is now, you would write something like: "skip skip [a b c d e] 2 2", which to make clearer with parentheses would be (skip (skip [a b c d e] 2) 2). How come it was chosen for it to be this way rather than being able to do "skip 2 skip 2 [a b c d e]", if the arguments were reversed? Just looking for some insight :) Thanks! Keith
[REBOL] Nonnegative remainder
Hi, does anybody know a simpler way how to compute: mod: func [ {compute a non-negative remainder} a [number!] b [number!] /local r ] [ either negative? r: a // b [ r + abs b ] [r] ] Regards Ladislav
[REBOL] Parse does not have not match type. Re:(3)
Hi, the latest version (see below) is better (the generated rule can be used recursively if needed): A-B-rule: func [ {Generate an A-B parse rule} A [block!] {A-rule} B [block!] {B-rule} /local o ] [ o: make object! [ A-rule: A B-rule: B res-rule: none ] bind/copy [ (self) [ B-rule (res-rule: [to end skip]) | (res-rule: A-rule) ] res-rule ] in o 'self ] { Example: a: [any "a" "b"] b: ["aa"] a-b: a-b-rule a b parse "ab" a-b parse "aab" a-b } not-rule: func [ "Generate a not A parse rule" A [block!] {A-rule} /local o ] [ o: make object! [ A-rule: A res-rule: none ] bind/copy [ (self) [ A-rule (res-rule: [to end skip]) | (res-rule: []) ] res-rule ] in o 'self ] { Example: a: [any "a" "b"] not-a: not-rule a parse "ab" not-a parse "b" not-a parse "" not-a } That's brilliant Ladislav. It took a little while to understand what magic you put there, and I learnt something as a result. I've made a few tests so far and cannot fault it. Thanks, Brett. - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Monday, July 31, 2000 4:06 AM Subject: [REBOL] Parse does not have "not" match type. Re: Hi, I think, that Parse has got a bug as in: parse "a" [none skip] == true cc-ing to feedback. Here is a version of A-B-rule, that should work reliably. Test it please. A-B-rule: func [ "Generate an A-B parse rule" A [block!] {A-rule} B [block!] {B-rule} /local o ] [ o: make object! [ A-rule: A B-rule: B res-rule: none ] bind/copy [ (self) [ B-rule (res-rule: [to end skip]) | A-rule (res-rule: []) | (res-rule: [to end skip]) ] res-rule ] in o 'self ]
[REBOL] What do I Do to determine the error? Re:
Hi, you can use Recycle explicitly at some points of your script to determine what is affected, for more info you can read Words, Bindings and Contexts thread. Normally it could mean, that one of your Contexts is already Garbage-collected, while you are trying to use a Word it contained... Regards Ladislav I get this message, ver 2.3.0.3.1, Invalid data type during recycle ** Press enter to quit... Larry
[REBOL] Parse does not have not match type. Re:(5)
Hi Zhang, the problem is the GC bug. If the bug didn't exist, (self) is unnecessary. As long, as the GC bug exists, (self) prevents the GC from collecting O. (for more information you can read Words, Bindings and Contexts thread) Regards Ladislav hi put up the question just in case i missed something+ seems could remove the (self) under bind/copy to achieve this function. or is it required for some reason? -z --- [EMAIL PROTECTED] wrote: Hi, the latest version (see below) is better (the generated rule can be used recursively if needed): A-B-rule: func [ {Generate an A-B parse rule} A [block!] {A-rule} B [block!] {B-rule} /local o ] [ o: make object! [ A-rule: A B-rule: B res-rule: none ] bind/copy [ (self) ; === here [ B-rule (res-rule: [to end skip]) | (res-rule: A-rule) ] res-rule ] in o 'self ] { Example: a: [any "a" "b"] b: ["aa"] a-b: a-b-rule a b parse "ab" a-b parse "aab" a-b } not-rule: func [ "Generate a not A parse rule" A [block!] {A-rule} /local o ] [ o: make object! [ A-rule: A res-rule: none ] bind/copy [ (self) [ A-rule (res-rule: [to end skip]) | (res-rule: []) ] res-rule ] in o 'self ] { Example: a: [any "a" "b"] not-a: not-rule a parse "ab" not-a parse "b" not-a parse "" not-a } That's brilliant Ladislav. It took a little while to understand what magic you put there, and I learnt something as a result. I've made a few tests so far and cannot fault it. Thanks, Brett. - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Monday, July 31, 2000 4:06 AM Subject: [REBOL] Parse does not have "not" match type. Re: Hi, I think, that Parse has got a bug as in: parse "a" [none skip] == true cc-ing to feedback. Here is a version of A-B-rule, that should work reliably. Test it please. A-B-rule: func [ "Generate an A-B parse rule" A [block!] {A-rule} B [block!] {B-rule} /local o ] [ o: make object! [ A-rule: A B-rule: B res-rule: none ] bind/copy [ (self) [ B-rule (res-rule: [to end skip]) | A-rule (res-rule: []) | (res-rule: [to end skip]) ] res-rule ] in o 'self ] __ Do You Yahoo!? Kick off your party with Yahoo! Invites. http://invites.yahoo.com/
[REBOL] Truncation Re:(3)
Hi Paul, for more info see www.rebol.org/math/rounding.r Regards Ladislav Damn I thought I tried that. Thanks, I knew it was something simple. -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Monday, July 31, 2000 12:50 PM To: [EMAIL PROTECTED] Subject: [REBOL] Truncation Re: Hi Paul Well for numbers of absolute magnitude less than 2,147,483,647 (i.e., within the range of the integer datatype) you can do this: to-integer 47.2393 == 47 HTH -Larry - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Monday, July 31, 2000 10:31 AM Subject: [REBOL] Truncation How do you truncate a number. For example if I have the following: num: 47.2393 How do I get just the 47. I want to return only the first part before the decimal and do NOT want to round the number. Paul Tretter
[REBOL] Parse does not have not match type. Re:
Hi, I think, that Parse has got a bug as in: parse "a" [none skip] == true cc-ing to feedback. Here is a version of A-B-rule, that should work reliably. Test it please. A-B-rule: func [ "Generate an A-B parse rule" A [block!] {A-rule} B [block!] {B-rule} /local o ] [ o: make object! [ A-rule: A B-rule: B res-rule: none ] bind/copy [ (self) [ B-rule (res-rule: [to end skip]) | A-rule (res-rule: []) | (res-rule: [to end skip]) ] res-rule ] in o 'self ]
[REBOL] Parse does not have not match type.
Hi, try this: (but look out!) As long, as Rebol functions are CQSB with DRP, there are problems with Rule-res word local to A-B-rule function. A-B-rule: func [ "Generate an A-B parse rule" A [block!] {A-rule} B [block!] {B-rule} /local succeed fail rule-res ] [ [[B to end (rule-res: [none skip]) | A (rule-res: [])] rule-res] ] Regards Ladislav
[REBOL] Words, Bindings and Contexts. (8)
The last part was about the behaviour of Rebol Functions. The present behaviour can be called "Computed Quasi Static Binding with Dynamic Recursion Patch." Interesting about the "Computed Quasi Static Binding" is, that it can handle recursion even without the "Dynamic Recursion Patch", as can be seen in the next model: ; Model of Context creation: ; ** make-context: func [ {create a Context containing given Words} words [block!] /local context-init result ] [ ; this implementation has got an issue: ; the created Context always contains 'Self words: difference/only words [self] context-init: make block! 4 * length? words foreach word words [ append context-init to set-word! word append context-init none append context-init :unset append context-init to lit-word! word ] result: make object! context-init unset in result 'self result ] { The following version of Same-context? uses Make-context to look more natural: } same-context?: func [ {find out, if the given Words are the Words of the same Context} word1 [word!] word2 [word!] ] [ either special-context? word2 [ special-context? word1 ] [ same? word1 bind in make-context reduce [word1] word1 word2 ] ] ; Model of CQSB function: ; * cqsb-function!: make object! [ ; every cqsb function has got a Spec attribute spec: none ; every cqsb function has got a Body attribute body: none ] ; Model of CQSB Func function: ; * cqsb-func: func [ {create a CQSB-function!} spec [block!] body [block!] /local spec-too body-too ] [ spec-too: copy spec body-too: copy/deep body make cqsb-function! [ spec: spec-too body: body-too ] ] ; Model of the CQSB function body execution: ; *** ; the same as for Sim-function do-body: func [body] [do body] ; Model of CQSB function Evaluation: ; *** cqsb-evaluate: func [ {evaluate a sim-function contained in a block with its arguments} block [block!] /local cqsb-f new-context actual-values ] [ ; evaluate the arguments block: reduce block ; the executed cqsb-function is first cqsb-f: first block ; create a new Context new-context: make-context cqsb-f/spec ; give new Context words the supplied values set/any bind/copy cqsb-f/spec in new-context 'self next block ; execute the function body and return the result return do-body bind/copy cqsb-f/body in new-context 'self ] ; Some tests: ; ** blk: copy [] probeblk: func [] [ prin mold blk prin ": " print mold reduce blk ] recfun: cqsb-func [x] [ append blk 'x either x = 1 [ probeblk ] [ cqsb-evaluate [recfun x - 1] ] ] cqsb-evaluate [recfun 3] probeblk { Results: cqsb-evaluate [recfun 3] [x x x]: [3 2 1] probeblk [x x x]: [3 2 1] This shows, that "Pure CQSB" looks better than "CQSB with DRP". Recursion is not the only case, where "Pure CQSB" looks better. For another example, see this: } f: func [x] ['x] y: f 1 z: f 2 get y { Results: get y == 2 While Pure CQSB yields: } f: cqsb-func [x] ['x] y: cqsb-evaluate [f 1] z: cqsb-evaluate [f 2] get y { and the results: get y == 1 But, as always, everything has got its price. Pure CQSB is more demanding (every call needs a new Context/Binding). Moreover, the above implementation is not GC-bug proof. } to be continued...
[REBOL] Words, Bindings and Contexts. (9)
; Model of Use behaviour: ; *** sim-use: func [ "Defines words local to a block." words [block! word!] "Local word(s) to the block" body [block!] "Block to evaluate" /local context ] [ if word? words [words: reduce [words]] ; create the Context context: make-context words do bind body in context 'self ] { The described behaviour has got its drawbacks (See Bug in Use?). There is a possibility to improve the behaviour, see the next model: } r-use: func [ "Defines words local to a block." words [block! word!] "Local word(s) to the block" body [block!] "Block to evaluate" /local context ] [ if word? words [words: reduce [words]] ; create the Context context: make-context words do bind/copy body in context 'self ] { The last subject left is the behaviour of make object!. Here it is: } make-object!: func [ {make object! simulation} spec [block!] /local words result ] [ words: make block! 0 foreach elem spec [ if set-word? get/any 'elem [ append words to word! elem ] ] result: make-context words result/self: result do bind spec in result 'self return get/any in result 'self ] { Analogically as above, this code is not well-behaved in some circumstances. I would prefer the following: } r-make-object!: func [ {make object! simulation} spec [block!] /local words result ] [ words: make block! 0 foreach elem spec [ if set-word? get/any 'elem [ append words to word! elem ] ] result: make-context words result/self: result do bind/copy spec in result 'self result ]
[REBOL] Re: highfun.r
Hi Brett, the script can be found at http://www.rebol.org/advanced/highfun.r Regards Ladislav Hi Ladislav, I cannot seem to find the script highfun.r in either www.rebol.com or www.rebol.org I have a copy and find it very useful. I suspect others would too. So just wondering if you would not mind posting up to one of these sites? Brett.
[REBOL] Bug in 'use? Re:(3)
The following has been written: Hi Ladislav, 15-Jul-2000 you wrote: you are right, the problem is caused by a context manipulation - Use unsets your Middle every time it gets executed. My suggestion is to not use Use in recursive functions, while this problem doesn't get corrected. Judging from the nature of recursiveness, that's a little hard, isn't it? ;-) Do you know if this problem has already been reported to feedback? Kind regards, -- Ole Friis [EMAIL PROTECTED] here is a pretty simple example showing the problem: temporary: "global temporary" recfun: func [level] [ use [temporary] [ if level 1 [ temporary: "temporary" recfun level + 1 print ["Temporary:" temporary] ] ] ] recfun 0 ; The result: ** Script Error: temporary has no value. ** Where: temporary ; let's define a function r-use like this: r-use: func [ "Defines words local to a block." words [block!] "Local word(s) to the block" body [block!] "Block to evaluate" ] [ do function [] words body ] ; and now use R-use instead of native Use temporary: "global temporary" recfun: func [level] [ r-use [temporary] [ if level 1 [ temporary: "temporary" recfun level + 1 print ["Temporary:" temporary] ] ] ] recfun 0 ; The result: Temporary: temporary Ladislav
[REBOL] APL'ish operations Re:(5)
Hi, I was thinking in terms of function projection. Take a binary function (like + ), fix one of the arguments (5) and create a monadic (?) function that can be applied to say a vector. Sorry if all this seems like elementary stuff, I'm just starting with REBOL and exploring the possibilities. It is not that elementary, but with a help of http://www.rebol.org/advanced/highfun.r you can do: block-add-5: mapper (do curry :add 1 5) block-add-5 [1 2 3] == [6 7 8] Regards Ladislav --- [EMAIL PROTECTED] wrote: Perfect. Just what I needed. Wish there was a way to make simple one-off functions in a block like [ + 5] etc. I think you can. Again according to what you need. This is where Rebol shines. Rebol gives you the ability to interpret blocks (and strings) in way other than the default provided by Rebol. That is, according to your own grammar. Rebol calls this a dialect. Admittedly this is not straight-forward when you're beginning with Rebol. On the other-hand once you have done this a few times, you will see opportunities for it everywhere and discover that it really is not as complex as it sounds. One way to achieve this is to interpret a block by stepping through it and checking types then doing something. Another way is to use the parse function of rebol. Parse takes a string or a block as input plus a grammar specification that will interpret your input according to rules. So to your example. What would [+ 5] actually do and how would it be used? Brett. = __ Do You Yahoo!? Get Yahoo! Mail - Free email you can access from anywhere! http://mail.yahoo.com/
[REBOL] Bug in 'use? Re:(12)
Hi Elan, you wrote: (...) I conclude from Carl's comment that bind's intended behavior is to bind the block such that all words that occur in the block behave as they would, if the block had been defined in the context it is being bound to. I.e. if print [g-arg f-arg global-word] evaluated in the g function's context were to generate This is g's argument. This is f's argument. This is the global word. then print bind [g-arg f-arg global-word] g's-context-word should generate the same result. If it doesn't, then it is - in Carl's words - a bug. Hierarchic context table inheritance is REBOL's intended behavior. I think, that here is the main difference between your "Mental Model Approach" and our approach: We, not having the official description, are writing the description of Rebol behaviour, while you are trying to describe the "Intended Behaviour", that surely differs. Problem with your approach is, that you neither know the Rebol "Intended Behaviour" not being its creator, nor are able to correctly describe the actual behaviour, because you don't even try to do it. Regards Ladislav f-arg: "Global f-arg!" == "Global f-arg!" print bind [g-arg f-arg global-word] g's-context-word This is g's argument. Global f-arg! This is the global word. So, how does it work when calling F? When F is created, a new context table is created. Thank you. I went to pains to demonstrate that. Then the BIND function is called to bind Metaphorically speaking? I have never seen the bind function called during the construction of a function. If you source func and function, you will find that neither of these mezzanine functions call bind. They both use make function! ... and I have no access to the code that is executed when make function! is called. the body block to that context table (this means binding each word in the block and the blocks (any-block!s actually) it contains, but only if present in the context table). So when F is created the block: [ print [g-arg f-arg global-word] ] gets bound to F's context; more precisely, the word "f-arg" gets bound to F's context, while "print", "g-arg" and "global-word" aren't changed (so they're still bound to the global context). I think this is a conceptual problem. There is no g-arg defined in the global context. Accordingly "g-arg" was never bound to the global context. Therefore "g-arg" cannot "still" be bound to the global context. When F is executed, the function G is created, and thus the block above gets bound to G's context. Again, only the word "g-arg" is affected, while "print" and "global-word" are left bound to the global context and "f-arg" to F's context. Thank you. Note what you are saying here. You are looking at this from a different perspective, an implementation perspective, - nevertheless - you are formulating a mechanism that exactly results in context inheritance. You may dislike the term "context (table) inheritance", but I think it expresses the fact quite well that words used - but not defined - in an embedded function, are interpreted in the context of their parent function - provided they are defined in that function. Or in their immediate parent's parent function ... until the global context is reached. Your implementation view (though speculative, but reasonable) supports my conceptual representation, don't you think? The result is what you expect, with "f-arg" bound to F's context, "g-arg" bound to G's context and "global-word" bound to the global context, but this is only a (wanted) side effect of REBOL static binding. r Example 2 for Context Hierarchy: [...] The same goes here. No hierarchy needed. No hierarchy "needed"? Did you not begin by claiming in your previous email Anyway, I can prove that there is no context hierarchy: then continue by saying in this email So, let's prove there's no hierarchy here: Now "No hierarchy NEEDED" has become the "same" as proving "there's no hierarchy here:"? After describing a speculative process (albeit a reasonable one) that brings about a behavior, which can be described - with precision - as a context table hierarchy, you have lowered your attack from "I can prove that there is no context hierarchy" to "no hierarchy needed"? Perhaps having thought through a process through which REBOL's hierarchical context behavior may be implemented, your opposition to this concept has become weaker, from proving "there's no hierarchy" to avoiding the hierarchy use of the word hierarchy, "no hierarchy needed"? Your speculation regarding the binding of words during the function's construction is only reasonable, because we know already, that the construction will eventually have to lead to a behavior that is consistent with the observable hierarchic behavior that REBOL displays, when it resolves words in embedded functions. r is based on the assumption that "embedded" objects are
[REBOL] Bug in 'use? Re:(12)
Hi, The discussed code: f: func [f-arg] [ g: func [g-arg] [ print [g-arg f-arg global-word] ] g "This is g's argument." ] Gabriele: So when F is created the block: [ print [g-arg f-arg global-word] ] gets bound to F's context; more precisely, the word "f-arg" gets bound to F's context, while "print", "g-arg" and "global-word" aren't changed (so they're still bound to the global context). Elan: I think this is a conceptual problem. There is no g-arg defined in the global context. Accordingly "g-arg" was never bound to the global context. Therefore "g-arg" cannot "still" be bound to the global context. Here is a proof: global? probe first second fourth second :f g-arg == true Regards Ladislav
[REBOL] Bug in 'use? Re:(12)
Hi, Gabriele: Then the BIND function is called to bind Elan: Metaphorically speaking? I have never seen the bind function called during the construction of a function. If you source func and function, you will find that neither of these mezzanine functions call bind. They both use make function! ... and I have no access to the code that is executed when make function! is called. You have never seen just because you didn't try. See the following: code-block: [ f: func [f-arg] [ g: func [g-arg] [ print [g-arg f-arg global-word] ] g "This is g's argument." ] ] do code-block f-body: second :f f-body-f-arg: probe second second fourth f-body f-body-template: fourth code-block bound-f-body-template: bind/copy f-body-template f-body-f-arg same? first bound-f-body-template first f-body same? second bound-f-body-template second f-body same? first third bound-f-body-template first third f-body same? first fourth bound-f-body-template first fourth f-body same? first second fourth bound-f-body-template first second fourth f-body same? second second fourth bound-f-body-template second second fourth f-body But: same? second second fourth f-body-template second second fourth f-body Ladislav
[REBOL] Words, Bindings and Contexts. (7) Re:(2)
Hi, HI Ladislav Very cool! Use of simulated behavior (implemented in REBOL) is a concise and precise way of expressing one's thoughts about the workings of REBOL functions. I find it much more informative than lengthy attempts to describe in ordinary language how functions work. I have followed your Words, Bindings, and Contexts posts with great interest. I have learned a lot from your discussions and hope to see more. Just a couple of quick questions: Can you say more about Dangerous Contexts? For instance: f: func [x][return x] first :f == [x] type? first first :f == word! value? first first :f;REBOL crashes on any attempt to examine the words in first :f Isn't this just a bug in REBOL? Why does it not return an error instead of crash? How about a modifying to sim-func to allow handling of /local and refinements? Then it would be a more complete model of func. Thank you again for sharing this excellent material. -Larry 1) I think, that every Rebol Context becomes Dangerous after being Garbage Collected while still accessible, ie. Dangerous Contexts may be just "Ghost Contexts" of once normal Rebol Contexts... 2) My intent was to describe the Rebol Context Handling and the refinements would complicate the code beyond the limit I considered acceptable. (BTW, if you consider Sim-function/spec as containing all Function Context's Words ie. Arguments, Refinements, Words specified as /local, everything holds, the things that should be added are the examination of a call-path used, a code to supply None as the value for respective Function Context's Words, a code for spec parsing and the type checking code.) .
[REBOL] Bug in 'use? Re:(11)
Hi Volker, no, the behaviour is correct. Try this: unset 'b a: make object! [b: none unset 'b if not value? 'b [b: "a bee!"]] a/b [rebol[author: "Volker"] {seems 'make does no deep binding? without bug this should set 'b in object-context too (hopefully)?} unset 'b a: make object! [if not value? 'b [b: "a bee!"]] b a/b ] unset 'b a: make object! [if not value? 'b [b: "a bee!"]] b == "a bee!" a/b ** Script Error: Invalid path value: b. ** Where: a/b That looks like a bug. -Carl Anyway, I can prove that there is no context hierarchy: a: 1 b: 1 c: 1 == 1 obj1: make object! [ [a: 2 [obj2: make object! [ [b: 2 [obj3: make object! [ [c: 2 [] [] [] blk: [a b c] == [a b c] print blk 1 1 1 print bind blk in obj1/obj2/obj3 'self 1 1 2 If contexts where organized hierarchycally the output would have been "2 2 2".
[REBOL] Bug in 'use? Re:(11)
Me too. Hello [EMAIL PROTECTED]! On 25-Lug-00, you wrote: c That looks like a bug. -Carl Hmm... do you have some little spare time to tell us how contexts work? Isn't binding done word-by-word? Isn't hierarchy achieved by multiple pass binding? You're confusing me, now. :-) Regards, Gabriele. -- Gabriele Santilli [EMAIL PROTECTED] - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[REBOL] Words, Bindings and Contexts. (7)
I see, that the fact, that my series didn't explain the behaviour of functions WRT Recursion and Binding is a flaw. Here is the continuation (a model of the behaviour): ; Model of Rebol function: ; sim-function!: make object! [ ; every function has got a Context attribute context: none ; every function has got a Spec attribute spec: none ; every function has got a Body attribute body: none ; every function has got a provision for Recursion recursion-level: 0 stack: none ] ; Model of Func function: ; *** sim-func: func [ {create a Sim-function!} spec [block!] body [block!] /local context-init spec-too body-too ] [ ; first of all, the function context should be created context-init: make block! 1 + length? spec foreach word spec [ append context-init to set-word! word ] append context-init none spec-too: spec body-too: body make sim-function! [ ; create context context: make object! context-init ; a simplification here spec: bind/copy spec-too in context 'self ; this is the secret of "Context Hierachy" body: bind/copy body-too in context 'self ; Create a stack for storing values during recursive calls stack: copy [] ] ] ; Model of the function body execution: ; ** do-body: func [body] [do body] ; Model of the return from function: ; ** sim-return: func [ sim-f value [any-type!] ] [ ; restore the former values from stack, if needed if (sim-f/recursion-level: sim-f/recursion-level - 1) 0 [ set/any sim-f/spec first sim-f/stack ; finish the stack-pop sim-f/stack: remove sim-f/stack ] ; return the value return get/any 'value ] ; Model of function Evaluation: ; * sim-evaluate: func [ {evaluate a sim-function contained in a block with its arguments} block [block!] /local sim-f actual-values ] [ ; evaluate the arguments block: reduce block ; the executed sim-function is first sim-f: first block ; detect recursion if (sim-f/recursion-level: sim-f/recursion-level + 1) 1 [ ; get the actual values of local words actual-values: copy [] foreach word sim-f/spec [ append/only actual-values get/any word ] ; push the actual values to stack sim-f/stack: head insert/only sim-f/stack actual-values ] ; give local words the supplied values set/any sim-f/spec next block ; execute the function body and return the result return sim-return sim-f do-body sim-f/body ] ; Some tests: ; ** blk: copy [] probeblk: func [] [ prin mold blk prin ": " print mold reduce blk ] recfun: sim-func [x] [ append blk 'x either x = 1 [ probeblk ] [ sim-evaluate [recfun x - 1] ] ] sim-evaluate [recfun 3] probeblk
[REBOL] Words, Bindings and Contexts. (5)
In the part 4 I forgot to introduce a special kind of Contexts: f) Dangerous Contexts. Example: f: func [x] [] special-context? first first :f CRASH I obviously cannot claim that Same-context? works in this case. Now I supply another interesting function: ; actually, Thomas Jensen was first there (nice work), but this function is able to find even the Unset Words context-words: func [ {returns all Context Words of a Word's Context} word [word!] /local result c-word ] [ either special-context? word [ ; we are out of luck in this case none ] [ result: copy [] foreach g-word first system/words [ if not same? g-word c-word: bind g-word word [ append result c-word ] ] result ] ] to be continued...
[REBOL] Words, Bindings and Contexts. (6)
In the previous sections I answered some questions regarding Contexts. The lifetime Contexts: * The Global Context should last forever, Local Context have indefinite extent, which should mean, that if there were no GC bugs, they should last as long, as they are accessible. Now something on Bindings: Bindings revealed: ** I think, that I succeeded to demonstrate, that every Rebol Word has got a Context attribute. The next attribute everybody is familiar with, is its Mold attribute. It is simply the value that can be obtained by: mold 'word The Context and Mold attributes are normally enough to characterize a Rebol Word. A special case can be discussed: Aliases. As a toy I present a function able to find out, if two given words are aliases of each other: aliases?: func [ {find out, if word1 and word2 are aliases} word1 [word!] word2 [word!] ] [ all [ ; aliases are equal in Rebol equal? word1 word2 ; but have different Mold attributes not equal? mold word1 mold word2 ] ] Aliases are not currently considered by Rebol as the same Words. (Because their Mold attributes differ?) Observation concerning Rebol Words is as follows: Two Words are the same, if their Context attributes are the same and their Mold attributes are equal. (This would be true probably for all Contexts, but we haven't got the means to check the case of Special Contexts and Dangerous Contexts.) Example illustrating, that the same value and equality of Words doesn't mean the same Binding: blk: copy [a] a: 11 b: make object! [append blk 'a a: 11] print [ mold blk ":" mold reduce blk ] print [ "Do the first and the second element above have the same Binding?" same-context? first blk second blk ] What I didn't discuss, is the case of recursive functions in Rebol, but I hope, that somebody finds even the present text helpful. (If any of the questions at the beginning remains unclear, feel free to ask.) Ladislav
[REBOL] sorry, meant Words, Bindings and Contexts. (4) Re:(2)
Hi Volker, no problem, but I didn't receive it (why?) Ladislav wrote [REBOL] Words, Bindings and Contexts. (5) which is of course (C) [EMAIL PROTECTED] :) sorry, Ladislav, must have thought Re's are now counted :) concentration.. Volker
[REBOL] Words, Bindings and Contexts. (4)
Note: The last two sections (Context Hierarchy. Pardon?; "Context hierarchy"? Aye, aye, sir!) were complicated and not very useful, but they can be skipped. What are Rebol Contexts? * Rebol Contexts are existing data, sometimes available to the user. They are used internally by Rebol for the purposes of many Core functions. Their main purpose is to serve as attribute of Rebol Words - ie. Rebol Context is a part of any Word's Binding - in different wording: every Rebol Word knows its Context. Proof: see the function Same-context? defined in part 3. Known Rebol Contexts: Available directly as: a) Global ContextRebol/Words b) Objectsthemselves c) Function Contexts not available d) Use Contexts not available e) Special Contextsnot available Properties: a) Global Context is the Default Context - Words are normally Global Context Words, if not stated otherwise. b) Objects are Local Contexts - as opposed to Global Context. They are created by Make native. The list of Words object O "contains" - ie. the list of Words that are local to O is available as First O. But look out! There is a catch - the elements of First O are equal to local O's Words, but the elements of First O are Special Context Words. To obtain a list of Words really local to O, one must do: words-local-to-o: bind first o in o 'self c) Function Contexts are Local Contexts too. They are attributes of functions and are created when the respective functions are created. Function Contexts contain: all argument Words, all refinement Words, all optional argument Words and all local Words specified by /local refinement. (you can verify it for particular examples by using Same-context? function). d) Use Contexts are Local Contexts and are created when the respective Use function is evaluated. They contain the Local Words specified by the first argument of Use. e) Special Contexts - see a note under Object Contexts, other example: a: "q" a: make block! a get first a Here First A is a Special Context Word too. The problem is, that Bind doesn't work for Special Contexts, which means, that our Same-context? function doesn't work too. Here is an improved version: special-context?: func [ {determines, if a word is a Special Context Word} word [word!] ] [ error? try [error? get/any word] ] ; this function can help us explore the Contexts, that aren't directly available same-context?: func [ {find out, if the given Words are the Words of the same Context} word1 [word!] word2 [word!] ] [ either global? word1 [ global? word2 ] [ either special-context? word2 [ special-context? word1 ] [ same? word1 bind global word1 word2 ] ] ]
[REBOL] REBOL's scoping rules Re:(5)
Hi Rebols, Brian wrote: Here's some REBOL pseudo-code of this (for block! spec): make-object: func [spec [block!] /local c o] [ c: copy [self] foreach x spec [ all [ set-word? x none? find c (x: to-word x) insert tail c x ] ] o: make-context c ; Here's the "pseudo-" part o/self: o spec: bind/copy spec in o 'self do spec o/self ; NOT o, for some reason ] Because the way Make Object! works limits the manipulation with 'self during the object creation, here is a code, that overcomes the limitation: Rebol [ Title: "MakeObject" Date: 20/7/2000 File: %mkobject.r Author: "Ladislav Mecir" Email: [EMAIL PROTECTED] Purpose: { Equivalent of Make Object!, but unlike it Self can be manipulated } Category: [General] ] make-object: func [ {make object} blk [block!] "object spec" /local result getres ] [ getres: func [value] [result: :value] blk: head insert insert copy blk :getres [:self] make object! blk result ] { Example: o: make-object [a: 1 self: 2] o/self }
[REBOL] roundoff? Re:
Hi, see also www.rebol.org/math/rounding.r I needed a simple two decimal place round off function for a script this evening. This is what I came up with: roundoff: func ["Rounds off to 2 decimal places" a][ a: a * 100 b: a - to-integer a a: to-integer a if b .5 [a: a + 1] a: divide a 100 ] Here's how it works: roundoff 10.567890 == 10.57 roundoff 10.56 == 10.56 Can anyone improve on this, or is there a function already in REBOL I overlooked? Okay, yes, to-money does it: to-money 10.567 == $10.57 to-money 10.563 == $10.56 but I want the decimal! type. --Ralph Roberts
[REBOL] Bug in 'use? Re:(3)
Hi, Hi Ladislav, 15-Jul-2000 you wrote: you are right, the problem is caused by a context manipulation - Use unsets your Middle every time it gets executed. My suggestion is to not use Use in recursive functions, while this problem doesn't get corrected. Judging from the nature of recursiveness, that's a little hard, isn't it? ;-) Do you know if this problem has already been reported to feedback? Kind regards, -- Ole Friis [EMAIL PROTECTED] Amiga is a trademark of Amiga Inc. You should probably report it to feedback. BTW, did you succeed to sort the permutations correctly? One more question for everybody. What do you want to see after executing: blk: copy [] probeblk: func [] [ prin mold blk prin ": " print mold reduce blk ] recfun: func [x] [ append blk 'x either x = 1 [ probeblk ] [ recfun x - 1 ] ] recfun 3 probeblk Regards Ladislav
[REBOL] REBOL's scoping rules Re:(2)
Hi, I've been wondering what the reasoning behind REBOL's scoping rules was for awhile. In C, for instance, any variable that you declare in a function is "automatic" (that's what C calls them anyway :). They're automatically local to the function they're defined in, etc. (...) Why does REBOL have variables be globally scoped by default? I ran into this a few days ago when I asked the list for assistance, and people helpfully replied (thank you). One of the things people pointed out was that I wasn't being careful with my recursion and kept using the same global variable over and over again. (...) Anyway, I'd really like to understand why REBOL works the way it does in this respect, so if anyone has any insight to give I'd love to receive it. Thanks so much. Keith In Rebol you need the core words to start writing the code (no "reserved words" as in other languages). The core words are all global and it would have been impossible to declare them as global in every block. Other languages use a "trick" - the counterparts of some Rebol global words are not globals, but "reserved words", that are globally available without any declaration... Ladislav
[REBOL] Bug in 'use? Re:(6)
Hi Elan, You wrote: "During recursive calls, REBOL is using a dynamic binding for 'x, which means that each instance of recfunc, called from within recfunc recursively, has its own context in which 'x is bound to the value that was passed to the recfunc instance." I would like to divide the paragraph into two parts: "During recursive calls, REBOL is using a dynamic binding for 'x." That looks allright, but the next part makes a problem: "...each instance of recfunc, called from within recfunc recursively, has its own context in which 'x is bound to the value that was passed to the recfunc instance" This is true for non-Rebol notion of "contexts". Once we compare this to Rebol Contexts, we see: blk: copy [] probeblk: func [] [ prin mold blk prin ": " print mold reduce blk ] recfun: func [x] [ append blk 'x either x = 1 [ probeblk probe same? first blk second blk ] [ recfun x - 1 ] ] recfun 2 The results: recfun 2 [x x]: [1 1] true == true While: blk: copy [] probeblk: func [] [ prin mold blk prin ": " print mold reduce blk ] fun1: func [x] [ append blk 'x either x = 1 [ probeblk probe same? first blk second blk ] [ fun2: func [x] [ append blk 'x probeblk probe same? first blk second blk ] fun2 x - 1 ] ] fun1 2 And the results: fun1 2 [x x]: [2 1] false == false From that is clear, that in the case of Recfun, there is only one 'x. Words 'x inserted to Blk as the first and the second element are in fact just one word 'x that was bound to just one Rebol Context - the (dynamic) Rebol Context of Recfun, while two Rebol Contexts in the case of Fun1 and Fun2 mean two words 'x in Blk, each bound to a different Rebol Context (Fun1's context's 'x and Fun2's context's 'x). Similarly the next statement's first part: "Once the recursion expires the context of 'x is again bound to the value it last had before recfunc called itself recursively..." Is true, if we consider a different kind of binding - "Value Binding", because "Context Binding" remains the same, the only thing changing between Recfun calls is the value of 'x. While the second part: "Once the recursion expires (...), it ('x) is bound in the static context of the top-level instance of the recfunc function." Can not be interpreted as Rebol Context change, because Rebol Context remains the same - namely that of Recfun and no Rebol Context change is necessary. As you pointed out, there is a conflict of two things: "Static Context Binding" vs. "Dynamic Value Binding". As a consequence, Use may misbehave during recursive calls. Regards Ladislav Hi Ladislav, Brett, Ladislav wrote: blk: copy [] probeblk: func [] [ prin mold blk prin ": " print mold reduce blk ] recfun: func [x] [ append blk 'x either x = 1 [ probeblk ] [ recfun x - 1 ] ] recfun 3 probeblk To which Brett replied I would have expected [3 2 1] not [1 1 1] nor [3 3 3]. What you are demonstrating, Ladislav, is IMHO a conflict that results from the fact that REBOL is using two different binding mechanisms. During recursive calls, REBOL is using a dynamic binding for 'x, which means that each instance of recfunc, called from within recfunc recursively, has its own context in which 'x is bound to the value that was passed to the recfunc instance. Once the recursion expires the context of 'x is again bound to the value it last had before recfunc called itself recursively, it is bound in the static context of the top-level instance of the recfunc function. So 'x exists in multiple contexts: the static context of the function recfunc, and the temporary dynamic contexts, that are created for each recfunc instance, when recfunc calls itself recursively. When you reduce blk from within a recursively called instance of recfunc, 'x is bound in the temporary dynamic context of the recursively called function's instance. Once recfunc's loop expires and there are no more recursively called instances of recfunc effective, then 'x is once again bound in the context of the top-level recfunc function, its static context, and the reduced block evaluates to the value that 'x is bound to in that context. At 11:44 PM 7/19/00 +1000, you wrote: I would have expected [3 2 1] not [1 1 1] nor [3 3 3]. But I find it difficult to answer what I want, because the function argument x seems like it's in a bit of a no-mans land (I'm thinking of :x ) My brain hurts now. :) Brett. - Original Message - From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Wednesday, July 19, 2000 5:03 PM Subject: [REBOL] Bug in 'use? Re:(3) Hi, Hi Ladislav, 15-Jul-2000 you wrote: you are right, the problem is caused by a context manipulation - Use unsets your Middle every time it gets executed. My suggestion is to
[REBOL] bugs in Rebol/Core 2.3 Re:
Hi, (...) the recently added 'unique function ignores the /case refinement. it doesn't even look at it's refinement, it just passes its argument to 'union. Moreover, the implementation is very inefficient, compare with this: unique: func [ "Returns a set with duplicate values removed." set [series! bitset!] /case "Use case-sensitive comparison" ][ either case [union/case set make set 0] [union set make set 0] ] Ladislav
[REBOL] Find cant find reference to block. Re:(5)
Hi, From: [EMAIL PROTECTED] probe find/only reverse_lookup :e ; The answer: [[] "a" ["added to the series"] "b" [] "c"] == [[] "a" ["added to the series"] "b" [] "c"] Thanks, but no - I tried that too. I wanted this to return [[] "c"] since that was what "e" was referring to. So, you needed a function sfind? sfind: func [ {finds the same value as a given one in a given series} series [series!] value [any-type!] ] [ while [not tail? :series] [ if same? first :series get/any 'value [ return :series ] series: next :series ] none ] probe sfind reverse_lookup :e ; The answer: [[] "c"] == [[] "c"] Regards Ladislav
[REBOL] Relative to Absolute Paths (again). Re:
Hi, you can try parse page: read http://site [ some [ thru "=^"/" here: (insert back here "http://site") ] to end ] Hello. I once asked about this problem and it's partially solved (thanks to everyone that helped me), but there is one minor problem that I'm usable to solve. What I want to do is read and HTML page and change all relative paths to absolute ones. For example: Change img src="/path/file" To img src="http://site/path/file" or Change a href="/path/file" To a href="http://site/path/file" Here is the partial solution to the problem: parse page: read http://site [ some [ thru "=^"/" here: (insert here "http://site") ] to end The problem here is that, with this code, I end up with something like img src="/http://sitepath/file" As you can see, the "http://site" string is being inserted in the wrong position. How do I fix it in the above sample code? Thanks. -Bruno -- Bruno G. Albuquerque ([EMAIL PROTECTED]) BeDevId 15362 Grupo Brasileiro de Usuarios de BeOS - Presidente http://beos.din.uem.br "I am returning this otherwise good typing paper to you because someone has printed gibberish all over it and put your name at the top." -- English Professor, Ohio University
[REBOL] func[func] Re:(7)
Hi, Hi Jeff You wrote: save-em: copy [] make-adder: func [x][ get in last append save-em make object! [ z: x f: func [y][+ z y] ] 'f ] The above creates new contexts to hold the different values of X in your separate add functions. (It also creates new functions that use those X values). Nice and it works. One can also tidy things up by encapsulating the block of saved items in the function which also illustrates a practical use of the behavior of literal blocks contained in functions. make-add: func [x][ saved: [] get in last append saved make object! [ z: x f: func [y][+ z y] ] 'f ] Cheers -Larry an even more tidy approach is to use www.rebol.org/general/sfun.r make-add: func [x][ sfun [z: x] [y][+ z y] ] Ladislav
[REBOL] func[func] Re:(8)
Hi Brian, You wrote: (...) When the function is recursed into a new context has to be created to make it reentrant. That is not true, as can be proven. The context remains the same, only the old values are saved (stack?) and restored after return... When that function returns, the new context is lost. The original is still there to be reused, though. Recursive functions are much like using the USE operation, with all of the overhead and GC-related context concerns. Not exactly, see above... Ladislav
[REBOL] bug ? Re:(3)
Hi, What I'm saying is that it is not consistent with the philosophy in Rebol. Datasets are not a datatype, it is a human convention. Take note of the help message : arg must be a series. Files are read as series. But yet difference won't work on them. Inconsistent. it works as described, not as you expect: difference %file1 %file2 == "12" what gets compared is the %file1 and %file2 as the series, not their contents. Ladislav
[REBOL] more context clues Re:
Hi, Thanks to Joe Marshall for his extremely helpful explanation of Rebol 1 vs. Rebol 2 and contexts and GC. Where did you get it? (Didn't I receive something?) Ladislav
[REBOL] Function and variable scope Re:
Hi, Hi all, A naïve question : how do you define a local variable in a function and then return it: Instead of this : dirtree: make block! 100 list-dirs: func [ "returns dir tree as block" dir [file!] "root dir" ] [ foreach name read dir [ if dir? dir/:name [ append dirtree dir/:name list-dirs dir/:name ] ] dirtree ] Something like this : list-dirs: func [ "returns dir tree as block" dir [file!] "root dir" ] [ dirtree: make block! 100 foreach name read dir [ if dir? dir/:name [ append dirtree dir/:name list-dirs dir/:name ] ] dirtree ] Problem is that " print list-dirs %/root " only works with the first block of code, not the second. What do I get wrong ? -- [EMAIL PROTECTED] http://perso.worldonline.fr/mutant You can do it as follows: list-dirs: func [ "returns dir tree as block" dir [file!] "root dir" /local dirtree rlist-dir ] [ dirtree: make block! 100 rlist-dir: func [ dir ] [ foreach name read dir [ if dir? dir/:name [ append dirtree dir/:name rlist-dir dir/:name ] ] dirtree ] rlist-dir dir ] Regards Ladislav
[REBOL] func[func] Re:(5)
Hi Galt, couldn't you ask simpler questions? {8^D Galt wrote: make-adder: func [x] [func [y] [+ x y]] Ladislav pointed out that if you use it more than once, you must do this: make-adder: func [x] [func [y] compose[+ (:x) y]] Galt again: what is the bloody point of having to put in the compose? I thought the whole idea here was that contexts were cool, and you could use them to have a hidden local variable. I got this from a Scheme example and there's no extra compose needed there. I am guessing that the problem is that there is only one copy of the block [+ x y] and that it has a context, whatever that is, and that it can only have one context, and that one gets changed everytime you run make-adder again with a new parameter value for x. So running make-adder a 2nd time messes up the value hidden in the context of the first? Ladislav: No, the problem is, that Make-adder uses just one context with just one 'x during its whole lifetime, that's why you can't rely on X's value, if you use Make-adder again. with the original simple method, you get this: source add6 add6: func [y][+ x y] with Ladislav's method, you get this: source add6 add6: func [y][+ 6 y] which is a nice demonstration. But it's mechanism doesn't depend on context at all any more. The function is really returning 6 not X with context. 6 is 6 in any context, so big whoop? Did this used to work in an older rebol without compose? Here you are: REBOL 1.0.3.3 (Win32 x86) TM Copyright 1998 REBOL Technologies Inc. All rights reserved. Send bugs to [EMAIL PROTECTED] Loading internal rebol.r REBOL top level. make-adder: func [x] [func [y] [x + y]] #[function [x] [func [y] [x + y]]] add5: make-adder 5 #[function [y] [x + y]] add6: make-adder 6 #[function [y] [x + y]] add6 1 7 add5 1 6 I note that this works, too, silly as it is: make-adder: func [x] [func [y] reduce['+ x 'y]] Ladislav: Exactly the same result as with Compose. And this failed to work, which surprised me, so I guess I still don't get it yet: z: [+ x y] make-adder: func [x] [func [y] bind copy z 'x] I was hoping that I could make a new copy of the z block each time make-adder was called, and then make x take on a different value in the context of each copy. Maybe somebody could show me how to do it using contexts? -galt I am curious too... (BTW, if you want to look at some higher order functions, have a look at http://www.rebol.org/advanced/highfun.r ) Regards Ladislav
[REBOL] func[func] Re:(7)
Hi, It sure is interesting that make-adder works with the old Rebol 1 but not with the newer ones. What exactly did we lose? What work-arounds are feasible? My work-arounds are collected in %highfun.r and %sfun.r I assume that the change was some deal with the devil that RT made for more speed. Bind was easier to implement too..., but the speed may even suffer, because the speed-up for the interpreter may mean a slow-down for the compiled code (JIT compiling may be interesting for Rebol and binding a block 1000 times may be more time-consuming, then the more common approach - bind once, do many times) ... a while back somebody was asking for a something like a whitepaper on the language and at the time people either denied it's usefulness, or claimed it would take important developer time away from improving rebol so it couldn't be written, or that nobody there seemed to understand the request. And really we are talking here about the core functionality of the language, not trying to get Rebol to cough up source code nor to dwell on the details of the implementation of web protocols. We just want to know how to think about the process so we can write correct programs based on understanding. The problem may have something in common with the feeling, that the language is still "under development". I still don't even use parse for any but the simplest things. If I had a burning need that nothing else could satisfy I probably would sit down and grind through the details, but short of that I may never go any deeper. The examples available for parse are certainly better today than they used to be, but they are not that easy. This really means that only expert users with a penchant for playing with parse will get much out of it. Regular users will merely boggle. I suspect however that it is actually possible to document parse better so that more people would be able to make it over the hump. Please chime in, everyone! -galt