[REBOL] Re: [TYPE] weird return value
Hello, all... Consider this: reduce [type? /home/http/run/cohen/birds] == [refinement! /http /run /cohen /birds] So each element of the path-looking thingie is treated as a distinct value, and what gets printed is the last one, just as in type? 1 2 3 4 == 4 Hope this helps! -jn- Hallvard Ystad wrote: Hi Tim, You start with a /, and for some reason, that is recognized as a refinement!, not a path!. type? /home == refinement! refinements are (like?) a data type: /home == /home But I do agree that type? /home/http/run/cohen/birds should not return /birds. HY Dixit Tim Johnson (20.29 21.04.2004): this is weird: type? /home/http/run/cohen/birds == /birds /birds is obviously not a type. What is happening here? thanks tim -- Tim Johnson [EMAIL PROTECTED] http://www.alaska-internet-solutions.com -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject. Prætera censeo Carthaginem esse delendam -- As we enjoy great advantages from inventions of others, we should be glad of an opportunity to serve others by any invention of ours; and this we should do freely and generously. -- Benjamin Franklin -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Simple XML
Hi, Terry, No script needed. PARSE-XML does what you're asking (given that you can use the block convention it creates -- see below). T. Brownell wrote: Is there any available scripts that turn xml into rebol blocks? So that ... xml-stuff: {root {person {name {fname {Bob {/fname {lname { Smith { /lname { /name {/person {/root} == {root person name fname Bob /fname lname Smith /ln... block-stuff: parse-xml xml-stuff == [document none [[root none [^/ [person none [^/ [name none [^/ [fname none [^/Bob^/ ... The convention is that each XML element is represented by a 3-item block, containing: 1) the name of the element/tag as a STRING! 2) attributes (as a block of name/value pairs) or NONE if no attrs 3) contents (as a block of the content items -- strings for text and blocks for child elements) or NONE if no contents *AT*ALL* IgnorableWhiteSpace is not ignored, but appears as STRING! content. The entire XML string is wrapped in a mythical element whose tag is the WORD! DOCUMENT with no attributes. If you juat want the XML content, just take FIRST THIRD of the result of PARSE-XML, as in (the line breaks were added for email formatting, and should be eliminated if you try to cut and paste): x: {topmiddle place='between' bottomdown/bottom/middle/top} == {topmiddle place='between' bottomdown/bottom/middle/top} print mold first third parse-xml x [top none [[middle [place between] [[bottom none [down]] HTH! -jn- -- Single bit errors are corrected. Joel Neely Double bit errors are detected. joel dot neely Undetected errors are ignored. at fedex dot com -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Help with HTTP protocol
Hi, Carlos, Carlos Lorenz wrote: read http://br.weather.com/weather/tenday/BRXX2888 does not work anymore as expected. What does it do? At first glance (using NS7.1) that the returned page is making heavy use of JavaScript to manage content. If that's correct (whether through stupidity or hostility on the part of weather.com ;-) you may have a much harder time getting the content you want without a browser that implements JS (assuming that you don't want to write your own JS interpreter... ;-) -jn- -- Joel Neelycom dot fedex at neely dot joel I had proved the hypothesis with a lovely Gedankenexperiment, but my brain was too small to contain it. -- Language Hat -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: MySQL protocol bug
Hi, Maxim, Pardon my being picky, but we can take your point even further... Maxim Olivier-Adlhoch wrote: in rebol, creating a function is an expression! so you usually write: funcname: func [arg] [put your code here] Although we *may* write something like that, when we do so we are actually combining two distinct concepts in one expression: 1) defining a function, and 2) making a particular word refer to that function. and the habit of thinking of those two together results in one of the standard newbie questions: How can I find out the name of this function? which is no more meaninful than asking for the name of a value of any other type. (Of course, that's what it means to say that functions are first-class values...) How can I find out the name of 2? How can I find out the name of {Hello, world!}? etc. Now, how many languages will handle a stray value in code without choking... not even python will let you insert a string anywhere in its code, if its not being used by a function. ... python or c would give you a syntax error, because it excepts ALL values to be part of a structure, which is defined by strict syntax and parenthesis useage. When it encouters bogus data, it just cant handle it, cause it differentiates values and functions. IMHO rebol does not. They really are all just values, even functions. The following (console transcript) shows that one *can* insert values (e.g. strings) into the body of a Python function when such values aren't actually used for anything. def somefunc (x, y): ... silly function containing pointless string ... x2 = x * x; ... y2 = y * y; ... foo?; ... print x2 + y2; ... somefunc (3, 4) 25 One can do similar things in Perl. The parser will let you know that the value is not used; surely you don't think that's all bad??? How many of us have *never* made a typo in a REBOL script that changed the meaning of something in a way that produced an error, but the interpreter never helped us find it? (However, Perl will still run your program after whining at you.) For example, take a largish REBOL script and delete a single occurrence of '+ somewhere in the middle. -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Shooting yourself in the foot...
The expression shoot foot evaluates to NONE because you forgot to use one of the /BULLET /ARROW or /CANNON refinements; however shoot/off x returns a STRING! longer than available memory if X is of type EMAIL! or MOUTH! ;-? -jn- Izkata wrote: ooh, hehehe, I'm saving this Anyone know of a REBOL addition? - Original Message - From: Jason Cunliffe [EMAIL PROTECTED] http://burks.bton.ac.uk/burks/language/shoot.htm -- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: oss revisited (briefly!)
Hi, Robert, Robert M. Münch wrote: ... As I'm doing a lot of software project proposal evaluation for my customers, the first questions to vendors is: Hmm... it's a Java product. Why? Java didn't work on the desktop, why should it on the server? You must have an interesting definition of didn't work! Just two examples should suffice: Eclipse (desktop) and WebLogic (server) work quite nicely. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: oss revisited (briefly!)
Hi, Karl, Karl Robillard wrote: I'm not a Java expert, but I assume that there is a formal specification for Java and that there are many implementations (Sun, IBM, Blackdown?). That may explain why people would be comfortable adopting Java but not REBOL. The authoritative page is http://java.sun.com/docs/books/jls/ The Java Language Specification, Second Edition - Written by the inventors of the technology, this book is the definitive technical reference for the Java programming language. If you want to know the precise meaning of the language's constructs, this is the source for you. The book provides complete, accurate, and detailed coverage of the syntax and semantics of the Java programming language. It describes all aspects of the language, including the semantics of all types, statements, and expressions, as well as threads and binary compatibility. The entire spec is available on-line in HTML, downloadable in HTML and PDF (both ZIPped), and orderable in dead-tree form. Having a definitive specification makes it possible to learn more efficiently then trial-and-error or ask-somebody-when-stumped, and also makes it possible to distinguish implementation defects (bugs) from cases of I-didn't-understand-that-feature. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: oss revisited (briefly!)
Hi, David, The punch-line (from my perspective) is at the end. David Feugey wrote: There are also big issues with portability. ... no OSS version of the language means no fragmentation of the source code. That simply doesn't follow. Perl, Python, Ruby, etc. etc. etc. have been open source from the beginning, and don't suffer from the oft-threatened specter of fragmentation. It simply hasn't happened. What has happened is that those languages are available on a very wide range of platforms, and are even capable of being embedded into another program as a macro language, thus providing even more (domain-specific) platforms where knowing the language can be an asset. Ask yourself what benefits there might be to REBOL if a team writing the next killer app could decide to use REBOL as the built- in scripting/macro language within that app. Of course that does not mean that OSS implementations dont have to exist, but just that the main implementation is not and that the other one cannot be called Rebol. It's the same for Java with Kaffe (for example). No. Java is a *language*, not an implementation. It is defined by a specification, which makes it possible to check whether any specific *implementation* (Sun's JDK, Kaffe, Jikes, Blackdown, etc. etc.) correctly implements that spec. Of course the holder of a trademarked language name for a language with a published spec is perfectly within rights to insist that the name only be used with implementations which conform to the spec. This is *not* parallel to the case of R# and REBOL. REBOL is an implementation, without a publicly available specification. That means that any effort to create another implementation is based on inferences, guesswork, etc. etc. etc. and can't be guaranteed to match precisely the behavior of the implementation from RT. Are the current limits on number of global words, depth of recursion, etc. actually part of the hypothetical spec of REBOL, or are they just limits of the current implementation? If the R# team guessed right on everything else, but allowed more global words or deeper recursion, would that be correct? Who's to say? PUNCH LINE: Most of the recent discussions re open source are irrelevant, and there have been many assertions made which are simply contrary to fact. REBOL isn't open source because the creator/owner has decided not to do that. Period. And he has a perfect right to choose how to make the fruit of his labors available to the rest of us. However, if we're going to discuss the pros and cons of open source in an attempt to persuade him to change his mind, or to persuade others on the list that his choice had general benefits, we need to stick to the facts and look at what has actually happened in the arena of open-sourced languages. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: oss revisited (briefly!)
Hi, David, David Feugey wrote: ... no OSS version of the language means no fragmentation of the source code. That simply doesn't follow. Perl, Python, Ruby, etc. etc. etc. have been open source from the beginning, and don't suffer from the oft-threatened specter of fragmentation. It simply hasn't happened. It is... When you want to make a GUI with Perl, you have the choice between about 10 toolkits. None of them is standard or widely used (sorry, I call this fragmentation). It's the same for CGI, network, image reading, etc. That has nothing to do with closed-source-vs-open-source issues. If two different programmers write, and offer to the world, two different solutions to the same problem domain, that doesn't mean that THE SOURCE CODE of the language itself has fragmented (which was the original complaint). Andrew's ML dialect is one solution to generating HTML/XML/SGML/etc. Someone else could come along and write (and give away) a different solution to that problem. That isn't fragmentation of the language itself. Perl was invented before the time when people considered full-blown graphics to be a part of a core language. (Some people still don't consider that to be so...) Different people wrote graphic libraries and frameworks (or adapters to externally-existing libs and fws) for use in writing graphic applications in Perl. That doesn't mean that the language itself is fragmented, any more than the independent existence of MySQL and Oracle mean that any language that can talk to both of them is fragmented. ... This is *not* parallel to the case of R# and REBOL. REBOL is an implementation, without a publicly available specification. That means that any effort to create another implementation is based on inferences, guesswork, etc. etc. etc. and can't be guaranteed to match precisely the behavior of the implementation from RT. Yes, you're absolutely right on this point... specifications should be public. I still believe that this would be the biggest single step toward facilitating the growth of REBOL. Pros and cons for both... even if I prefer an OSS model. But Rebol is pretty good... Appart from the licence (still not clear) it's a good language, and for me it's essential. I agree that it's a good language. I just want us not to be caught comparing apples with Thursdays when we talk about the pros and cons of different distribution/development models. ;-) -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: oss revisited (briefly!)
Hi, Robert, Just my $0.02 here... However, let me emphasize that I'm not agitating for a change of RT position here, but just clarifying what I understand open source to be about, and some benefits of open source. Robert M. Münch wrote: Hi, I never undestand what the problem is? What's the problem with Rebol not being open-source? It doesn't cost hundred-of-thousands of $s to use. So if you are doing things that will create revenue, you can afford a license, if not use the free interpreter. With all due respect, I think you're confusing two distinct issues here. To paraphrase ESR and RMS, open source is about free as in free speech, not free as in free beer. Access to source code is about availability of knowledge, as expanded below. But, all those open-source demagogues, if you can show-up with a business-model that let RT make some money from their work, I will be quite but otherwise it's just a techie POV with no business know-how behind it. And, BTW: Those not caring about Rebol because not being open-source have a problem ;-) Again WADR I think you're contradicting yourself here. Saying that something has no value unless somebody can make money off of it seems just as much advocating a philosophical POV (not to accuse anybody of demagoguery ;-) as saying that the greatest value to society at large is obtained by knowledge to be freely available. As for the other contradiction, your first paragraph seems to be arguing for a strictly commercial POV, but your second paragraph seems to ignore the marketing principle that the customer has the right to decide what (s)he wants. I know some people who don't care about anything that doesn't run on Windows. Do you think they have a problem simply because they have a preferred platform and delivery model? RT can make money by providing expert support, just as an engineering firm can make money by providing expertise, even though that expertise is based on applying the open source laws of physics which are freely available to all. Similarly, legal firms make *LOTS* of money offering their expertise, even though anyone can legally go to a law library and read the source code of the laws of the nation. Well, why not? If someone can tell me a really benefit Rebol being open-source I might change my POV. Sorry, if this sound a bit harsh here, but only moaning without showing a solution is not that professional. 1) Faster bug fixes. Many folks on this mailing list have offered but fixes for mezzanine code, but their/our ability to help debug and offer corrections hits the wall when natives are involved. RT produces good code but nobody is perfect and we know that there have been bugs which have taken quite a while to resolve due to other priorites and limits on resources. 2) Improved documentation. Many on this list have contributed ideas, explanations, and mental models re various features of REBOL. If we had access to the source code, those who are willing to invest the effort to understand the interpreter and/or natives could offer exact and definite answers for how does REBOL do ... and what does ... mean in REBOL kinds of questions. The user community could stop wasting time trying to guess and/or debate such issues. Making the user community more effective certainly benefits both the users and RT! 3) Faster porting. There have been several mentions on this list in the past few days about the fact that /View on Mac OS/X has been pending for over a year. In the open source world, sufficiently- interested parties can perform (or at least contribute to) the legwork of getting an existing piece of code ported to another environment (even if only for beta purposes). The list could go on, but you asked for a benefit and I've mentioned three, so I'll stop. ;-) Again, let me stress that I'm not complaining or advocating here; RT has a perfect right to decide what model and license REBOL will be provided under. As a user, I simply decide whether I prefer to use the tool under their model, or live without it. I certainly agree that whining and moaning are not professional, but I do believe that calm, rational discussion of the pros and cons of alternatives is also legitimate. -jn- -- Joel Neelycom dot fedex at neely dot joel I had proved the hypothesis with a lovely Gedankenexperiment, but my brain was too small to contain it. -- Language Hat -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Threading continued
Hi, Maarten, Maarten Koopmans wrote: ... it responds to a 'rest word, giving you the restof the block to be evaluated and the value of the last evaluated expression. So: eval [ 10 + 10 join a b rest 20 print howdy ] [ ab [ 20 print howdy]] Note that the second item (the rest of the code) is the position in the original code, so a ' head on that gives you the original code back. Sort of like iterating DO/NEXT with an additional check for REST ? Question: is this a thing any of you want despite the performance hit of 400% ? I pondered doing something with DO/NEXT a while back, but gave up in frustration (I hope you're smarter and/or more patient than I ;-) as I want to be able to write expressions/functions more sophisticated than a single block, but still have interruptability. For example: eval [ foreach line read/lines %somefile [ print line rest ] ] Or interruptableFunction: func [aLine [string!]] [ print aLine doSomethingInteresting aLine rest ] eval [ foreach line read/lines %someOtherFile [ interruptableFunction line ] ] You said takes a block so I inferred that things such as the above (nested blocks, including function evaluation) are currently out of reach. Am I too pessimistic? If I have to do all the work of managing e.g. loops and other control structures, including functions, I think I'd probably want to just go ahead and evert the code into a task object (per the article on REBOLforces) with a STEP method that does some meaningful (but not over long) piece of work and then saves state and returns control. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Directory
Hi, Chris, Chris Siegle wrote: Why is it I cannot make a directory from an assigned variable name? testVariable: 12312323 make-dir %testVariable The argument to MAKE-DIR should be a FILE! or URL! value, not a STRING! value. ? make-dir USAGE: MAKE-DIR path /deep DESCRIPTION: Creates the directory structure specified. MAKE-DIR is a function value. ARGUMENTS: path -- (Type: file url) REFINEMENTS: /deep (SPECIAL ATTRIBUTES) catch therefore, testVariable: 12312323 make-dir to-file testVariable should work for you (assuming you have write permissions in the current directory). -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: How to remove words from objects?
Hi, Luke, Sorry. Luke wrote: Dear list I'm trying to dynamically add and remove words from an object... You can't. now I want to remove c from obj. How do I do that. I know I could dynamically reconstruct it from scratch, but that is not very elegant. There must be a better way to get back to obj being: There's not. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: How to remove words from objects?
Hi, Luke, Luke wrote: I dont understand Gregg what you mean when you say the context of an object isnt dynamic... Once an object has been created, its context (namespace) is set in concrete and cannot be changed (although the values to which its words are set *can* be changed). But if so, then how does that explain why can I do this (but not reverse the action): ;---create object obj: make object [a: 1] ;---add a new word to the object obj: make obj [b: 2] Because you are not adding a new word to *the*original* object, but instead are creating a *new* object (based on the original) which contains the new value. To see that this is not modifying the original, just consider this: obj: make object! [a: 1] other: obj obj: make obj [b: 2] source obj obj: make object! [ a: 1 b: 2 ] source other other: make object! [ a: 1 ] So the original object is still around (referent of OTHER) but now OBJ refers to a *new* object. You can get tricky and work around it, by including a block in your object and using that as kind of a sub-context--because blocks are resizable. I think Ladislav or Joel posted a dynamic object example here at one time... If you want shared references to an object to all show the effect of such structural changes, you can wrap the object in another object (i.e. create an additional level of indirection) which is the common referent: wrapper: make object! [ [inner: make object! [ [a: 1 [] [] obj: wrapper other: wrapper source obj obj: make object! [ inner: make object! [ a: 1 ] ] source other other: make object! [ inner: make object! [ a: 1 ] ] obj/inner: make obj/inner [b: 2] source obj obj: make object! [ inner: make object! [ a: 1 b: 2 ] ] source other other: make object! [ inner: make object! [ a: 1 b: 2 ] ] (Of course, the wrapper could be a block as well, but using an object as a wrapper allows an easy way to put methods in the wrapper that delegate to the inner object, so you can hide the indirection from any client code.) -jn- -- Joel Neelycom dot fedex at neely dot joel I had proved the hypothesis with a lovely Gedankenexperiment, but my brain was too small to contain it. -- Language Hat -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Is Rebol OO?
Hi, Behrang, Behrang Saeedzadeh wrote: ... is REBOL Object Oriented? As you can tell from the variety of responses, the question is a bit tricky to handle. Unfortunately, the phrase object oriented has been siezed on by marketers, reporters, comp sci researchers, methodologists, consultants, and snake oil salesmen, and given different spins by all of the above. Let me duck the phrasing of your original question, and answer a closely-related one, in the hope that something I say will address your needs: I already know how to program in language XYZ, which is commonly regarded as an object-oriented language. How much of what I know about programming in XYZ will be useful to programming in REBOL? Answering this modified question would require addressing some of the following issues: 1) REBOL is a dynamically-typed language. This is familiar territory if you are used to Smalltalk, Python, or Perl; It may take some adjustment if you are used to Java, C++, Eiffel, Delphi, etc. Type errors (attempting to apply an innappropriate operation on a value, trying to access a non-existent component of an object, etc.) are caught at run time, not prevented at compile time. 2) An object in REBOL is a namespace. The values associated with the words defined in an object represent the state of the object, and functions defined (at creation time) within the object use those words in the familiar way: sample: make object! [ some-data: Hello, world! some-method: func [] [print some-data] ] Immediately after evaluating the above definition, an evaluation of SOME-METHOD results in the output of Hello, world! regardless of whether there's a word SOME-DATA defined anywhere else (e.g. globally, within another object, etc.) 3) All words defined within an object are public. That's why I had to say immediately after evaluating... in the previous point. Given the above object, you can also say sample/some-data: Goodbye, cruel world! to change the state of SAMPLE. There's no built-in way to make SOME-DATA private, and inaccessible to the rest of the world. 4) REBOL uses a prototype model of object creation, rather than a class-based model or a delegation model. Objects are made one-at-a-time and one-of-a-kind. You can use a block (as in the above example) as a specification for creating an object, and can use the same block repeatedly: sample-spec: [ some-data: Hello, world! some-method: func [] [print some-data] ] sample1: make object! sample-spec sample2: make object! sample-spec sample3: make object! sample-spec but once those objects are created, each has a life (state) of its own; any resemblance is viewed by REBOL as merely coincidental. In particular, each of the above objects has its *own* function named SOME-METHOD . There's no concept in REBOL of instance method shared between the objects. You can also use an existing object as a specification: demo1: make object! [ some-data: Hello, world! some-method: func [] [print some-data] ] demo2: make demo1 [] demo3: make demo2 [] but, again, a newly created object is like a newly-hatched sea turtle; it resembles any siblings which may have come from the same parent, but immediatly upon hatching, it must face the wild ocean on its own. It has no parent. 5) As a consequence of all of the above (and the dynamic nature of REBOL itself) you can build your own convenience methods to implement some features you may be accustomed to using: greeter-class: make object! [ _greeter: make object! [ greetee: TBD greet: func [] [greeter-class/_greet self] ] new: func [who [string!]] [ make _greeter [greetee: copy who] ] _greet: func [which [object!]] [ print [Hello, which/greetee] ] ] which provides a constructor (NEW) and a single shared method for all instances (GREETER-CLASS/GREET), which defer to the class definition... world-greeter: greeter-class/new world! mom-greeter: greeter-class/new Mom! lonesome-greeter: greeter-class/new anybody? ...so that each instance uses the common behavior: world-greeter/greet Hello, world! mom-greeter/greet Hello, Mom! lonesome-greeter/greet Hello, anybody? Of course this is overkill for something as simple as shown above, but if the GREET method were complex and lengthy, it would save space to have each instance object contain only stub methods
[REBOL] Re: sort/scramble
Hi, Anton, Anton Rolls wrote: You might be able to do all this in the sort comparator function somehow, but it's not obvious to me. I don't believe that it's possible to handle all of this via SORT/COMPARE . The comparison function only tells whether two values are in order or out of order (presumably the basis for a decision whether to swap them, regardless of sorting strategy: shellsort, quicksort, heapsort, bubblesort, etc.) Exchanging two elements (or partitioning the set) based on a two-element comparison is guaranteed to improve the net sortedness of the entire collection, without regard for the rest of the values. (The elements don't even have to be adjacent for this to be true!) The property of a block that says all pairs of adjacent elements are different for some definition of different is a global property and can't necessarily be improved by considering only two values. If they are the same, then clearly one of them must be swapped away from the other, but without taking more of the collection into account, it is not possible to guarantee that such a swap will improve the desired condition. For example: ... a b c d e f... if the values represented by C and D are same for the case at hand, we MIGHT be able to improve things by swapping B and C, but only if A and C differ and B and D differ, etc. I'm not saying that one couldn't create an tuned algorithm to massage the collection into the desired state, only that I don't believe there's a way to do it with a sorting function. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: sort/scramble
Hi, Hallvard, To ensure unsorted, first sort, then interleave second and first halves. (Assuming you have enough distinct values that moving halfway through the sorted order gives you a different value.) Hallvard Ystad wrote: I have a block with, say 10 blocks inside it. Each block has many different data types within it (but only one element matters). I want to unsort them so that _part of_ the fourth element (a string) is not identical in adjacent blocks... example: [[4 1 7 nicsrg 5 6 3 8 2 9] [3 1 2 sicrtg 9 8 4 7 6 5] [9 3 7 iscgtn 6 2 8 5 4 1] [1 3 8 inctrg 5 2 9 4 6 7] [9 6 5 ngsirt 8 2 1 3 7 4] [3 7 8 igtnrs 4 1 2 9 5 6] [6 4 8 gnrsit 2 3 9 1 5 7] [9 5 4 sntgir 6 7 8 2 1 3] [6 7 4 gstinr 1 5 2 3 9 8] [7 9 2 sgcnit 5 1 8 3 6 4]] In the first four blocks, the third character in the fourth element is #c. I want these four blocks split apart. Getting at the character in question is easy (foreach b example [print pick fourth b 3]), but unsorting the blocks from there? Let's define (and demonstrate) the interleaving function first: riffle: func [b [block!] /local n j result] [ j: to-integer (n: length? b) / 2 result: make block! n for i 1 j 1 [ append/only result pick b i + j append/only result pick b i ] if odd? n [append/only result last b] result ] Which behaves as: riffle [0 1 2 3 4 5 6 7 8 9] == [5 0 6 1 7 2 8 3 9 4] riffle [0 1 2 3 4 5 6 7 8] == [4 0 5 1 6 2 7 3 8] So that (for a trivial case, which I know is already sorted) riffle sort [0 0 0 1 1 1 2 2 2 3 3 3] == [2 0 2 0 2 0 3 1 3 1 3 1] adjacent elements are now different. Finally, for your example: example: [[4 1 7 nicsrg 5 6 3 8 2 9] [3 1 2 sicrtg 9 8 4 7 6 5] [9 3 7 iscgtn 6 2 8 5 4 1] [1 3 8 inctrg 5 2 9 4 6 7] [9 6 5 ngsirt 8 2 1 3 7 4] [3 7 8 igtnrs 4 1 2 9 5 6] [6 4 8 gnrsit 2 3 9 1 5 7] [9 5 4 sntgir 6 7 8 2 1 3] [6 7 4 gstinr 1 5 2 3 9 8] [7 9 2 sgcnit 5 1 8 3 6 4]] example: riffle sort/compare example func [a b][a/4/3 b/4/3] foreach item example [print mold item] which gives: [6 4 8 gnrsit 2 3 9 1 5 7] [1 3 8 inctrg 5 2 9 4 6 7] [9 6 5 ngsirt 8 2 1 3 7 4] [3 1 2 sicrtg 9 8 4 7 6 5] [3 7 8 igtnrs 4 1 2 9 5 6] [4 1 7 nicsrg 5 6 3 8 2 9] [6 7 4 gstinr 1 5 2 3 9 8] [7 9 2 sgcnit 5 1 8 3 6 4] [9 5 4 sntgir 6 7 8 2 1 3] [9 3 7 iscgtn 6 2 8 5 4 1] where adjacent (sub-)blocks differ in the third character of the fourth element. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: sort/scramble
Hi, Hallvard, Hallvard Ystad wrote: Hi I need a function that will make sure a block is _not_ sorted. How about this: random [0 1 2 3 4 5 6 7 8 9] == [8 9 3 4 2 1 7 6 0 5] Of course, there's a 1 in 3628800 chance that a random arrangement of ten values will actually be in order! ;-) If you really mean *NOT* sorted (and your values are distinct), but don't care about randomness, then reverse sort foo will make sure that FOO is _not_ sorted in ascending order. Can you provide a little more detail on your requirements? -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] This time of year...
...gets quite busy in my world, so let me take this opportunity to wish all of you a joyous holiday season and a happy new year! -jn- -- -- Joel NeelymocTODxedefTAyleenTODleoj 6444-362-109 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: a new switch-like flow-control function
Hi, Maxim, There's more to the story, although YMMV... Maxim Olivier-Adlhoch wrote: describe: func [x [integer!] y [integer!]] [ switch true compose [ (x = 1) [X is one] (y = 1) [Y is one] (x = 2) [X is two] (y = 2) [Y is two] (true) [X and Y are too big!] ] ] ... (its also 10% faster, on my computer). The timing comparison (even for the trival example I gave) is *highly* dependent on the range of values which X and Y take! The issue is that PIF will evaluate only enough guards to find the first true one, while the SWITCH TRUE COMPOSE approach evaluates *all* guards (and constructs a new block) every time. If e.g. your timing test looks like t0: now/time/precise loop somebignumber [ for x 1 hi 1 [ for y 1 hi 1 [ describe x y ] ] ] t1: now/time/precise print to-decimal t1 - t0 then using HI: 3 will give very different ratios between the two approaches than HI: 6 or HI: 20 etc. PIF allows the programmer easily to follow the standard heuristic of making cheap (or high-probability) tests early to reduce the average cost of a decision-driven expression, e.g.: dihedral-signum: func [ x [number!] y [number!] z [number!] ][ pif [ x = 0 [0] y = 0 [0] z = 0 [0] 10 square-root abs ( x * (x + 1) * y * (y + 1) * z * (z + 1) - ((x + 2) * (y + 3) * (z + 4)) ) [1] true [-1] ] ] Also, PIF allows the programmer to use failure of earlier tests as guards for the evaluation of later tests, which is another useful (and easy to read/write/understand) technique which the SWITCH TRUE COMPOSE doesn't support: fuel-economy: func [ fuel [number!] distance [number!] ][ pif [ fuel = 0 [No data] distance / fuel 20 [Poor fuel economy!] distance / fuel 40 [Great fuel economy!] true [Acceptable fuel economy] ] ] In the above case, we can only reasonably make the later tests if the test FUEL = 0 has failed. In case anyone is tempted to redesign the tiny examples above, please remember that those are off-the-cuff examples, and they aren't the point! The point is that there's inherent economy in only evaluating enough expressions to get a result (instead of every possible one and then picking the winner), and there are inherent safety and simplicity considerations in knowing that a test can only be evaluated if the previous ones have failed. ON THE OTHER HAND ... If I wanted to resurrect the discussion of a non-deterministic choice among multiple options, I'd be very grateful that you provided a nice way to express that!!! nif: func [[throw catch] b [block!] /local options] [ options: copy [] foreach [guard option] compose b [ if guard [append options option] ] do random/only options ] e.g. from among the guard/action pairs with true guard, evaluate an arbitrarily-chosen action, so that nif [ (x = y) [x] (y = x) [y] ] nicely expresses that if X and Y are equal, then either one can be used as the minimum of the two! Thanks! -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Newbie Mailing List Questions
Hi, Stan, Welcome to the list! Stan Silver wrote: Greetings, 1. Are mail list threads determined only by the subject? In other words, can I add my two cents to an existing topic just by typing in the correct subject? Or do I have to reply to an existing email? Does Re: matter in the subject? Take a look at the mail headers in your email client (e.g. in Netscape or Mozilla there's an option in the View menu to do this). If you reply to a previous email, the mail client should include the email ID of the onw you're replying to in the References header. I think that some email clients use this to construct the threading; If you don't reply, but simply type the same string into the Subject then it may not be picked up as belonging to the same thread. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: a new switch-like flow-control function
Hi, Anton, Set the WayBack machine to 2000... ;-) Anton Rolls wrote: I yearn (want), occasionally, a kind of any/switch-like flow-control function... Some years ago we had a long discussion about generalizing IF on the list, and kicked around various options/versions. The copy I could lay my hands on most quickly was Ladislav's refinement (the last in the discussion???): pif: func [[throw catch] args [block!] /local res] [ either unset? first res: do/next args [ if not empty? args [ throw make error! [script no-arg pif condition] ] ][ either first res [ either block? first res: do/next second res [ do first res ][ throw make error! [ script expect-arg pif block [block!] ] ] ][ pif second do/next second res ] ] ] PIF (Polymorphic IF) takes a block of guard-expression/block pairs and uses the (first true) guard-expressions to select block to be evaluated. It can be used (I believe) essentially as you were asking. Refactoring PIF to iterative form is left as an exercise for the reader! ;-) As long as the argument block isn't too long the recursion likely won't be a problem. Heres a sample usage: describe: func [x [integer!] y [integer!]] [ pif [ x = 1 [X is one] y = 1 [Y is one] x = 2 [X is two] y = 2 [Y is two] true [X and Y are too big!] ] ] which behaves as: describe 1 1 == X is one describe 2 1 == Y is one describe 2 2 == X is two describe 3 2 == Y is two describe 3 3 == X and Y are too big! -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Rebol API to DyBASE
Hi, Konstantin, Maybe even worse? Konstantin Knizhnik wrote: And as far as Rebol hash is also series, appending element to it cause a lot of reallocations, so complexity of insert operation seems to be linear (instead of constant). And if we use insert hash instead of append hash (not insert tail hash), then performance becomes really awful - copying all series element increase complexity to quadratic and insertion of 10 integer elements in hash takes about half an hour (less then second in all other languages). INSERTs into a fresh hash (created each time with MAKE HASH! []): Appears to be increasing faster than quadratically! # eltsseconds ratio quad slowdown 1 3.065 2 25.8178.423 4 2.106 3 63.682 20.777 9 2.309 4123.417 40.267 16 2.517 APPENDs into a growing hash (not reconstructed between runs): # elts seconds 4 2.153 4 6.69 410.956 415.453 419.568 Here the number of appends in each stest is the same, but the time complexity of managing a growing structure shows up; likewise, for a simple block: APPENDs into a growing block: # elts seconds 4 2.073 4 6.529 410.735 414.962 418.907 If we take out the reallocation-for-growth issues we get these: APPENDs into a growing hash initialized with MAKE HASH! 20 # elts seconds 4 0.22 4 0.251 4 0.2 4 0.33 4 0.281 APPENDs into a growing block initialized with MAKE BLOCK! 20 # elts seconds 4 0.17 4 0.17 4 0.171 4 0.191 4 0.171 Preallocation of space (whenever possible ;-) is our friend! -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: What does REBOL fix?
Hi, James, Were you just joking? (OBTW, REBOL isn't the only language that supports dialects...) James Marsden wrote: Dialecting in Rebol, more fun than Latin! Damien Conway has actually written a Latin dialect for Perl! [begin excerpt] Lingua::Romana::Perligata -- Perl for the XXI-imum Century Damian Conway School of Computer Science and Software Engineering Monash University Clayton 3168, Australia Abstract This paper describes a Perl module -- Lingua::Romana::Perligata -- that makes it possible to write Perl programs in Latin. A plausible rationale for wanting to do such a thing is provided, along with a comprehensive overview of the syntax and semantics of Latinized Perl. The paper also explains the special source filtering and parsing techniques required to efficiently interpret a programming language in which the syntax is (largely) non-positional. ... The Sieve of Eratosthenes is one of oldest well-known algorithms. As the better part of Roman culture was ``borrowed'' from the Greeks, it is perhaps fitting that the first ever Perligata program should be as well: #! /usr/local/bin/perl -w use Lingua::Romana::Perligata; maximum inquementum tum biguttam egresso scribe. meo maximo vestibulo perlegamentum da. da duo tum maximum conscribementa meis listis. dum listis decapitamentum damentum nexto fac sic nextum tum novumversum scribe egresso. lista sic hoc recidementum nextum cis vannementa da listis. cis. The use Lingua::Romana::Perligata statement causes the remainder of the program to be translated into the following Perl: print STDOUT 'maximum:'; my $maxim = STDIN; my (@list) = (2..$maxim); while ($next = shift @list) { print STDOUT $next, \n; @list = grep {$_ % $next} @list; } Note in the very last Perligata statement (lista sic hoc...da listis) that the use of inflexion distinguishes the @list that is grep'ed (lista) from the @list that is assigned to (listis), even though each is at the ``wrong'' end of the statement, compared with the Perl version. [end excerpt] For those with a classical education (and a high tolerance for pain ;-) the full paper is available at http://www.csse.monash.edu.au/~damian/papers/HTML/Perligata.html It's a hilarious tour-de-force! -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: What does REBOL fix?
- REBOL: The message is the medium. - REBOL: Programming for block heads - REBOL: Life's too short to write long programs - REBOL: Fight carpal tunnel syndrome! - REBOL: Good things come in small packages - REBOL: Because Von Neumann was right! - Real Expressiveness Based On diaLects - Radical Economy Built Of Literals - REBOL: just DO %it - Fewer moving parts - more parts move - REBOL: Spread the WORD! - REBOL: word up! - REBOL: the last WORD in programming - REBOL... I :it - REBOL... :on-the-network - foreach program your-to-do-list [:REBOL] - REBOL: because this bumpersticker is too shor On 14-Dec-03, [EMAIL PROTECTED] wrote: Can we find a snappy one-liner? http://www.paulgraham.com/fix.html -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: What does REBOL fix?
Hi, Gabriele, Gabriele Santilli wrote: Hi Jason, On Monday, December 15, 2003, 6:02:50 PM, you wrote: JC Yes but that is still also true for HTML, XSLT, Perl, Python, JC PHP, Java, C, JC etc.. How do you MOLD some PHP code and send it to another computer? ;-) I disclaim all knowledge re PHP, but here's a trivial Perl client to fetch and execute/evaluate source from a remote host. use LWP::Simple; eval get (http://your-site-here;); The only point I was making in my earlier comment was that there are several languages that are highly platform-neutral. It's also true that many of them are mobile in the sense of being able to migrate run-ning/-nable code across the 'Net. I guess one has to decide whether a one-line summary for REBOL (or any other language) is to be: a) a claim of a unique strength of the language (in contrast to other languages of the claimant's in-depth knowledge), b) a bullet point naming something the language does well (whether or not other languages do so as well), c) a bumper-sticker slogan intended primarily for fun (as in my recent list of submissions), or d) a sufficiently intriguing statement to motivate others to look at the language. And, of course, submitting types (b), (c), or (d), and having them perceived as if of type (a) is the basis is the basis of many language holy wars! ;-) -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: What does REBOL fix?
Hi, Maxim, Maxim Olivier-Adlhoch wrote: ... In this case, rebol outdoes everybody, IMHO. For security, you can just encrypt the data before sending it, and even that is (rather) easy to integrate right in a protocol. That's not the only security issue. Encrypting the source as it moves over the wire doesn't protect one from bugs (or malicious intent) in the code itself once executed. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: What does REBOL fix?
Hi, Ged, Ged Byrne wrote: use LWP::Simple; eval get (http://your-site-here;); The code required to pass a string to another machine and have it execute is simple enough, but it isn't enough for the real world. The code as given presents a massive security risk. I completely agree. I was only trying to show that the classic REBOL example do read http://your-site-here isn't unique. So you have to construct sandboxes and all the rest of it. Layers upon layers of complexity. Which is as non-trivial in REBOL as in other languages. ... On the other hand, the ability to send an expression for another machine to execute is central to Rebol's purpose. But the ability to store/send an expression for later evaluation (whether on the same machine or not!) is a part of MANY current languages. I think I may be taking this all too seriously. I think we all are! ;-) -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: What does REBOL fix?
Hi, Ged, Ged Byrne wrote: Because every other language is trapped on just one computer. Let's be fair. There are MANY languages that are highly portable in today's world: Perl, Python, Ruby, Java, and a whole slew of open-source efforts. And we're still waiting for the MacOS/X version of /View... -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] rot13
First, thank you for the effort you've put into the ROT13 page at: http://www.miranda.org/~jkominek/rot13/ With respect to your page on REBOL: http://www.miranda.org/~jkominek/rot13/rebol/rot13.r and especially with respect to the Note to others... I suggest that it is unfair to condemn a programming language on the strength of an overly complicated, poorly-written function by someone who is clearly unfamiliar with the language. I can think of several ways to write the rot13 conversion in a much more natural-to-REBOL style. The quickest (for me) to write uses REBOL's object mechanism, and generates the translation table algorithmically at object set-up time (as a one-shot initialization to reduce risk of typos): rot13: make object! [ xlate: make string! 78 for ch #a #m 1 [append xlate reduce [ch ch + 13 ch]] for ch #A #M 1 [append xlate reduce [ch ch + 13 ch]] code: func [s [string!] /local result] [ result: make string! length? s foreach ch s [ insert tail result any [select/case xlate ch ch] ] result ] ] It would be invoked on a string by evaluating rot13/code somestringexpression and extending this to process an file (or standard input) is easy. Again, thanks for the comparisons, and I hope to offer the above comments in the spirit of assistance, not negativism! -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Guru's please help improve ROT13 algorithm !
I submitted a cleaner one (than what's on the ROT13 page) along with some remarks, and copied the list here, and then saw Sunanda's reply: [EMAIL PROTECTED] wrote: http://www.rebol.org/cgi-bin/cgiwrap/rebol/view-script.r?script=rot-13.r WRT that version, I'll add my $0.02... rot-13: func [ {Converts a string to or from Rot-13} data [any-string!] /local scrambled rot-chars rot-char ][ rot-chars: {anabobcpcdqderefsfgtghuhivijwjkxklylmzmANABOBCPCDQDEREFSFGTGHUHIVIJWJKXKLYLMZM} scrambled: copy foreach char data [ if none? (rot-char: select/case rot-chars char) [rot-char: char] insert tail scrambled :rot-char ] return scrambled ] My suggestions follow: 1) I prefer to avoid typo-prone strings when I can. 2) Both the above and my submission to the ROT13 site would benefit from comments explaining the construction of the translation string as related to SELECT/CASE. It is a nice REBOL-ism that we only need 39 characters per case as opposed to 52! 3) I'd rather initialize the result as an empty string with the full (known) length preallocated to avoid excessive memory management overhead for longer arguments. 4) The use of the get-word (:ROT-CHAR) is surprising (but marginally defensible by speed?) 5) The if-none-then-use-default pattern is a great opportunity to use another REBOL-ism, ANY. I did a little benchmarking with four versions: code - is the version from my earlier post, if/get - replaces the FOREACH body with if none? cc: select/case xlate ch [cc: ch] insert tail result :cc similar to the version in the script library if - simply replaces the get-word (:CC) with the word itself if none? cc: select/case xlate ch [cc: ch] insert tail result cc either - evaluates the replacement character as an expression as the last argument of the INSERT insert tail result either none? cc: select/case xlate ch [ch] [cc] The results of a quick timing test (50,000 evaluations of each function on a 243-character string) are rot13/time-it 5 datum code: 108.356 if/get: 132.24 if: 133.502 either: 137.117 The use of the get-word saves about 1% to the run-time of the function (if/get vs is). The time for EITHER vs IF was a bit of a surprise to me, because it added another 3-4% to the run time. Comparing the object/method version vs a stand-alone function, we can pull a REBOL-persistence-of-series trick: rot13: func [s [string!] /local result xlate] [ if empty? xlate: [ for ch #a #m 1 [append xlate reduce [ch ch + 13 ch]] for ch #A #M 1 [append xlate reduce [ch ch + 13 ch]] ] result: make string! length? s foreach ch s [ insert tail result any [select/case xlate ch ch] ] result ] (not that I'd ever write somehing like that, for several reasons ;-) or embed the translation strings in place of the local XLATE, and get the following timings: fn-vs-obj 5 datum method: 108.255 stateful: 107.405 stateless: 107.514 where stateful is the above ROT13 function, and stateless uses the literal instead of persistence. Any critiques or suggestions for improvement to my object-based version are welcome! -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: [tek@wiw.org: Re: rot13]
Hi, Julian, Julian Squires wrote: Hi. I sent this reply off promptly, but I was unable to send to the rebol list without a subscription. I'll be glad to forward it. I evaluated rebol again later, having learned more about similar languages, but I find ruby more suiting to my personal preferences. Actually, I'm a bit of a polyglot myself (mostly Perl and Java for work, still dabbling at Python, bought Dave Andy's Ruby book but haven't had time to invest in serious reading/playing.) I get very interested in seeing how mental models of various languages shape (or at least influence) one's design and coding, and would likely have spent more time on Python had it been around when I decided to learn Perl. Cheers. (hoping to never have to hear about this again, and hoping to meet people under friendlier circumstances than language wars.) Happy holidays (and I'll try to point a cold fire-hose at some of the flamers! ;-) -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] REBOL in another multi-language site...
...by some guy with WAYYY too much computer access! ;-) http://www.kernelthread.com/hanoi/html/r.html -- Joel Neelycom dot fedex at neely dot joel I had proved the hypothesis with a lovely Gedankenexperiment, but my brain was too small to contain it. -- Language Hat -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Some other questions
Hi, Mike, Here we jump off the deep end... ;-) Mike Loolard wrote: 5) On the webpage about objects one passage mentioned that sub-objects don't get cloned- what does that mean ? Reading that I would expect that all objects within an object aren't available when I create an object on the basis of that object. But I seem to be able to use it anyway. Maybe I am getting something wrong here ? If you have an object like this: proto: make object! [ ID: 1 label: My object ] then whenever you say instance-1: make proto [] REBOL will implicitly clone/copy the string value for the LABEL attribute, so that the new object doesn't have the *same* string as the prototype. Aside on Same-ness: Consider this transcript: a: Whoopee! == Whoopee! b: a == Whoopee! a/8: #? == Whoopee? b == Whoopee? The reason that the value for B changed is that B was set to (refer to) the *same* string as A (i.e. not a copy): a = b == true same? a b == true therefore there's only one string, but A and B can both get at it. On the other hand, if we explicitly ask for copying: a: Whoopee! == Whoopee! b: copy a == Whoopee! a = b == true same? a b == false a/8: #? == Whoopee? b == Whoopee! A similar situation (equal but not same) would result from saying a: Whoopee! == Whoopee! b: Whoopee! == Whoopee! It's important to remember that same and equal aren't the same! End of Aside on Same-ness That means that we can examine our objects: ? proto PROTO is an object of value: make object! [ ID: 1 label: My object ] ? instance-1 INSTANCE-1 is an object of value: make object! [ ID: 1 label: My object ] same? proto/label instance-1/label == false and see that the LABEL attributes are equal strings, but are not the same string. Now, suppose that our prototype had an object as the value of one of its attributes instead: proto: make object! [ ID: 1 label: make object! [ part-nr: 38562 name:Flanged widget ] ] and we used it as the basis of a new instance: instance-1: make proto [] Now we can examine our objects ? proto PROTO is an object of value: make object! [ ID: 1 label: make object! [ part-nr: 38562 name: Flanged widget ] ] ? instance-1 INSTANCE-1 is an object of value: make object! [ ID: 1 label: make object! [ part-nr: 38562 name: Flanged widget ] ] same? proto/label instance-1/label == true and see that the sub-object referred to be the LABEL attribute of INSTANCE-1 is the *same* object that is referred to by the LABEL attribute of PROTO. That means (again) that changes/mutations of that sub-object will be seen everywhere that it is referenced. replace proto/label/name widget blivet == Flanged blivet ? instance-1 INSTANCE-1 is an object of value: make object! [ ID: 1 label: make object! [ part-nr: 38562 name: Flanged blivet ] ] Now, to sum all of that up in a single sentence: When a new object is created from a prototype object, series-valued attributes of the prototype are copied, but object-valued attributes are shared. Hope this helps! -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: what a subject ;-) Re: Re: [enum][constructor][memory][cloning][vid] Some other questions
Hi, Petr, Petr Krenzelok wrote: I am sorry, maybe I missed significant discussion to the topic, but don't you guys find subject key-words a bit contraproductive? I think the problem is not with key words, but with trying to cram too many topics into a single email/thread. Use decent mailers as Mozilla and you will not have trouble searching for certain topics ;-) True. However, there's more than searching involved here. Subject keywords (when properly used) allow you to scan the inbox to see which emails to read first, ignore, etc. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] [email] Re: Some other questions
Hi, Mike, Mike Loolard wrote: I hope you guys don't mind me asking some other questions I have come up with meanwhile. Welcome to the list! I'm sure you'll find it as helpful and friendly as I have. However, let me suggest that it will make discussions easier to follow if you will put each question (or small group of closely related questions) in a separate email. That way people can follow -- and participate in the discussions -- in a more focused way. Happy REBOLing! -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: [array] Some other questions
Hi, Andrew, A J Martin wrote: Anton wrote: Watch out though, each item in chickenfarm is the same chicken object: Yes! You've found a bug in 'array! It's not a bug, since AFAIK there's no published specification that says ARRAY should behave any differently than it does. We've seen this issue before, in connection with other reference types, as in foo: Hi! == Hi! gorp: array/initial 10 foo == [Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi!] foo/2: #a == Ha! gorp == [Ha! Ha! Ha! Ha! Ha! Ha! Ha! Ha! Ha! Ha!] Given the available documentation for ARRAY: ? array USAGE: ARRAY size /initial value DESCRIPTION: Makes and initializes a series of a given size. ARRAY is a function value. ARGUMENTS: size -- Size or block of sizes for each dimension (Type: integer block) REFINEMENTS: /initial -- Specify an initial value for all elements value -- Initial value (Type: any) it is consistent that the (single!) initial value is uses for all elements. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] [array] [syntax] Re: Some other questions
Hi, Mike, Anton has already given a direct answer, but let me dig deeper. Mike Loolard wrote: 1) If I have an object - how do I create an array of objects with it ? for example chicken: make object! [ tasty: wings ] now I would want to have an array of objects of that type. I tried it like that: chickenfarm: make chicken [] array 10 It doesn't seem to work that way, though ? What you have written is two distinct expressions: chickenfarm: make chicken [] and array 10 One of the crucial light-bulbs that went on in my head when I first began using REBOL is the following: REBOL has no syntax! (other than the low-level lexical syntax for e.g. strings, numbers, etc., but I keep the sentence short for emphasis and effect.) All you have in REBOL is values, and when you put a bunch of them together, you have expressions. That's all. So let's look at the expressions you wrote, step by step. chickenfarm:; this is a set-word which will take the value ; of the immediatly-following expression make; use HELP; make wants a TYPE/SAMPLE and a SPEC chicken ; this is an object, so MAKE will create an object [] ; ... with this spec, i.e. with the same words ; as the original chicken with no added words ; or new values for the same words At this point, make has a prototype object and an empty spec, so it can construct a new object just like CHICKEN. Then, at that point, the expression following CHICKENFARM: has completed evaluation, so CHICKENFARM is set to that result. Now we continue: array ; again, use HELP, to learn that ARRAY wants a 10 ; size (but the initial value is optional). So... At this point, ARRAY has a size (but no initial value, as you didn't use the /INITIAL refinement) and so happily creates a 10-element block, with each element being NONE (REBOL's value that means nothing here). I hope I'm not insulting your intelligence with the details above! Reading through your email, I get the feeling that you may still be trying to read/write REBOL as if it were some other language, and just want to suggest a shift in perspective that I found helpful when I was beginning with REBOL. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] [enum] Re: Some other questions
Hi, again, Mike, Mike Loolard wrote: 2) How do you create custom types ? I am talking of a way to emulate the typedef behavour in C ? How would you go to create an enum type in REBOL ? Strictly speaking, there are two answers to your first question: 1) You can't. But REBOL has a very rich set of types already, so you can often find a type that suits your purpose (if you ask yourself the right questions!) 2) You can create objects, and use those as prototypes to creat other objects. There's a real problem is with your second question (and if you don't read anything else I write, PLEASE remember this one!) COBOL is alphabet blocks. C is a set of tinkertoys. Java is an Erector Set (IIRC similar to Meccano in Europe?) with all kinds of braces, motors, girders, nuts, and bolts. Perl is a Swiss-army chainsaw. REBOL is modeling clay. Learn to use each one according to its own nature. Let's talk about question 3 and then return to the first one. As I said above, we must first ask ourselves the right questionS. If your question is really How can I create a set of names for distinct, related values to use in my REBOL program? Then the answer is easy: words! Suppose I am doing something with personnel data, and want to represent the status of each employee. I could do something like the following: employee: make object! [ ID: 0 name: hire: now/date status: 'full-time ] Notice that the STATUS attribute is a word! value, whose name is chosen for mnemonic value. That's all there is to it. Now let's proceed to hire some people, with: bob: make employee [ ID: 1234 name: Robert R. Robertson hire: 01-Jan-1997 ] carol: make employee [ ID: 2345 name: Carolyn C. Carroll hire: 14-Feb-1998 ] ted: make employee [ ID: 3456 name: Theodore T. Theoden hire: 27-Nov-1999 status: 'part-time ] alice: make employee [ ID: 4567 name: Alicia A. Allison hire: 31-Dec-2000 status: 'leave ] Notice that BOB and CAROL are created with the default status of full time, while TED and ALICE each have different status. Here we had to quote the words, making them LIT-WORD! values, to keep REBOL from trying to evaluate them. We don't care about whether there's a value associate with e.g. LEAVE , but simply want to use the word itself as a label. Let's use a block as our pretend database: all-employees: reduce [bob carol ted alice] The reason we had to REDUCE that block is that here we don't want a block of words, but want a block containing the objects that those words are set to. (We could also have written a constructor function which would make a new employee from the arguments passed to it, and would append that new employee to ALL-EMPLOYEES at the same time.) Then we can produce an employee report, grouped by status with the following (rather inefficient!) function: group-report: func [ /local count ][ foreach [ status title ][ full-time Full Time (at least 35 hrs/wk) part-time Part Time (up to 34 hrs/wk) leave Leave of Absence (half benefits) suspended Disciplinary Suspension (no benefits) terminated Not Here (no further information available) ][ count: 0 print [title newline] foreach emp all-employees [ if emp/status = status [ print [tab emp/hire tab emp/ID tab emp/name] count: count + 1 ] ] print [newline count employees in this status newline] ] ] When we evaluate that function, we get: group-report Full Time (at least 35 hrs/wk) 1-Jan-1997 1234Robert R. Robertson 14-Feb-1998 2345Carolyn C. Carroll 2 employees in this status Part Time (up to 34 hrs/wk) 27-Nov-1999 3456Theodore T. Theoden 1 employees in this status Leave of Absence (half benefits) 31-Dec-2000 4567Alicia A. Allison 1 employees in this status Disciplinary Suspension (no benefits) 0 employees in this status Not Here (no further information available) 0 employees in this status Notice that the second argument to the outer FOREACH in the function above is a block containing alternating WORD! and STRING! values: the word is the name/symbol of a status, and the string is the associated description. (In a real application, this would be global to the entire application, of course!) Since we didn't REDUCE that block, we literally have words and strings. The REBOL word type can be used in this way --
[REBOL] Re: [array] Some other questions
Hi, Andrew, A J Martin wrote: Hi, Joel! /initial -- Specify an initial value for all elements it is consistent that the (single!) initial value is uses for all elements. Hmmm, at the moment, I can't see a good use for an array that has multiple references to the one series or object. :-/ The /Initial refinement seems, to me, to indicate a initial value for each element, implying that each element in the result is distinct. I guess we're just differing over the interpretation of the words here. I read the phrases a value for all elements and a value for each element as slightly different (but see below). I believe that 'array is more useful to most people when each value is a unique value, like: When dealing with reference values I certainly agree that it would be more useful if /INITIAL gave a *spec* to be used to construct an initial value for each element. My quibble was only with the notion of calling the present behavior a bug, instead of saying that it would have been more useful if ARRAY worked in the way that you (and I) would have expected. I'm just being an old grouch on this point because I've recently been bitten again by a subtlety that isn't documented anywhere that I could find, so I had to resort to particle physics just to figure out what the interpreter was doing (and have to hope that it won't change in a future release). It's just my old build-to-spec temperament, chanting: If there ain't no spec, there ain't no bugs! ;-) -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] [datatypes] action! vs. native! vs function!
Hi, all, OK, so a FUNCTION! is a function written in REBOL itself (what FORTH used to call high-level in contrast with primitive). I've always thought of NATIVE! as primitive in the above contrast -- a function written inside the interpreter in C (or whatever), but then ACTION! enters the picture and leaves me scratching my head. Does anyone know the difference between NATIVE! and ACTION! types? -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] [constructors] Re: Some other questions
Hi, Mike, Mike Loolard wrote: 3) Back on objects: objects seem to be pretty neat in REBOL - but I didn't find anything about implementing and using constructor/destructors ? I know I could manually add a function that serves as constructor each time I create an object, but is that the way REBOL requires it ? You don't need constructors in REBOL. Since REBOL also doesn't have classes, objects can either be created directly: tally: make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0] ] or created from a prototype object. In this second case, you must supply a block (possibly empty) of changes or additions. The simplest case is constructing another object with identical properties: tally2: make tally [] whose initial values will be based on the current values of the object used as a prototype. You can also base a new object on an existing one, but make some changes in the initial state, add methods/attributes, or change methods. enr0n: make tally [ total: 100 put: func [x [number!]] [ total: total + x + 100 count: count + 17 ] ] If you *want* to implement a function that serves as a constructor, you certainly can, using the above standard capabilities. As OBJECT! is a first-class data type in REBOL, there's nothing magical about writing a function which returns an object: make-tally: func [] [ make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0] ] ] ...but that doesn't buy us much. It would be more useful if we had a small number of attributes that were initialized based on the function's arguments, but that's just a convenience issue, not a fundamental issue of REBOL capabilities. Finally, when I know I will be using multiple similar objects, I have sometimes put a function within the object itself to provide me with another, similar object (again just for convenience), as in: tally: make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0] new: func [/local result] [ result: make self [] result/reset result ] ] That way the fresh instance is always initialized to some standard beginning state. Actually, I'd be more likely to write this as: tally: make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0 self] new: func [] [do in make self [] 'reset] ] As for destructors, there's little need in REBOL as memory management (including garbage collecting) is automatic. If you *want* to add a method to an object to release big data structures, print final state, or whatever, you can certainly do so, but you'll have to invoke it for yourself, as the concept of an automatic call to a finalizer is not in REBOL. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Some other questions
Hi, Mike, Mike Loolard wrote: 4) In the same context: how do I actually 'free' memory/variables ? You don't need to do so, as memory management in REBOL is automatic (including collection of circular garbage). However, if you are doing some processing of large structures, you can limit the need for REBOL to go back to the O/S and ask for more memory by clearing out stuff you no longer need. If you only have one word that refers e.g. to a large block, you can simply set that word to a trivial value, such as NONE, to make the previous contents available for garbage collection. blort: make block! 10 repeat i 10 [append blort sine i] ; whatever ; then, after that block is no longer needed... blort: none You can also use CLEAR to remove all values from a series (from the current position). This can be handy if you want to reuse the space after the initial contents are no longer needed. blort: make block! 10 repeat i 10 [append blort sine i] ; do something with sines clear blort repeat i 10 [append blort cosine i] ; do something with cosines clear blort repeat i 10 [append blort tangent i] ; do something with tangents ;... etc. But, again, unless you're working on huge structures, have a long- lived process, and are running on a small-memory or slow box, there's seldom any reason to worry about such things. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: [data structures] (was Re: [append][series]Appending to a series of strings)
Hi, Ladislav, et al, Ladislav Mecir wrote: Joel Neely napsal(a): REBOL seems to occupy a middle-ground position on this issue; it does not require you to declare the existence of a data structure (as e.g. Java does) but it *does* require that you allocate and initialize it explicitly. I think, that you are describing *only* a top-down approach here. A bottom-up approach might lead to: No, not the way I understand those terms (top-down = beginning with the overall top goal and working down to successively finder- grained detail; bottom-up = beginning with detailed bottom concepts and aggregating/building them up to the final goal). Those terms have to do with *when* in the development process we address a given level of detail; what I'm trying to focus on is the issue of *whether* certain levels of detail have to be addressed at all (regardless of when). get-value: function [ ... ] set-value: func [ ... ] inc: func [ ... ] ... In Rebol you can teach the language to do what you want it to, because Rebol facilitates the process of the language extension. While I would probably write such things as methods on an object, presenting those capabilities as three individual functions is certainly a way to get the job done. But in either case, whether we sweep those details under an object or into separate functions, the fact remains that -- at some point in our design and development process -- we had to pick up the broom! ... Finally, (back to the original discussion) Perl will even automatically figure out when to allocate/initialize structures and elements for me. What if you needed a different default value, wouldn't that leave you on your own in Perl? Certainly, although the default applied in a given case depends on the operation being performed: zero for numerical operations and the empty string for string operations. And overriding those defaults is easy; if we wanted to accumulate products of values associated with keys (instead of sums) the key expressions would be: if (defined $tallies [$key]) { $tallies [$key] *= $val; } else { $tallies [$key] = $val; } or $tallies [$key] = 1 unless defined $tallies [$key]; $tallies [$key] *= $val; And note, in passing, that the test to see whether a given element of the data structure is defined is independent of what types of data might be stored there. The corresponding test in your GET-VALUE was equivalent to: value: pick array index + 1 either value [value] [0] which would have to be re-engineered if we wanted e.g. an array which might include LOGIC! or NONE! values. (The fact that we even have to think of such details is again my real point here.) I think, that the effect on thinking in Rebol may be caused more by inertia than by language limitations. I'm not condemning REBOL for limitations, but merely observing that different language designs reflect the designers' philosophies of programming and choices about what would be most likely needed by the programmer. And I could certainly give examples of nice REBOL features of REBOL that aren't built into Perl (see footnote). I'd certainly agree that inertia in the sense that one tends to think in habitual ways is a factor in almost everything we humans do. But please reread my statement before taking issue with it: As a polyglot, I'm less interested in picking sides in a political debate than understanding deeply the effects on my own thinking when I begin to think like a native in one or more of them. As one begins to think like a native in language X, that means that one has begun to overcome the pre-X habits, IMHO. I'm not going to lay any claim to REBOL-guru-hood, but I do believe my approach to writing-in/thinking-with REBOL is different than when I began using it some years ago. I recently spent some time with a decades-old book of programming puzzles of the recreational mathematics flavor. I used REBOL to construct my solutions, then compared my approach with the code in the back of the book (given in C, BASIC, and Pascal). I was repeatedly struck by the differences in my designs and those of the book -- to the point that it was very difficult to compare some of them in any meaningful way (although REBOL on my 600 MHz laptop handily outperformed the timings in the book for compiled C on an 8MHz Pc! ;-) I often used recursive functions and/or dynamically-managed blocks in my solutions; needless to say, both of these were absent from the book. But my interest goes even deeper than language features. In at least one puzzle, I had a single loop that operated on a small number of variables holding only integer values. But the thought process by which I arrived at that solution was radically different than that taken in the book's solution. To whatever degree my design approach was an improvement over the book's (and over my
[REBOL] Re: FW: Re: [append][series]Appending to a series of strings
Hi, Ladislav, Actually, it's not faster (for sufficiently large cases). See below. Ladislav Mecir wrote: Hi, my solution using Parse (I think, that it is much faster, than other solutions): I did a bit of benchmarking with functions that use each of the three strategies to generate a block of answers (value/count pairs). I'll include those functions at the end, in case anyone wants to verify that I didn't mangle any code. Using a SCORES block of random numbers between 0 and 100 (inclusive), the iterative version scales up better than the parse-based version as the size of the SCORES block increases (all times in seconds): sizeiterative remove-each parse-based 10001E-20.28 0 1 0.3512.8740.24 10 3.024 36.8134.637 20 4.787 --4.556 30 6.74--6.94 40 8.832 -- 14.371 50 11.887 -- 18.517 100 21.891 -- 39.227 I gave up VERY quickly on the remove-each-based version; it gets eaten alive by memory management overhead. Since the parse-based version sorts (a copy of) the scores block, its time complexity must be at least O (n log n). The iterative version is only O (n), so it will be faster for sufficiently large n. I should also point out that the iterative version requires only one value at a time; it can work on an arbitrarily large set of values (e.g., being retrieved across a network connection, read from a huge data file, resulting from computation in a loop, etc.), but the remove- and parse-based versions require the entire set to be available for sorting. There's one final point, but I'll post it separately. -jn- Ladislav Mecir wrote: scores: clear [] loop 30 [append scores random 20] group: [p: set i integer! any i q: (print [score: i tallies: offset? p q])] parse probe sort scores [any group] -Original Message- From: Anton Rolls [mailto:[EMAIL PROTECTED] ; initialize some random scores scores: clear [] loop 30 [append scores random 20] ; figure out how many of each score tallies: clear [] foreach uscore sort unique scores [ append/only tallies reduce [ uscore length? remove-each score copy scores [uscore score] ] ] SOURCE CODE FOR TIMED FUNCTIONS IS GIVEN BELOW: ;iterative version tally-i: func [ scores [block!] /local tallies result ][ tallies: copy [] foreach score scores [ either found? here: select tallies score [ here/1: here/1 + 1 ][ insert tail tallies reduce [score copy [1]] ] ] result: make block! length? tallies foreach [score tally] sort/skip tallies 2 [ insert tail result score insert tail result tally ] result ] ;remove-each-based version tally-r: func [ scores [block!] /local tallies ][ tallies: clear [] foreach uscore sort unique scores [ append/only tallies reduce [ uscore length? remove-each score copy scores [uscore score] ] ] ] ;parse-based version tally-p: func [ scores [block!] /local group p q result ][ result: copy [] group: [ p: set i integer! any i q: ( insert tail result i insert tail result offset? p q ) ] parse sort copy scores [any group] result ] -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] [data structures] (was Re: [append][series]Appending to a series of strings)
Hi again, Ladislav and all Joel Neely wrote: Hi, Ladislav, I did a bit of benchmarking with functions that use each of the three strategies ... There's one final point, but I'll post it separately. This has been very interesting, and your parse-based solution is an *excellent* illustration of thinking with series-level operations instead of element-level operations -- a classic bit of REBOL-style thinking IMHO. Perhaps I should blame my illustration that started this -- or how I explained my request for alternative solutions -- because I was trying to focus on a different issue than histograms! (although it DID have to do with language thinking styles ;-) The design of every language with which I'm familiar reflects at least two issues: the conceptual model used by the designer(s) (or lack thereof!) and the decisions about what things to make easy for the programmer using the language. Both Perl and REBOL make it easy to use a variable -- you just start using it and the language keeps up with what you're doing; no advance declaration is required. OTOH Java makes it easy to detect errors in type mismatch as early as possible (at compile time), which REBOL and Perl can't catch until the program is running. Perl goes further and makes it easy to use data structures; if you try to modify/store data, the appropriate place is automagically created (and initialized to an appropriate value, depending on the operation you are performing). The Perl expression ++$array[$n] means add one to the nth element of array. If the array doesn't have n elements (or if the array doesn't even exist!), Perl will allocate that position and and initialize it to zero before evaluating your expression. REBOL seems to occupy a middle-ground position on this issue; it does not require you to declare the existence of a data structure (as e.g. Java does) but it *does* require that you allocate and initialize it explicitly. REBOL certainly has some nice built-in facilities for processing series data, but once you leave those you are *really* on your own. My original dinky demo was intended to compare that one expression above with insert/dup tail tallies 0 score + 1 - length? tallies change at tallies score + 1 1 + pick tallies score + 1 or either found? here: select tallies score [ here/1: here/1 + 1 ][ append tallies reduce [score copy [1]] ] which are the equivalent in REBOL (given that it's the programmer's responsibility to allocate and initialize the tally structure). Of course, I'm well aware that I could initialize the tally structure for e.g. all key values between 0 and 100 as a way to avoid the dynamic initialization issues above... (But my experience tells me that as soon as I do that, some teacher will add an extra credit problem so that some students can score 110! ;-) Language design decisions have far-reaching (and often subliminal) effects on the subsequent design thinking of programmers using the language(s) in question. One such issue that I find interesting is the question of when I -- as the programmer -- must commit to a decision regarding the data structures used within my programs. COBOL and Pascal require that I commit to the type and size of every array before submitting my programs to the compiler, and initialize the structures appropriately (at run time, but before any other use). Java requires me to commit to the type of an array, but lets me defer the size committment until run-time when I actually initialize it. Newer versions of Java provide the Vector class, which can be thought of as an array that can change size during use. Perl and REBOL (and Python, et cetera) arrays/blocks not only let me dynamically resize during use, I don't even have to commit to a single type of data to put there! Finally, (back to the original discussion) Perl will even automatically figure out when to allocate/initialize structures and elements for me. Advocates of each of these languages will offer passionate arguments for why the binding-time choices of their preferred language are good. As a polyglot, I'm less interested in picking sides in a political debate than understanding deeply the effects on my own thinking when I begin to think like a native in one or more of them. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: [data structures]
Hi, Gregg, Gregg Irwin wrote: ... For example, how would we build constructs in REBOL to emulate what Perl does with auto-sizing arrays, Exactly what I was hoping for. As an example, I've been using the nested-block trick to simulate mutable arrays in REBOL for some time, and have no specific problem/complaint with it (other than the fact that it looks a bit funny... ;-) However, I was hoping for some additional suggestions from the list. or what would a Perlite/Perler/Perl-monger (proper term?) do to provide protection *against* auto-sizing if it wasn't desired. I can think of three alternatives right off: ++$array[$n] if $minOK = $n $n = $maxOK; to ignore OOBVs (out-of-bounds values), ++$array[$n $minOK ? $minOK : $maxOK $n ? $maxOK : $n]; to force OOBVs to the violated boundary, or ++$array[$minOK = $n $n = $maxOK ? $n : $default]; to force OOBVs to some default bucket. The last two index expressions (for those not familiar with C or Perl) are essentially equivalent to the REBOL expressions either n minOK [minOK] [either maxOK n [maxOK] [n]] and either all [minOK = n n = maxOK] [n] [default] I'd actually write the first of these in REBOL as max minOK min maxOK n To say that in Perl one would need to define the min and max functions, as they aren't built in. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: [append][series]Appending to a series of strings
Hi Seth, See below... Seth wrote: a: [1 2 3 4 5] == [1 2 3 4 5] b: [] == [] x: index? a == 1 append b/:x hi == hi At this point, take a look at the value of B to see why: b == [hi] fourth b ** Script Error: Out of range or past end ** Near: fourth b b/:x == none x: index? find a 4 == 4 At this point B has no fourth element (ergo B/:X returns NONE) so... append b/:x hi ** Script Error: append expected series argument of type: series port ** Near: append b/:x hi In theory, shouldn't append do it's thing on b/4 ... What's with the error? :\ ...you can't treat that (non-existent) element as a series. Unlike Perl, which automatically allocates and meaningfully initializes previously non-existent data, REBOL requires that a value exist and be of the correct type for whatever operation you attempt to perform on it. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: [append][series]Appending to a series of strings
Hi, Seth, Seth wrote: Joel Neely wrote: ...you can't treat that (non-existent) element as a series. Unlike Perl, which automatically allocates and meaningfully initializes previously non-existent data, REBOL requires that a value exist and be of the correct type for whatever operation you attempt to perform on it. Thanks everyone... I was coming from a Perl point of view here -- The REBOL way is a lot more logical -- This is what I get for coding at ungodly hours in the morning ;] Thanks... :D IMHO neither more nor less logical, just differently logical. Suppose one has a collection of small natural numbers (such as test scores ranging from 0 to 100) and one wants to know how many occurrences of each distinct number there are. Using Perl arrays: # assume @scores contains the raw data with dups @tallies = (); foreach $score (@scores) { ++$tallies[$score]; } foreach $score (0..$#tallies) { print $score: $tallies[$score]\n if $tallies[$score]; } Using REBOL blocks: ; assume SCORES contains the raw data with dups tallies: [] foreach score scores [ insert/dup tail tallies 0 score + 1 - length? tallies change at tallies score + 1 1 + pick tallies score + 1 ] forall tallies [ if 0 tallies/1 [print [-1 + index? tallies : tallies/1]] ] or ; assume SCORES contains the raw data with dups tallies: [] foreach score scores [ either found? here: select tallies score [ here/1: here/1 + 1 ][ append tallies reduce [score copy [1]] ] ] foreach [score tally] sort/skip tallies 2 [ print [score ; tally/1] ] REBOL is much more literal; there are no values that one does not explicitly create (although it is possible to be implicitly explicit at times ;-). On the other hand, it is necessary explicitly to manage details that aren't at the same logical level as the original problem (making sure that there enough places to store the next tally needed, etc). I'd be interested in any *self-contained* solutions to the above task that might be clearer than the above. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] REBOLforces site down?
I'm experiencing breakage with some links on www.rebolforces.com, including the email link at the bottom of the front page. Is that site out of service, or are there just some glitches? -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: RSA Encryption
Hi, Matt, I'll give it a shot... Matt MacDonald wrote: Can someone please explain to me, in as few mathematical equations as possible, why RSA public/private encryption works? ... How is this any different from using a syncronous encryption method and then just sending the encryption key along with the data? It just doesn't make sense to me. Let's sneak up on it. For simplicity of examples, suppose that all of my messages will be made up of ONLY uppercase letters, spaces, periods, or question marks (29 possible characters). We can represent our characters via: 0 = space, 1-26 = A-Z, 27 = period, 28 = question mark and then encode messages by doing arithmetic on the numbers ( as long as our results are limited to the range 0-28). A trivial example would encode by adding some fixed value (mod 29) to the plaintext and decode by subtracting that same fixed value (mod 29) to the plain text. Here the here the algorithms for encoding and decoding are different, but the keys for those operations are the same. Let's make the algorithm the same (by adding the key mod 29 to each value), which means that the decoding key is must be the mod-29 complement of the encoding key. IOW, if I encode by adding 3, I decode by adding 26. In that simple case it is trivial to figure out the decoding key from the encoding key. Suppose I multiply by the encoding key (mod 29) instead. It's a bit more work, but still easy to figure out what decoding key I can multiply by (mod 29) to get back the original character. Suppose I use two encoding keys (a and b) and encode a character by evaluating encoded-character: a * plain-character + b // 29 Now it's slightly more complicated (or just plain time consuming) to figure out what values of (c and d) will give me plain-character: c * encoded-character + d // 29 i.e. the original character's number. Enough dinky examples. As we increase the mathematical complexity of the formula, we discover that that the effort to find the decoding key *EVEN IF WE KNOW THE ENCODING KEY AND THE FORMULA* can increase substantially. Public key cryptography is based on using certain mathematical operations that *NOBODY* knows how to invert in reasonable time. (Of course, that could change dramatically if quantum computing provides us a way to factor arbitrary huge numbers quickly!) Anyway, that's the core idea of why the public key can be made ... well ... public! without exposing the message content. HTH! -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Another coffee break problem?
Hi, Gregg, Gregg Irwin wrote: JN The following 3-by-3 display is a simple magic square: JN 0 8 4 JN 5 1 6 JN 7 3 2 JN because each row and each column sums to 12... No diagonals? I thought magic squares had to work on the diagonal as well? (not to be nit-picky or anything :) To be equally picky ;-) That's why I said simple magic square instead of totally magic. I was going to post a follow-up problem to refine the first program so that it also checks diagonals. Also, not all sources I've looked at insist on diagonal operations. One interesting way to generalize the problem is to magic rectangles with different height and width. In that case, the definition of diagonal becomes more interesting... -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Another coffee break problem?
Hi, Anton... Anton Rolls wrote: I can see you are going to ask us to generalize it later so it can do integers higher than 8. Since Gregg has already partially debagged the cat, I'll admit that I have some generalizations in mind, but not that particular one ;-) I think for this set of numbers 12 is the only sum you will get, but just to be clear, shouldn't it be: it's a magic square because each row and column sum to the same number ? Yes, but only because a square is a rectangle with the same height and width... WARNING: YOU ARE NOW ENTERING THE [scary music] ALGEBRA ZONE! A rectangular display of numbers with R rows and C columns contains R*C cells. The simplest way to fill those cells with distinct values is to use the first R*C natural numbers, such that 0 = n R*C. The sum of all of the values is then (+i : 0 = i R*C : i) = R*C * (R*C - 1) / 2 Adding the requirement that all row totals be equal tells us that the row total must be the grand total divided by the number of rows, so all row totals = R * C * (R * C - 1) / 2 / R = C * (R * C - 1) / 2 and likewise all col totals = R * C * (R * C - 1) / 2 / C = R * (R * C - 1) / 2 so that e.g. for a 3 x 5 simple magic rectangle, grand total= 3 * 5 * (3 * 5 - 1) / 2 = 15 * 14 / 2 = 15 * 7 = 105 all row totals = 105 / 3 = 35 all col totals = 105 / 5 = 21 and, of course, if R and C are equal, the magic row and col totals will be equal (so e.g. for the 3 x 3 case, 9 * 8 / 2 / 3 = 12). If I wanted to be sneaky, I'd ask how many magic rectangles there are with 99 rows and 100 columns! YOU ARE NOW ENTERING AN ALGEBRA-FREE ZONE! ;-) HINT AHEAD -- Don't read if you want to solve it on your own steam! . . . . . . . . . . Since there are 362880 ways to arrange 9 distinct values, the key issue is to do something more economical than simply generating all possible permutations, checking each one for magicness. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Curiosity
Hi, Carlos, For educational purposes (and just for fun... ;-) I'm currently using REBOL on all of the following platforms: Mac OS/X, Linux, W2000, WXP, W98, Solaris I might add that I am only using /Core features. One of the main reasons I began using REBOL (the same is true of Perl, Python, ... in short, all of my tools of choice) is the cross-platform support. Until View is available for OS/X, I will not use it. -jn- Carlos Lorenz wrote: Hi list, I am very curious about to know how many of us use REBOL under Linux and how many use REBOL under Windows both at work and at home. Would you mind answer a this? Thanks Carlos -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Opening Specific Ports
Hi, Matt, I claim no guruhood re networking, but... IIRC, firewall rules can take both origin and destination ports into account. Could they use a rule that allows any client-side port, as long as it is attempting to connect to a specified server/port where the authorized service is available? -jn- Matt MacDonald wrote: I'm making a client software for other users. I need to somehow limit the ports that rebol will try to open on their computers so that their company firewalls can be configured to allow access over those ports. Or am I going about it the wrong way? Any networking gurus out there? -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Looking over the horizon - Rebol 3
Hi, Andrew, Thanks for starting what I hope will be a productive thread! Now, speaking strictly for myself, little of my REBOL wish list is about adding features to the language. Andrew Martin wrote: * Lots more datatypes! For example, a Telephone! data type, temperature, audio/sound data-type, metric and imperial units like 123.5Km, 50MpH, and so on... No. Please, no. Please, please, no. There have been plenty of threads in the past about the confusing and not-completely-documented behavior associated with the existing plethora of types. Do we really want that situation compounded??? (e.g. what happens when I add 2 to 123.5Km, what happens when I multiply 50MpH by 32F, ...) I realy have only two wishes in regard to data types: 1) Fully document the existing ones. 2) Add support for promoting objects to true user-defined types. I hope the first is obvious (and non-controversial) to the list. Let me give a trivial example of the second issue, and then apply it (in a non-trivial way, I hope! ;-) to your wish list above. REBOL has a PAIR! type which can be used for 2D points, but suppose I am working on projective geometry in a serious way. I can define ; projective point ppoint: make object! [ u: v: w: 0 ; projective coordinates of pline to-string: func [] [...] ; create a printable representation ... ; other natural behavior of a ppoint ] ; projective line pline : make object! [ p: q: r: 0 ; projective coordinates of pline to-string: func [] [...] ; create a printable representation ... ; other natural behavior of a pline ] after which I can sprinkle such things as the following thru my code: P1: make ppoint [u: -1 v: 2 w: 1] P2: make ppoint [u: 4 v: 5 w: -1] L1: make pline [p: 1 q: -1 r: 0] but the list of useful things I *can't* do includes the following: ; function that returns the point where two lines intersect common-point: func [l1 [pline] l2 [pline]] [ ... ] ; function that returns the line joining two points common-line: func [p1 [ppoint] p2 [ppoint]] [ ... ] ; is the given point on the given line? pt-on-line?: func [p1 [ppoint] l1 [pline]] [ ... ] print [line 2 is common-line P1 P2] ; and get meaningful output P3: 2 * P1 ; by defining for REBOL what it means to multiply ; a ppoint by a number If I want to define a function that takes a ppoint as an argument, I can only say: some-function: func [ppt [object!] ...] [...] but then REBOL will allow *any* object to be passed (likely giving me a run-time error when I try to actually perform some operation on/with it inside the function body). Now, let's apply this idea to your list; many of your desired types are just numbers with an associated dimensionality -- so many degrees F (or C or K ...), yea many pounds (or grams or kilograms or stone ...), and (with composite dimensions) thus many grams per cubic centimeter (or miles per hour, or liters per second ...) If we had true type support for objects, we (*any* REBOL programmer with enough experience/determination) could write something like (I'm making this up as an illustration, so it's not debugged! ;-) dimensions: make object! [ numerators: [] denominators: [] to-string: func [] [...] ... ] dimensioned-number: make object! [ value: 0 units: make dimensions [] to-string: func [] [...] ... ] distance: dimensioned-number 6 [mile] how-long: dimensioned-number .1 [hour] print distance / how-long ; or print divide distance how-long and get 60 mile per hour Then someone who wanted to compute earth's escape velocity in furlongs per fortnight could do so without further support from RT! * A way to access words outside of the current context. Perhaps extending the refinement! data-type, like: /Foo: 123 ; set the value of 'Foo outside this context to 123. Could you give an example of what this means and how it would be used/useful? I must confess that I don't understand it at all. * Regular Expressions as well as parse, which acts much like Perl's regexp. At the risk of sounding inconsistent, I believe that this one added feature would do more to broaden REBOL's appeal than anything I've seen on the list in a long time. Even though there's some variation in syntax (and number of extensions), REs are a core, mainstream concept in the world I live in. Recognizing that fact, and making a (tiny) concession to the existing skills of the programming community would eliminate one more excuse for serious geeks to dismiss REBOL. * Native XML! data-type. My top XML wish is simply a beefed-up XML parser which does validation
[REBOL] Another coffee break problem?
If Sunanda will allow me to steal his subject line... ;-) The following 3-by-3 display is a simple magic square: 0 8 4 5 1 6 7 3 2 because each row and each column sums to 12. Write a function which uses the integers 0 thru 8 (once each!) to construct all possible 3-by-3 simple magic squares. Make it run as quickly as possible. -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: REBOL hosting
Hi, Gabriele, That doesn't always work... Gabriele Santilli wrote: Unless the server is braindead (i.e. Windows ;-), you just put the REBOL binary somewhere in your space (possibly out of the web accessible area) and use the CGI extension for your scripts. However, having support from the techs is usually a good thing; so, a hosting company that treats REBOL nicely is good news anyway. The .cgi extension doesn't work unless the server is configured for it. Non-braindead web servers (e.g. Apache, Netscape, etc.) don't serve cgi scripts from user space unless specifically configured to do so. Some (many?) ISPs choose not to turn these options on, out of concern for one or more of the following: - security, - wanting to prevent unskilled programmers from writing code that consumes too much resource (e.g. cpu, ram, disk, etc.), - preventing their users from generating spam, - etc. For many of the same reasons, ISPs often do not allow (or charge more, or require special arramgment for) shell access. Assuming that the server is running A Real Operating System (e.g. Linux, Unix, et familia) one may need shell access to make a file executable, even if one can upload it to one's filespace. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: REBOL hosting
Hi, Gabriele, YMMV Gabriele Santilli wrote: JN The .cgi extension doesn't work unless the server is configured for it. Of course, but a standard installation of Apache comes with a cgi-bin directory and .cgi extension preconfigured (as well as .pl, usually). My experience has been different. In the instances of Apache I've worked with, the cgi-bin directory is generally writable only by the admins, not by users in general, and .cgi service from user directories has to be enabled (is not enabled by default). JN Assuming that the JN server is running A Real Operating System (e.g. Linux, Unix, et familia) JN one may need shell access to make a file executable, even if one can JN upload it to one's filespace. Usually FTP does it nicely, you just need a decent FTP client. Only if you're coming from another Linux/Unix/etc box. If you FTP from a 'doze box, the bits aren't set IME. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Coffee break problem anyone?
Hi, Sunanda, [EMAIL PROTECTED] wrote: Your point is that it is usually best to start with the data structures. I'd agree. But it isn't always that simple. I agree. Sorry for not being more precise. What I should have said (adding the omitted conditions/details) was: For problems where the input/output (or argument/result) data structures are already defined, it is usually very helpful in design, implementation, and maintenance to use the I/O (a/r) structures as much as possible as guides for the algorithm structure. This approach usually helps minimize redundant code, gives unambiguous guidance to where each part of the code should be placed in the algorithm, and minimizes the risk of bugs arising from accidental mismatches between the flow of the algorithm and the flow of the data. Of course, in cases where the nature of the data are somewhat up in the air (e.g. the problem is more vaguely specified, or the designer is given latitude to choose data/representation structures) there's clearly not so much heuristic guidance. Also, if the structure of the data changes, it may imply significant rework of the program. The actual original task was to find the best why to describe the differences between two version of the same file. There is a lot of subjectivity there. That's exactly what I meant by not well-defined. I don't mean that as a negative description, but simply as an indication that there may be a period of more exploratory programming to try different ideas before choosing one as the basis for final design and implementation (or that the program may very well simply evolve, as various ideas/heuristics are added and tweaked). I suggest that in such a case, there's benefit from a program structure that makes it easy to figure out where to put such heuristics (and where to find them when its time to change or delete them;-) But best and better depend on the resources available. In this case, they are a little restricted: Again, we'll certainly agree that the juggling and comprimises made when shoehorning a 10-pound algorithm into a 5-pound interpreter are at least as much art as science! ;-) -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: syntax across languages
Hi, Maarten, and all, There's a serious question at the end of all the yammering below! ;-) Maarten Koopmans wrote: came accross an interesting site on syntax across languages which is soliciting help with constructs in various languages including rebol. They are currently missing 120 syntax constructs for rebol. Most of them are available in REBOL but not in the comparison. If I only had time... I can relate! On the other hand, I'm also ambivalent their terminology; the table of contents maintains the syntax pretense, but there are really three different levels being addressed (somewhat indiscriminantly): 1 lexical rules (e.g. structure of a user-defined name/word) 2 higher-order syntax (e.g. structure of an if statement) 3 language features (e.g. get type/class [of] object/instance/value) I'd be glad to be updated, but I haven't seen (1) fully documented anywhere for REBOL. (Remember recent -- and not so recent -- posts about what characters are allowed in a word? IIRC most such questions get resolved by trial and error or advice from someone who's already traveled that road, not by pointing to section x.y in the manual.) As for (2), it doesn't exists! I'm not trying to be pedantic here, but sincerely believe that one of the early steps to getting REBOL is to realize that e.g. THERE IS NO IF STATEMENT, but merely some functions (IF, IF/ELSE, EITHER) that take an argument of type [LOGIC! NONE!] and one or two arguments of type [BLOCK!] and, if you so choose, YOU CAN WRITE YOUR OWN. Being pragmatic, I know that a short answer to the question: How can I say the likely equivalent of if (buff [0] == '\0') { p--; } else { p = q % ++r; } is either zero? length? buff [ p: p - 1 ][ p: q // r: r + 1 ] but that doesn't necessarily help the questioner make the leap to p: either zero? length? buff [ p - 1 ][ q // r: r + 1 ] or even more REBOL-ish reconceptualizations of the programming task. That brings me to (3), where IMHO it becomes most clear that efforts such as the page in question often become either too encylpaedic for ease of use, or else too superficial for useful ... use. It's one thing to take two languages that share most of their conceptual base (e.g. Pascal and C, ALGOL and Pascal, etc.) and address in a fairly complete way the questionS (plural emphasized): - What are the correspondences between the languages (i.e. for those features that are conceptually similar, how does one respell from one notation to the other)? In this category, explaining that Pascal uses begin ... end for sequences of statements, while C uses { ... } is reasonable. - What are points of NON-CORRESPONDENCE between the languages, and what effect does that have on one's programming/design thinking? In this category, the nesting of lexical scope (e.g. procedures defined locally to enclosing procedures in Pascal, vs. the flatter, assembly- like model of C) can cause one to think and design quite differently. I should also add that many of the issues under the second point above often become significant when [only when?] designing programs that deal with larger-than-toy problems. But when approaching languages with substantially different conceptual models, the second issue becomes so dominant that the first issue is either irrelevant or misleading IMHO. For example, what is the REBOL equivalent for the elementary PROLOG idiom conc( [], L, L ). conc( [X | L1], L2, [X | L3] ) :- conc( L1, L2, L3 ). ??? As much as we might like to write conc: 'join that just won't cut it, when trying to understand why last( Item, List ) :- conc( _, [Item], List ). works. Inspired by discussions on this list, I started putting together some recipes for a Perl-to-REBOL cookbook. I say started because I was smacked in the face by the above issues on the very first recipe, which dealt with the Perl substr function. You see, in Perl, substr can be used both as an lvalue and an rvalue (a distinction which doesn't exist in REBOL). And OBTW, using an rvalue string expression as an rvalue in Perl implicitly copies, while an lvalue string expression mutates... And OBTW, the Perl splice function (more or less) does for arrays what substr does for strings, but REBOL blocks are the closest analog to arrays, and block! and string! types are both subsumed in the REBOL meta-type series! so instead of defining SUBSTR, shouldn't one actually define SUBSER and ... So instead of a one-page recipe, I suddenly had a very long chapter (I know you can't believe that I found lots to say on such a narrow topic ;-) and began to question whether anyone would bother to read it! On the other hand, I don't want to spend the effort to produce something that ends up being so superficial that it's a read-once-and-throw-away (as is the case with too many books and articles in the computing field
[REBOL] Re: syntax across languages
Hi, Maarten... Maarten Koopmans wrote: Wow! You can do a bind 'word [ multiple values ] in your real life? multitask-into-stress: func [word [word!] selves [block!]] [ forever [ foreach role selves [ do get in role word ] ] ] ; -) Any/all feedback/comments are welcome! Are the alternatives or refinements? Oops... my lexer got stuck (again) ;-) It's just a different dialect! ;-) -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Coffee break problem anyone?
Hi, Sunanda, First, let me offer an improvement and then address some more of the good discussion points you raise. (There's a little challenge at the end for the interested who wade through to that point! ;-) Minor issue first: instead of initializing run length to zero and incrementing for each added element, just directly calculate the length once the run is finished. Now for the more interesting stuff... Instead of saying that: - a block is an iteration of runs, and - a run is an iteration of numbers; block --*-- run --*-- number lets say that: - a block is an iteration of runs, and - a run is a first number, followed by any consecutive numbers. +-- first number | block --*--+ | +--*-- consecutive number This (again) addresses a boundary issue; the first value in a run plays a different role than the other numbers in the run. Tricky setup of initial conditions so that the first value can be treated just like all the others adds more complexity to the code. That said, here's a version that implements that view: where-j: func [ block [block!] /local maxpos maxlen runpos runlen prev curr ][ maxpos: maxlen: 0 ; default empty run while [not empty? block] [; more data = more runs runpos: index? block ; start new run here prev: block/1 ; remember first value block: next block ; done with first while [ prev + 1 = curr: block/1 ; extending the run ][ prev: curr; save comparison value block: next block ; move on ] runlen: (index? block) - runpos ; now compute length if runlen maxlen [ ; update best run? maxpos: runpos maxlen: runlen ] ] reduce [maxpos maxlen]; return best run ] [EMAIL PROTECTED] wrote: ... the insight that (in effect) the procedures can fall naturally out of an analysis of the data structures can lead to some very elegant solutions. Of course there are situations where neither approach works, and then you need other approaches too. Object-orientation is one claim to the next step as it merges both approaches. I never quite saw the point there, either, but it does work in some areas. I'm not clear on what you mean by both approaches... I view JSP (Jackson Structured Programming) simply as a specific type of structured programming which has strong heuristics about which structure(s) should drive the design. And then there are situations that seem completely off the deterministic axis. ??? Do you mean non-deterministic programming, or just programming when the criteria are only vaguely stated? Consider this progression: -- Find the sum of the numbers (simply almost any way: write a loop; use a map function, etc) Easy. Agreed. -- Find the longest run with the highest end value (101--107 in the original data) An easy extension of the above program: - add a local MAXTOP initialized to anything - change the condition at the end from runlen maxlen to any [runlen maxlen all [runlen = maxlen prev maxtop]] - change the new best run block to include maxtop: prev (For why this was easy, see below...) -- Find the run (as defined in the original problem) whose run length is the modal length of runs First, we have to change the run to a run, since the answer is no longer unique. For the data [10 8 9 6 7 4 5 0 1 2] there are runs of length 1, 2, 2, 2, and 3, so the mode length is 2, and there are three runs that have that length. However, something more significant has happened. The previous change to the problem (longest run with highest upper value) actually had THE SAME STRUCTURE as the original problem: find the best run, where we have a simple test for determining whether one run is better than another. In other words, we can generate runs one at a time, and test each one against the current best to see which one wins. But in this last change, we now are asking for a run based on some property/ies of the entire collection of runs, so we must generate (and retain) all of them. We can (trivially) change the above function to return all runs, then write a separate pick a median function to operate on that collection (or we build the additional stuff into the end of the modified function). In either case we now have a two-step approach: 1) transform the offered block into a collection of runs; 2) do something with the collection of runs. That's why the first change was easy and the second one was harder. --Find the two runs that are most nearly similar (contain mostly the same numbers) I think I
[REBOL] Re: Hitting the learning curve
Hi, Volker, Volker Nitsch wrote: Am Mittwoch, 5. November 2003 18:56 schrieb Steven White: ... So to easy my confusion I type all the REBOL words in lower case and all the words of my own invention in upper case, just like old COBOL. It is not recommended as a style, but it helps me personally. There is a script somewhere, %colorize.r? rebol.org? it takes a script and outputs colored html. words found in rebol itself have a diferent color.AFAIK. could be used/modified to show scripts with your own words more marked up. All of the above is more reason to use vim (or some other equivalent editor) that does syntax coloring. My normal development environment for REBOL is one or more vim windows (or terminal windows with vi[m] running in it/them, depending on platform) and a REBOL console. The edit/test cycle simply toggles between windows, and the syntax coloring is always there (without the need to run some utility to get a static view of the code that's outdated with the next editor keystroke). -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: function to object?
] [ count: usages: 0 foreach object object-inventory [ print [ object with factor object/constant was used object/usage times ] count: count + 1 usages: usages + object/usage ] print [count objects used a total of usages times] ] which gives us inventory-usage-report object with factor 2.54 was used 1 times object with factor 4.546 was used 2 times 2 objects used a total of 3 times And (assuming we actually re-used the same name for our factory instead of changing the name every time, as I did above for the purpose of explanation) we accomplished this without changing any of the code that used PRODUCT-FACTORY (the standardized name). Of course, if there's no state that persists between evaluations, using an object seems overkill... or does it? The other nice thing that an object does for us is to provide a private namespace, which allows us to decompose a complicated function into an interface function that uses a collection of (hidden) helper functions and values shared among those functions without cluttering up the global namespace with all of those implementation details. The QAD above left OBJECT-INVENTORY in the global namespace, whereas general-products: make object! [ inventory: [] manufacture: func [a [niumber] /local obj]] [ append inventory obj: make object! [ constant: a usage: 0 f: func [b [number!]] [ usage: usage + 1 times constant b ] ] get in obj 'f ] report: func [/local count usages] [ count: usages: 0 foreach object inventory [ print [ object with factor object/constant was used object/usage times ] count: count + 1 usages: usages + object/usage ] print [count objects used a total of usages times] ] ] product-factory: get in general-products 'manufacture so now the rest of the world doesn't need to know or worry about the block holding the inventory, and the INVENTORY-USAGE-REPORT doesn't conflict with the warehouse database. ;-) -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Coffee break problem anyone?
maxlen: seqlen ; ... and length ] ] reduce [maxpos maxlen] ] Notice that now there's a single, obvious place for the test for new best run -- right after the inner loop across a run's numbers! The condition on the inner loop has to satisfy the outer loops condition first, and then add its own criteria (which uses ZERO? SEQLEN to mean that we have a new run, and therefore don't care whether the previous value was one less than the current one). To see the value of this structural change, imagine that we now need to return a triplet of numbers; in addition to the position and length of the longest consecutive run, also return the count of how many runs of that length existed. Where would that code go in the Jackson version? Where would it have to appear in the other one? -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Formatting a display line
Hi, Steven, The typing of the parameter has already been pointed out, but let me give you a speed improvement as well. Using SOURCE shows us that APPEND is essentially INSERT TAIL (just what you'd expect), and INSERT has a /DUP refinement that duplicates the insertion, so instead of ... Steven White wrote: ADD-FILLER: func [ Add a specified number of blanks to FORMATTED-LINE SPACE-COUNT integer! ] [ PRINT [NOW WE WILL ADD SPACE-COUNT SPACES] loop SPACE-COUNT [ append FORMATTED-LINE;; PRINT [FORMATTED LINE IS LENGTH? FORMATTED-LINE BYTES: FORMATTED-LINE] ] ] ... just define ... add-filler: func [ add specified number of spaces to formatted-line space-count [integer!] ][ insert/dup tail formatted-line space-count ] -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Bidirectional value mapping.
Hi, Bruno, I know of no way to avoid some duplication. See below. Bruno G. Albuquerque wrote: I have 2 values that would be mapped to each other. What I need to do is to be able to find the first valeu by searching for the ceond and locate the second by searching for the first. I did come up with solutions to that but I am not satisfied with any of the solutions. Is there a standard Rebol-Way ofr doing that? The best option would be a way that would not result in data duplication. The answer somewhat depends on details of your problem; if forward and reverse mappings are distinct (as in translating between host names and IP addresses, or encoding and decoding with a non-symmetric encryption scheme) then the simplest thing to do is keep both maps as separate blocks (or hashes): roman2number: [i 1 v 5 x 10 l 50 c 100] == [i 1 v 5 x 10 l 50 c 100] number2roman: [1 i 5 v 10 x 50 l 100 c] == [1 i 5 v 10 x 50 l 100 c] select roman2number x == 10 select number2roman 10 == x If you know which way you're mapping, you just select the appropriate map. (Of course, it's easy to write a function that would take one of the above and give the other, so you don't have to create both by hand.) NOTE!!! That last sentence is only true if the mapping is an invertable function!!! If, instead, you have a many-to-one (e.g. letters to the words consonant or vowel) of course there's no way to invert. I assume you know that, but want to include that warning for completeness. The other (perhaps slightly more REBOLish) way to do this is to inter- leave the forward and reverse mapping values as follows: roman-numerals: [ i 1 i v 5 v x 10 x l 50 l c 100 c ] == [i 1 i v 5 v x 10 x l 50 l c 100 c] select roman-numerals x == 10 select roman-numerals 10 == x This works nicely for such things as ROT13, which is a self-inverse mapping (and again, you can write a utility function that would take e.g. ROMAN2NUMBER above and give you the interleaved ROMAN-NUMERALS). However THIS DOES NOT WORK IN GENERAL if the domain and range of your mapping overlap. As a simple example, consider the trivial example of rotating among three elements: forward: [a b c a] reverse: [c b a c] Since a maps to b going forward, but b maps to c going forward, then both forward and reverse mappings can't be combined into a single block/hash. To see why this is true, consider what would have to follow b in the combined series! Unless you know you have a self-inverse mapping and you consider speed soo important that you'll sacrifice readability for performance, I recommend using distinct forward/reverse mappings (with a helper to construct the inverted one). It'll be easier to read anyway! -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: check me? deleting files based on a pattern
Hi, Tom, Saving some typing and evaluation... Tom Foster wrote: home: to-file rejoin [~ /] base: to-file rejoin [home attempt-it/] foreach file read base [ if found? (find file editpost) [ delete base/:file ] ] You can just use a literal FILE! value for the base directory foreach file read base: %~/attempt-it/ [...[ and avoid all the REJOIN evaluations. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Storing a logical condition
Hi, Brett, Actually, you remind me of another point which I failed to raise... Brett Handley wrote: ... result encourages one to use a form that has the least effect on the parent/calling expression - whether you evaluate the condition early eg: condition-result: dummy = 1 or you evaluate it late using the function: condition-result: does [dummy = 1] Your parent expression eg. print condition-result Need not change (unless of course dummy does). A nice finding. That also points out another drawback of the any [expr] and all [expr] versions; they do not preserve the type of (the evaluation of) EXPR for FALSE values, but yield NONE instead! This can become an issue in various ways, such as causing erroneous results when comparing with LOGIC! values from other expressions (FALSE does not equal NONE) or causing type errors when handing off to a mezzanine which expects a LOGIC! argument. While there are workarounds based on standard boolean identities: true and all [expr] or false or all [expr] they simply obscure what is being expressed, IMHO. Per the extreme guys, Do the simplest thing that could possible work! -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: reduce/deep
Hi, Robert, Robert M. Münch wrote: Hi, ahhh forgot about this one. Rebol just has to many words to remember ;-) But this doesn't seem to work for nested blocks: Sure it does! d: reduce [a b] == [[a 1 b 2] [a 1 b 2]] e: reduce [a b] == [[a 1 b 2] [a 1 b 2]] same? d e == false Consider a simpler, analogous set of evaluations: a: b: xyz== xyz same? a b == true c: reduce [a b]== [xyz xyz] d: reduce [a b]== [xyz xyz] same? c/1 d/1 == true same? c/2 d/2 == true same? c d == false equal? c d == true or even *more* simpler (pardon the grammar! ;-) p: 12 == 12 q: 12 == 12 same? p/1 q/1== true same? p/2 q/2== true same? p q== false equal? p q == true These all illustrate the difference between SAME? and EQUAL? in that it is entirely possible to have two different series values whose corresponding elements are the same. In my first example above, as in your original post, two different REDUCE expressions over two different blocks will not produce THE SAME block, even if the content of those two blocks are the same. However the blocks are equal. My second example breaks it down even further. Two different appearances in the input of 12 correspond to two different strings, even though the corresponding characters in those strings are equal (and same, being immutable). Likewise, two different appearances of [a b] result in the creation of two different blocks, even though the corresponding words in those blocks are the same. Therefore, when we reduce those distinct but equal blocks, we get distinct but equal resulting blocks. -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Storing a logical condition
Hi, Tim, and all! My buffer overflowed, but maybe this is still worth posting... Tim Johnson wrote: * Brett Handley [EMAIL PROTECTED] [031013 16:42]: Like Ingo's observation, it is significantly faster too - significant if you have a million iterations ;^) timeit [repeat i 100 [do b]] == 0:00:04.387 timeit [repeat i 100 [all b]] == 0:00:02.604 Cool! Who woulda thunk it? That's a good tip. thnx tim Using a block specified as blk: [dummy = 1] and a function defined as fn: func [] blk I compared the runtimes of loop reps [] ;; to deduct loop overhead loop reps blk ;; in-line loop reps [do blk];; do loop reps [first reduce blk] ;; first reduce loop reps [fn];; fn loop reps [any blk] ;; any loop reps [all blk] ;; all After deducting the loop overhead from all other timings (average of ten) I calculated the ratio of each relative to the inline case. I tested with DUMMY equal to 1 and 2 (just in case there was an effect on ANY or ALL), but found no significant difference. Timings were done on an Athlon 2400 running wXP, with REPS set to ten million. I was surprised (and educated) by the result for one version! versionavg time ratio to in-line in-line 1.827 s 100.0% fn 3.067 s 167.9% any 3.826 s 209.4% all 3.869 s 211.7% do 3.998 s 218.8% first reduce 15.771 s 863.1% Yep! The winner is the lowly, plain-vanilla function! At least for this simple case, the fastest way to defer the evaluation of an expression is simply to make that expression the body of a function with no parameters! I guess sometimes we outsmart ourselves! ;-) -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1 -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Multithreading with Rebol
Hi, Robert, A couple of thoughts on the other side... Robert M. Münch wrote: Hi, don't bee fooled by all this multi-threading hype. For example, have a look at www.xitami.com and theire LRWP protocol. This is done using a cooperative multi-tasking. Very cool and fast, and it can be coupled with Rebol quite easy. I don't know what you mean by hype, nor what that has to do with speed. I've never thought of parallelism in terms of the speed of a single task, but as a design/expressiveness issue. Remember: it's possible to express *any* computation in terms of only sequence, alternation, and iteration (e.g. block, IF, and WHILE) but few of us choose to restrict ourselves to only those mechanisms. For that matter, most of us would prefer to write (e.g.): foo: func [b [block! n [integer!] ...] [ ... expressions with B and N ... ... final expression with B and N ] ... blort: foo someblock 23 instead of foo-b: foo-n: foo-result: none foo-exprs: [ ... expressions with B and N ... foo-result: ... final expression with B and N ] ... foo-b: someblock foo-n: 23 do foo-exprs blort: foo-result The gain in expressiveness from having functions renders irrelevent the contention that we could find other ways to get the job done without them. There are some problems whose solution can be most naturally expressed in recursive terms. Likewise, there are some problems which can be expressed most clearly as a collection of distinct processes with well-defined collaboration patterns. Consider the popularity of | as a means of structuring computations via the *nix shell. Of course, anything that can be done with | can also be done in a single-threaded program, but then the programmer has to concern herself/himself with implementation/algorithm details that are simply irrelevant at the level of the original problem (e.g. buffering, distinguishing push-driven and pull-driven variations of the same algorithm, etc.) Finally, there are cases in which one of a set of collaborating activities should be allowed to stall for a time without forcing all others to wait. The fact that we can (sometimes!) deconstruct our code in a scheme to allow this to be managed in a single thread only means that we now have to add the issues of that scheme to the things to consider in doing our design, instead of being able to keep our focus on the top problem. I've recently been involved in several (very hard-core practical) projects where parallelism made significant contribution to the simplicity of the solution, overall performance, or both. Remember: multi threading won't solve performance problems just because it's multi threaded... Agreed, but... Remember: single-threading won't solve design problems just because only one thing is happening at a given instant! ;-) -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Counting lines of code is to software development as counting bricks is to urban development. -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Compose on tag! values
Hi, Andrew, Here's a QAD RYO... Andrew Martin wrote: What do people think about extending 'compose to work within tag! values? For example: paragraph_colour: green compose [ p style=Color: (paragraph_colour); ] which results in: [ p style=Color: green; ] One function definition... compose-tag: func [blk [block!]] [to-tag rejoin compose blk] ...after which... paragraph_color: green == green compose-tag [{p } {style=Color:} (paragraph_color) {}] == p style=Color:green -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Counting lines of code is to software development as counting bricks is to urban development. -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: pleac
Thanks, Andreas! Andreas Bolka wrote: rot13: func [s [string!]] [ foreach char s [ prin any [ select/case anabobcpcdqderefsfgtghuhivijwjkxklylmzm char select/case AZABOBCPCDQDEREFSFGTGHUHIVIJWJKXKLYLMZM char char ] ] prin newline ] sorry the nit-picking, but i guess the first #Z in the second sequence should rather be an #N :) You're absolutely right. I didn't proofread (or test enough)! -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: pleac
Hi, Carl, How about a slightly more REBOL-intensive variation? Carl Read wrote: Going by most of the examples I've checked on the site it seems they'd like characters to be printed one at a time, so here's a modified version of the script I just posted... rebol [] foreach char input [ letter: to-string char if all [letter = a letter = z][ char: char + either letter n [13][-13] ] prin char ] prin ^/ rot13: func [s [string!]] [ foreach char s [ prin any [ select/case anabobcpcdqderefsfgtghuhivijwjkxklylmzm char select/case AZABOBCPCDQDEREFSFGTGHUHIVIJWJKXKLYLMZM char char ] ] prin newline ] -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: pleac/rot13
Hi, Norman, Here's one way, but I don't know about smallness... Rebolinth wrote: A honarable listing on the one that builds the smallest ROT13 using bitsets and parsing ;-) r13: func [s [string!] /local left right neither r13char c] [ left: charset [#a - #m #A - #M] right: charset [#n - #z #N - #Z] neither: complement union left right r13char: [ [ copy c left (c: +13 + to-char c) | copy c right (c: -13 + to-char c) | copy c neither] (prin to-char c) ] parse s [any r13char] ] -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Newbie expression question
Hi, Sunanda, Minor quibble below... [EMAIL PROTECTED] wrote: Kai: if length? tlist/data 1000 Can someone give me a pointer as to what i need to do? Try these: if (length? tlist/data) 1000 or if 1000 = length? tlist/data I think you meant if 1000 length? tlist/data as equality isn't in the other cases. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Newbie expression question
Ooops! I hit the send button before finishing... [EMAIL PROTECTED] wrote: if length? tlist/data 1000 Try these: if (length? tlist/data) 1000 or if 1000 = length? tlist/data (I always go for the (...) solution as I can't be bothered with reversing boolean operations. I've been experimenting lately with restricting myself to using only and = to express ordered comparisons. There were a couple of initial reasons for the experiment: - as the number line (conventionally pictured, anyway!) contains smaller values on the left and larger values on the right, I wanted to test the mnemonic value of writing expressions with smaller/left and larger/right ordering; - it gives compound and range conditions a natural form: ... all [lowerlimit = testvalue testvalue = upperlimit] ... which resembles the normal mathematical notation: lowerlimit = testvalue = upperlimit (the only languages I can recall at the moment that understand that notation would be Python and Icon). - it's an interesting psychological experiment; mathematically the two expressions (e.g.) a b and b a are equivalent, so why is it that so many of us have learned to feel more comfortable with foo 100 than 100 foo in our programs? Is it because our natural language habits make us subconsciously think of the expresson(s) above as being more about FOO as the subject of the sentence, rather than about the relationship between two equally-important values? At any rate, it also has the interesting side effects that many REBOL expressions no longer need parentheses. It's also interesting to see the effect on one's thinking from deliberately breaking almost sub- conscious habits. -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: IDIOMS: setting multiple words
Hi, Elan and all, Elan wrote: Hi Sunanda: set [foo bar baz] copy [] You will find that only foo is set set to a block, whereas bar and baz are initialized to the value none. This is unlike using set [foo bar baz[] 3 ;- (i.e. some non-series value where all words will be initialized to the same value. Actually, all of FOO BAR and BAZ will be set to NONE, as the empty list is the source of *all* values for the three words: set [foo bar baz] copy [] == [] foo == none bar == none baz == none -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Accessing a variable's method
Hi, Arnoux It's simple (simpler than that, actually ;-) Arnoux Vincent wrote: Hi List, I have a list of objects: /l: copy [] obj: make object! [ a: none calc: does [self/a: (self/a + 1)]] append l make obj [a: 1] append l make obj [a: 2]/ I would like to write a function like: /inc-obj: func [arg][ arg/calc ]/ That would allow me to do: /foreach o l [ inc-obj o ] / And output: /probe (first l)/a/ /2 //probe (second l)/a/ /3 /Is it possible ? Yes, and you don't need the overhead of INC-OBJ or the repeated uses of SELF within the method on your objects. See transcript below: proto: make object! [ [count: 0 [bump: func [] [count: count + 1] [] obj-block: [] == [] repeat i 4 [append obj-block make proto [count: i]] == [ make object! [ count: 1 bump: func [][count: count + 1] ] make object! [ count: 2 ... foreach obj obj-block [obj/bump] == 5 foreach obj obj-block [print obj/count] 2 3 4 5 -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Counting lines of code is to software development as counting bricks is to urban development. -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: Tail end recursion
Hi, Maxim, and all Maxim Olivier-Adlhoch wrote: so basically its like using recursion to do a loop? ... but how does tail-end recursion stop? Recursion and looping are just two ways of expressing that something is to be repeated. In both cases one needs a terminating condition (unless the process is to run forever...) The example given earlier was a tad to trivial to make that point, but consider instead the slightly more complete example: forr-count: func [limit [integer!]] [ for i 0 limit 1 [print i] ] As we all know, this is just syntactic sugar for: while-count: func [limit [integer!] /local i] [ i: 0 while [i = limit] [ print i i: i + 1 ] ] Notice that this version clearly states the initial state (I = 1), the condition for continuing the computation (I = LIMIT), and the evaluation to occur for each continued case (PRINT and increment). Those same three ingredients are required to write an equivalent recursive function: rec-count: func [limit [integer!] /local .rec-count] [ do .rec-count: func [ i [integer!] .limit [integer!] ][ if i = .limit [ print i .rec-count i + 1 .limit ] ] 0 limit ] Notice that every evaluation path through the inner function (.REC-COUNT) either terminates the computation or ends with a recursive call on itself, and every call to the inner function is the last thing in an execution path. (There's one of each.) In such cases, some languages/implementations can avoid the state-saving/restoration normally associated with beginning a subordinate evaluation -- in other words, they transform the recursive inner function above into a loop. REBOL does not. Sometimes the clearest/simplest specification for how to solve some problem is based on a divide-and-conquer strategy, where the sub-problems are either trivial to solve or are smaller cases similar to the original problem. In these cases, it is often easier to write a recursive solution. If the state management of the recursive implementation is too costly, one can (attempt to! ;-) formally transform the recursive solution into an iterative one; sometimes that's easy and sometimes not. (*) For more on this subject, please see http://www.rebolforces.com/articles/ria/ and for more on why recursion isn't complicated, see http://www.rebolforces.com/articles/metaphors/ HTH! -jn- (*) For an example of a problem that's easy to solve recursively, but which takes a bit of thought to solve iteratively (or in closed form! ;-), consider the old Fibonacci numbers. The original problem can be framed as follows: Begin a pair of new-born rabbits (one male, one female). When a pair of rabbits reaches age one month, they begin breeding, with a one-month gestation period, and breeding again immediatly after birth. Each breeding produces a pair of rabbits (one mail, one female). How many pairs of rabbits does one have each month (assuming that rabbits are immortal, food is infinitely available, etc...) Classify them as mature (at least one month old, breeding every month) and immature (just born, not mature for one more month). This give us the following population chart (in pairs): Month Mature Immature Total - -- - 1 0 1 1 2 1 0 1 3 1 1 2 4 2 1 3 5 3 2 5 etc... In other words, all pairs (immature or mature) which were alive last month are still alive, and all mature pairs from last month have produced new pairs. But the mature pairs last month are just the total population the month before! Finally, during the first two months we only have the original pair (immature or mature), so we get rfib1: func [n [integer!]] [ either n 3 [1] [(rfib1 n - 1) + (rfib1 n - 2)] ] A little programming algebra produces the equivalent iterative form ifib1: func [n [integer!] /local a b] [ a: 0 b: 1 loop n [ a: (b: b + a) - a ] a ] But it takes a bit more mathematics to produce the equivalent closed form solution cfib1: func [n [integer!] /local r] [ r: square-root 5 ((1 + r / 2) ** n) - ((1 - r / 2) ** n) / r ] So recursion and iteration both have their places! ;-) -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Counting lines of code is to software development as counting bricks is to urban development. -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: IDIOMS: setting multiple words
Hi, Greg, Gregg Irwin wrote: Scenario: You have a number of words that you want initialized to copy [] or some other value. Do you do it like this? foo: copy [] bar: copy [] baz: copy [] Or like this? foreach word [foo bar baz][set word copy []] Or something else. Occasionally I might write foo: copy bar: copy baz: copy [] to emphasize that they're all alike in some way. That also scales well if the intial value is more complex than [] (especially if it must be computed, but that value -- or a copy -- is needed for more than one variable). Otherwise, I'd probably use your first case. Do you use a different approach for more or less words? If I had more words than the above, I'd start looking at whether I needed to redesign so that they all were parts of a larger data structure, rather than individual words. Do you do things differently if you're setting words in a object? When setting up an object, I usually prefer the foo: ... bar: ... baz: ... format to make the members of the object very clearly visible. Do you do something different based on the initial value? Is there anything else you take into consideration when you do this kind of thing? For both of these, see above comments re scaling and number of distinct copies. Thanks for playing! Thanks for asking! ;-) -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Counting lines of code is to software development as counting bricks is to urban development. -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: help with function utilising extended life-time words ..
Hi, Petr, Petr Krenzelok wrote: Thanks all for answers! I was just thinking in a bit different way - I did not want to enclose measured task into special block to prevent myself from forgetting to include ending bracket :-) However, the presence of explicit brackets makes it clear precisely what you mean when inserting or removing a call to the timer. Without that hint, presence/absence of a call could affect the results of other calls in hard-to-track-down ways. So, my initial intention was to have how-long? just marking current time substracted from last function call ... From the various aproaches I saw I like object based the most probably ... do not why though :-) I prefer to use objects to manage persistent state precisely because that is what objects were intended for in the first place. The amount of state can scale up gracefully as one's design evolves (e.g. add one more attribute to the object) without requiring lots of tricky digital plumbing (e.g. the REDUCE... issue at the beginning of this thread). Just MHO, of course! ;-) -jn- -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] Re: help with function utilising extended life-time words ..
Hi, Petr, Here are a couple of simple approaches (which you can complicate as desired for more functionality ;-) -jn- Petr Krenzelok wrote: start: now/time/precise do something ... print now/time/precise - start start: now/time/precise I wanted to write myself short logger function, which will save me from repeating above sequences, as the script becomes a bit messy then. So I wanted to have following interface: how-long? Some task ... Single-task timing doesn't require any tricky state: how-long?: func [msg [string!] to-do [block!] /local timing] [ timing: now/time/precise do to-do timing: to-decimal now/time/precise - timing print [timing msg] ] Which behaves as in the following transcript: (begin transcript) how-long? count to one million [for i 1 100 1 []] 3.195 count to one million how-long? count to one hundred thousand ten times [ [ loop 10 [ [ how-long? count to one hundred thousand [for i 1 10 1[]] [ ] [ ] 0.33 count to one hundred thousand 0.321 count to one hundred thousand 0.31 count to one hundred thousand 0.321 count to one hundred thousand 0.31 count to one hundred thousand 0.321 count to one hundred thousand 0.32 count to one hundred thousand 0.321 count to one hundred thousand 0.31 count to one hundred thousand 0.32 count to one hundred thousand 3.184 count to one hundred thousand ten times (end transcript) If you want accumulation of times across multiple calls, just wrap the total in a block (per the tricky approach you quoted) or do The Right Thing and represent stateful timing accumulators with objects: time-accumulator: make object! [ message: no message? total: 0.0 reset: func [][total: 0.0] time-this: func [to-do [block!] /local timing] [ timing: now/time/precise do to-do timing: to-decimal now/time/precise - timing total: total + timing print [Total: total This: timing message] ] ] which can be used as follows: stopwatch1: make time-accumulator [message: Watch 1] stopwatch1/time-this [for i 1 100 1 []] Total: 3.155 This: 3.155 Watch 1 stopwatch2: make time-accumulator [message: smaller chunks] loop 10 [stopwatch2/time-this [for i 1 10 1 []]] Total: 0.32 This: 0.32 smaller chunks Total: 0.631 This: 0.311 smaller chunks Total: 0.941 This: 0.31 smaller chunks Total: 1.262 This: 0.321 smaller chunks Total: 1.582 This: 0.32 smaller chunks Total: 1.893 This: 0.311 smaller chunks Total: 2.203 This: 0.31 smaller chunks Total: 2.514 This: 0.311 smaller chunks Total: 2.834 This: 0.32 smaller chunks Total: 3.144 This: 0.31 smaller chunks I prefer to represent stateful entities via objects rather than functions. Among other reasons, stateful functions depend on aspects of REBOL (persistence of mutations to literal series values) that are very mysterious to REBOL newbies. There's no point in being obscure, just for the sake of obscurity! ;-) -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 Counting lines of code is to software development as counting bricks is to urban development. -- To unsubscribe from this list, just send an email to [EMAIL PROTECTED] with unsubscribe as the subject.
[REBOL] to/make datatype!
Hi, all, Some conversions to/from STRING! work nicely (and in the obvious, intuitive fashion), join 1 == 1 to-string 1== 1 mold 1 == 1 and type? to-integer 1 == integer! type? to-decimal 1 == decimal! type? to integer! 1 == integer! type? to decimal! 1 == decimal! type? make integer! 1== integer! type? make decimal! 1== decimal! We can convert a DATATYPE! value to a STRING! value in different ways, with slightly different results, int-type: type? 1 == integer! join int-type == integer to-string int-type== integer mold int-type == integer! (note the presence/absence of the trailing bang), but the corresponding transformations *don't* work then other way, with no TO-xxx shortcut: to-datatype int-type-name ** Script Error: to-datatype has no value ** Where: halt-view ** Near: to-datatype int-type-name and no support from TO or MAKE either: to datatype! int-type-name ** Script Error: Cannot use to on datatype! value ** Where: halt-view ** Near: to datatype! int-type-name make datatype! int-type-name ** Script Error: Cannot use make on datatype! value ** Where: halt-view ** Near: make datatype! int-type-name So far the most simplest way I've come up with to create a DATATYPE! value from a STRING! value is to-datatype: func [s [string!]] [ first reduce load rejoin [ [ s either #! = last s []] [!]] ] ] type? to-datatype string == datatype! make to-datatype integer 12== 12 There's *got* to be a better way! Any suggestions? -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: to/make datatype!
Thanks, Scott! G. Scott Jones wrote: From: Joel Neely ... to-datatype: func [s [string!]] [ first reduce load rejoin [ [ s either #! = last s []] [!]] ] ] type? to-datatype string == datatype! make to-datatype integer 12== 12 There's *got* to be a better way! Any suggestions? ... to-datatype: func [s [string!]] [ do join s either #! = last s [][!] ] ;where type? to-datatype string ;== datatype! to to-datatype string 12 ;== 12 That's certainly an improvement, IMHO! Anybody know why it has to be so hard? -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: XML.com Embedded Markup Considered Harmful [Oct. 02,1997]
Hi, Dick, Two thoughts, one a direct reply and one more deferred... [EMAIL PROTECTED] wrote: I originally chirped in on the XML comments ... Seems that there should be an XML_Display... XML_Display (25 87 20) (date) (2 2 ReshapeOf 4 Random 1000) (UCase Hello World) VECTOR LENGTH=4 VECTOR LENGTH=3 SCALAR DATATYPE=NUMERIC25/SCALAR SCALAR DATATYPE=NUMERIC87/SCALAR SCALAR DATATYPE=NUMERIC20/SCALAR /VECTOR STRINGSun Oct 13 07:00:24 2002/STRING ARRAY RANK=2 SHAPE=2,2 SCALAR DATATYPE=NUMERIC12/SCALAR SCALAR DATATYPE=NUMERIC987/SCALAR SCALAR DATATYPE=NUMERIC82/SCALAR SCALAR DATATYPE=NUMERIC132/SCALAR /ARRAY STRINGHELLO WORLD/STRING /VECTOR 1) The REBOL-to-XML issue seems simple; consider this fragment ... 8-- r2x: make object! [ buff: {} padl: 0 v:none emit: func [sb [string! block!]] [ insert insert insert/dup tail buff {} padl either block? sb [rejoin sb] [sb] newline ] render-item: func [v [any-type!] /local t] [ emit [{} t: type? v {} v {/} t {}] ] v: none rule: [ any [ into [ ( emit {block} padl: padl + 1 ) rule ( padl: padl - 1 emit {/block} ) ] | set v any-type! (render-item v) ] ] render: func [b [block!]] [ buff: copy {} padl: 0 parse/all reduce [b] rule buff ] ] 8-- ... which behaves as follows: reffy: [ [[25 87 20] [13-Oct-2002 [[ [1 3 5] [2 4 6] ] [That's all, folks! [] == [ [25 87 20] 13-Oct-2002 [[1 3 5] [2 4 6]] That's all, folks! ] print r2x/render reffy block block integer25/integer integer87/integer integer20/integer /block date13-Oct-2002/date block block integer1/integer integer3/integer integer5/integer /block block integer2/integer integer4/integer integer6/integer /block /block stringThat's all, folks!/string /block Adding length attribute/value data to the block tag is left as an exercise to the reader. (Mostly because it wasn't immediately obvious how to do so, as SET before INTO doesn't seem to do what I expected, and I didn't have time for another research project. Perhaps someone else on the list has a clue... ;-) 2) Back to the discussion of arbitrary choices in representation, it's not clear to me that the concept of inherent structure and representation has any meaning apart from convention. Take the case of a two-dimensional matrix. FORTRAN and C store such structures in orthogonal layouts (FORTRAN varies the left subscript most rapidly, and C varies the right subscript most rapidly), while both REBOL and Perl would use nested one-dimensional structures (REBOL blocks or Perl arrays). Even my use of language betrays me if I talk about rows and columns of the matrix, which terms imply some sort of typographic layout. As another example consider a REBOL block containing student data: e.g., an ID, a name, and a phone number for each student. One person might immediately think of something like this: [ [123 Alex Ant #555-] [234 Betty Bee #555-] [345 Cliff Cricket #555-] ... ] while another would think of this: [ [123 234 345 ...] [Alex Ant Betty Bee Cliff Cricket ...] [{555-} {555-} {555-} ...] ] and yet another would envision: [ 123 [Alex Ant [555 ]] 234 [Betty Bee [555 ]] 345 [Cliff Cricket [555 ]] ... ] Clearly each of these serves *some* purposes well and others poorly; the choice ultimately is entangled with one's intended processing (or one's habits and assumptions). I'm not trying to beat a dead horse here, but rather just musing quasi-philosophically about the process by which we programmers make our design decisions, and how many of those decisions are so deeply unconscious that we aren't even aware that there are alternatives. EWD told a wonderful story about giving an individualized test where the student is presented with a problem and is expected to think aloud while designing a solution on the board in the professor's presence. The problem he described involves achieving a specified condition in a single pass across a one-dimensional array, where the obvious solution would sweep back-and-forth multiple times. He had been accustomed (over many uses of
[REBOL] Re: XML.com Embedded Markup Considered Harmful [Oct. 02,1997]
Hi, Dick, [EMAIL PROTECTED] wrote: You must forgive me Joel, None needed! I had typed my comments very late at night, and wanted to be sure I hadn't rambled on so much that I'd obscured my point. -jn- -- To me, boxing is like ballet, except that there's no music, no choreography, and the dancers hit each other. -- Jack Handy joel~dot~neely~FIX~PUNCTUATION~at~fedex~dot~com -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: idioms to reduce logic clutter ?
Jason Cunliffe wrote: Time to factor out and simplify the mess... Here are some simplification strategies: - use default values, which can trigger default behaviors - use FUNC/RETURN to manage premature exits - use long strings - avoid large in-line literals - avoid use-once variables - eliminate dead code OBSCURENOTE The phrase foo: either error? [foo: expression] [defaultvalue] [foo] ensures that FOO will either be the result of a successful evaluation or will be the specified default value, as in foo: either error? try [foo: 1 / a] [0] [foo] which will result in FOO containing zero if there's a problem, such as an undefined word a ** Script Error: a has no value ** Near: a foo: either error? try [foo: 1 / a] [0] [foo] == 0 or an invalid divisor a: 0 == 0 foo: either error? try [foo: 1 / a] [0] [foo] == 0 but will give the desired result if the TRYed expression succeeds a: .5 == 0.5 foo: either error? try [foo: 1 / a] [0] [foo] == 2 /OBSCURENOTE Now let's apply them in one of many possible ways. (In-line comments followed by sketch of simplified version.) ; ; TEST FOR PASSWORD ; upass: copy loginstatus: false either error? try [ ;condition upass: cgi-obj/userpass ][ ;error if = upass [ print rejoin [ {bBad login!/b} {no user password provided } {a href=upload.html}{try again}{/a} {br} ] ] quit It appears that QUIT really means I've finished assembling my reply page. The following IF expression appears to be dead code, as it follows a QUIT inside the error branch. if upass [ print rejoin [ {funny password provided. Please } {a href=upload.html}{try again}{/a} {br} ] ] Could error on fetching password be treated identically with missing password? ][ ; ok user has submitted a name and password ; check to see if they match upass: cgi-obj/userpass either = upass logindict/:uname [loginstatus: true] [loginstatus: false] The above EITHER expression is just a round-about way of saying loginstatus: upass = logindict/:uname if not loginstatus [ ... but if this is the only use, why use up a name? ;trouble in paradise - help them out.. print rejoin [ {brUsername and password do not match. brPlease } {a href=upload.html}{try again}{/a} {form method=POST action=echo-login.r enctype=multipart/form-data iForgot your login or need to register ? br Please enter your email address here: /i input type=text name=email_address value=/ input type=submit value=send login by email/ /form} ] quit ] ] One approach for using the above hints would look like this: 8 blah_blah_cgi: make object! [ ;; all chunks of message text go here: ;; (embedded whitespace disappears unless wrapped in pre/pre) ;; parameterize messages with common structure msg_retry_missing: func [what [string!]] [ rejoin [ {bBad login!/b no } what { provided.br / a href=upload.htmltry again/a.br /} ] ] msg_bad_password: {brUsername and password do not match.br / Please a href=upload.htmltry again/abr / form method=POST action=echo-login.r enctype=multipart/form-data iForgot your login or need to register?br / Please enter your email address here: /ibr / input type=text name=email_address value=/br / input type=submit value=send login by email/ /form} msg_blah_blah: {...} ;; process form content, return string form_results: func [ a_user [string!] ;; form userID or default (empty string) a_pass [string!] ;; form passwd or default (empty string) ... ;; other form data /local vpass ;; valid password for a_user ][ if empty? a_pass [return msg_retry_mising user password] if empty? a_name [return msg_retry_mising user name] if any [ empty? vpass: either error? [vpass: logindict/:a_name] [none] [vpass] vpass upass ][ return msg_bad_password ] ;; now process validated form content, and return appropriate results ] run: func [] [ ... print form_results either error? [upass: cgi-obj/userpass] [] [upass] either error? [upass: cgi-obj/username] [] [upass] ... ... ] ]
[REBOL] Re: XML.com Embedded Markup Considered Harmful [Oct. 02,1997]
Hi, Dick, I guess you're using a later version of REBOL than I have... ? average No information on average (word has no value) ;-) My point was that we use FOR or FOREACH to process array/block structure precisely because both directly express iteration; for a chosen conceptual structure of a problem, I think that it *is* a good thing for the data and the algorithm to reflect compatible structures, all else equal. -jn- [EMAIL PROTECTED] wrote: total: 0.0 foreach grade gradeblock [total: total + grade] average: total / length? gradelist than the (commonly used when the structured programming issue was first unleashed on the world) more primitive 100 let t = 0 110 let i = 1 120 if g(i) = -1 then 160 130 let t = t + g(i) l40 let i = i + 1 150 goto 120 160 let a = t / i -- I prefer: Average expressionwhichyieldsanarrayofdata -- Those who make peaceful revolution impossible will make violent revolution inevitable. -- John F. Kennedy joel dot neely at fedex FIX PUNCTUATION dot com -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: XML.com Embedded Markup Considered Harmful [Oct. 02,1997]
Hi, Dick, Kemp, and all, I'll be the first to agree that Ted Nelson is a very bright guy, and a real visionary, but sometimes visionaries overstate their case to make a point, or miss something that doesn't quite match their vision. [EMAIL PROTECTED] wrote: I vote for Kemp's thoughts. HTML and XML are merely contrived formats (wrappers). But, as one writer put it, When I talk to you, I gotta use words! If I'm gonna send data from point A to point B, I gotta use *some* format... WIDR, I don't think HTML and XML belong in the same sentence. HTML is a conceptual hash of: - a particular viewpoint of a common logical structure for text documents, - a heavy overlay of other viewpoints of how to mish non-text content into the overall mash, and - an amalgam of presentation-oriented hints which assume that the resulting stew will be viewed by a human being on an arbitrarily long piece of virtual scrolling paper. OTOH, XML is a meta-language and culture that include: - notation(s) for allowing one to design specific formats/representations for particular classes of data, and - a preference for representing *a* hierarchical semantic structure, rather than presentation formatting. Unfortunately, there's so much hype about XML replacing (or being translated into) HTML via a bunch of other Xacronyms that the distinctions above are candidates for endangered species of the month. ;-) IMHO, the interesting issue with XML is as a counterbalance to ASN-1 (Unicode text instead of bit-level binary), so that: - XML is human-readable (and writable, if one is e.g. creating test data or small chunks of content), - XML is *F*A*R* easier to encode/decode, - ASN-1 takes way less bandwidth. I too have a major problem with HTML and XML heirarchical structure - it's not the way most things work. I never thought of as XML representing the way things work, but just as a flexible notation for sending a description of a thing from point A to point B (in space *or* time). It's an encoding. What we are doing is cramming arbitarily-structured information into a predefined heirarchy. What we should be doing is assigning appropriate structures to the information as required by (a) the intrinsic structure of the content, (b) the relationship between the information and the application, and ((c) the structure of the application itself. All 3 are different and should be separable, and NONE of them are always heirarchical. We could get into *major* philosophical wars over that paragraph! ;-) I suggest that the activity of programming involves at least the following four structures: 1) a conceptual structure of the class of problems under consideration, 2) a representational (e.g. data) structure for a specific instance of the problem class, 3) a textual structure (source code) for a solution to the problem, and 4) a dynamic structure of events that occur as a computer performs the solution of an instance of the problem class. AFAIAC, all of structured programming boils down to an approach that pursues harmony among those four structures. As a trivial example, figuring the average of a collection of grades, can be viewed as: 1) thinking of the collection as an iteration of (occurrences of) the concept of grade [the conceptual structure]; 2) choosing to represent the collection as: 2a) a file (iteration of lines with one grade each), or 2b) an array (positional iteration of grade data), or ... some other iterative structure [the representational structure]; 3) having a notation to indicate clearly and succinctly that each individual grade should be added into the total [the textual structure], and 4) expecting the computer to repeat the operation of add this one also for as many instances as appropriate [the dynamic structure]. As a result, I'd rather be able to write something like total: 0.0 foreach grade gradeblock [total: total + grade] average: total / length? gradelist than the (commonly used when the structured programming issue was first unleashed on the world) more primitive 100 let t = 0 110 let i = 1 120 if g(i) = -1 then 160 130 let t = t + g(i) l40 let i = i + 1 150 goto 120 160 let a = t / i because the text doesn't contain any single/simple/unambiguous thing that indicates repetition/iteration. Harmony among structures is A Good Thing IMHO. That said, I was careful above to keep saying a ... structure rather than the ... structure because most non-trivial problems can be thought about in more than one way, and it's only to be expected that two people who think about a problem in different ways will develop different structures for their representations, program text, and execution events. average (L) = avg (L, 0, 0). avg ([], t, n) = t / n. avg ([g | r], t, n) = avg (r, t + g, n + 1) Anytime we communicate an instance of a concept from
[REBOL] Off-the-wall request
snippets that I feel should be included in the remarks. FOR EXTRA FUN: If you wish to submit additional solutions in other languages (than REBOL/Core, that is) I'd be happy to have them. I can't promise to have access to any other language implementations, but this is about looking at source code anyway, so that doesn't really matter. Thanks in advance to anyone willing to participate! -jn- -- -- Joel NeelyjoelDOTneelyATfedexDOTcom 901-263-4446 -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: if and parens
Hi, Laurent, Infix (operators) has higher precedence than prefix (function evaluation), so the expression if get in info? to-file elt 'type = 'file [print elt] is actually treated by REBOL in the same order as if parenthesized as if get (in (info? (to-file elt)) ('type = 'file)) [print elt] that is, the IN is applied to the INFO? object, but the second argument is the LOGICAL! value FALSE, which, as the error message stated, is not a WORD! value. Since you just want to exclude subdirectories from the list of contents of the current directory, you could write foreach elt read %. [if not dir? elt [print elt]] instead. -jn- Laurent Giroud wrote: Hi everyone again, I have a little problem that I encounter quite frequently with 'if ... this simply prints the list of files in the current folder and works quite fine : foreach elt read %. [if (get in info? to-file elt 'type) = 'file [print elt]] ... -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ] -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: radical pov ... Re: Re: rebol/base
Hi, Petr, Petr Krenzelok wrote: Yes, it is - but enough is enough imo. Just ask someone from external world, what do they know about Rebol? If they even recognise it, they are already confused by all the following: Rebol/Core [snip snip snip snip ...] Rebol/Encap not to mention Rebol/World, Rebol/Media, Rebol/Author, Rebol/Apache, etc., which appeared here or there even in some of announcements, articles, etc. ... ... My suggestion is - change Rebol architecture for good, do it clever way, allow options and reduce product line - remove /Pro and /Command versions - add real components... Sorry for bringing in different pov, maybe a radical one, but that's just me (and those agreeing with me, staying silent ;-) This is me agreeing and being silent about it. ;-) Or, as John Cage put it, I have nothing to say and I am saying it. There's a bit of irony here, in that REBOL claims (and delivers, for the most part) to simplify things that are complicated and confusing in (some) other languages. Yet many of the things that are necessary for scaling and for marketing have ended up appearing quite confusing. Simplifying the claims/versions/deliverables and exposing some simple, common mechanisms for extensions/modules would be A Good Thing IMHO. -jn- -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: Introducing REBOL/Base - FAQ
IIRC Photon is the name of the GUI environment for QNX. -jn- Anton wrote: REBOL/Photon Anton. On Sat, 28 Sep 2002, Carl at REBOL wrote: Q: Does /Base include graphics functions? A: No. But, there will be a similar version of REBOL/View (as of yet unnamed, got any ideas?). REBOL/Squint -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes. -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ] -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: cyclic values
Hi, Pat, Ingeneous!!! (...of course, with me, there's always a but... ;-) pat665 wrote: I want to get values in order from a block, the first value coming again after the last, and this forever. Is there a better way than the one I am using now ? colors: [red green blue] ; I want color to be red, then green, then blue, then red ;again forever ; the first value is duplicated color: first colors append colors color ; then forever color: select colors color That's a nice compact way to accomplish your stated result, but under two constraints: 1) the number of values in the block is very small, and 2) the values are all distinct. SMALL NUMBER OF VALUES -- Given REBOL 1-origin indexing, the fastest/simplest way I've found for cycling an integer counter through the range of values 1..N is cnt: 0 ;; initialization cnt: cnt // N + 1 which means we could get your forever case above by using color: pick colors cnt: cnt // + 1 The alternative to using the modulus operator is explicit logic, as in color: pick colors counter: either counter length? colors [counter + 1] [1] but that is very sub-optimal... In any case, the time complexity of modifying the integer index is O(1) -- constant -- while the time complexity of SELECT on an ordinary block is O(N) -- linear on the size of the block. A little quick benchmarking shows that this adds up very quickly. On my old slow benchmarking box (200 MHz Pentium, w95) the timings are (in microseconds) SELECTmodulusEITHER... 3 elements 13.94 14.28 18.73 10 elements 16.76 14.72 19.33 (As you can see from the second column, there's still some statistical variability...) The above times were taken using function evaluations, so after removing that overhead, we get the following ratios: SELECT EITHER... vs vs modulus modulus 3 elements0.971.41 10 elements1.181.41 With only three elements, the SELECT approach saves 3% over the modulus approach, but the EITHER strategy costs 41% extra. But with ten elements, SELECT is now 18% slower than modulus, while EITHER is still 41% slower. CONCLUSION: The SELECT strategy doesn't scale well. DISTINCT VALUES --- Suppose you wanted to simulate a monitor which was cycling between the primary colors (e.g. using your original COLORS data), but went off in between each color (e.g. interspersed black displays). If we change our block to contain: colors: [red black green black blue black] color: first colors and then try color: select colors color We'll find that we're stuck in a green/black cycle, since the first occurrence of black is always the one that's found by SELECT. CONCLUSION: The SELECT strategy doesn't handle cases with values that occur more than once in the block. HOWEVER... With all of the above said, for small blocks with distinct values, your approach is quite elegant. Thanks for posting it! -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ] -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: Delete an Instance of an Object
Hi, Philippe, Can you supply a little more detail? Philippe Oehler wrote: How Can I delete an instance of an object ? In the simple case of something like myword: make object! [...] you can simply evaluate myword: none or any other expression that destroys the reference to the object. However AFAIK the object isn't really eligible for garbage collection until all references have gone away. If you other references, then it's not yet garbage. For example, foo: make object! [...] gorp: make block! 10 loop 10 [ insert tail gorp make foo [...] ] myword: first gorp creates a situation in which evaluating either (one) of myword: none or gorp: none still leaves another reference to the first object created from FOO. Does that address your question, or am I missing something? -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ] -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: cyclic values
Hi, Carl Carl Read wrote: ... Indeed. But it suggests a way I haven't seen posted... colors: [red green blue] == [red green blue] forever [print color: colors/1 remove append colors color] red green blue red green blue red green blue red green blue red green blue red (escape) Has the advantage of no extra words being needed. The disadvantages being the contents of the colors block is cycling, (might or might not matter), and it may be slower... It should have a consistant speed though. Comments Joel? Don't try this at home kids! ;-) Cycling the values within the block does matter; there's much more memory management overhead. Using the same benchmarks as in the earlier comparison, the block-cycling version takes 4 to 5 times as long as the modulus approach for 3-10 elements. In addition the overhead grows with the length of the block being cycled: bruteforce: func [n [integer!] c [integer!] /local t b v] [ b: make block! n repeat i n [insert tail b i] t: now/time/precise loop c [ remove append b v: b/1 ] t: to-decimal now/time/precise - t ] behaves as: for i 10 200 10 [print [i bruteforce i 50]] 10 24.99 20 22.91 30 29.49 40 25.27 50 23.45 60 27.19 70 25.76 80 29.22 90 25.98 100 29.6 110 26.75 120 30.05 130 27.24 140 28.89 150 29.83 160 30.71 170 30.97 180 31.2 190 33.18 200 32.9 The raggedness likely indicates intermittent gc operations; the trend is definitely upward as the block length grows. -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ] -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: Byte on Mac OS X (and Rebol too)
Hi, Gabriele and all, I posted some links re this topic on Thursday, with subject [REBOL] Re: Cross 'X' Platform? I agree it's encouraging that he mentioned REBOL in the same list with other important tools. Gabriele Santilli wrote: Hi Paolo, On Saturday, September 28, 2002, 6:34:59 AM, you wrote: PR I just found this one on byte.com: PR http://www.byte.com/documents/s=7620/byt1032475416823/0923_bar.html [OT] I wonder if this stimulates the Linux people to create a better desktop, and better multimedia support. The only thing I didn't like was that BSD kernel running on top of a Mach microkernel --- I'm not sure I would want an OS that needs TWO kernels to run. (Also, that not on microkernels not being fast enough shows that that guy has never seen AmigaOS or QNX...) I'm a bit puzzled by his choice of phrasing re kernel layers, but don't see kernel over microkernel as any more of an issue than layers in other contexts (e.g., protocol stacks). The use of a microkernel as a single point of control for resource sharing and message passing in support of higher layers of system management is well established AFAICT in the RTOS arena, where speed is of the essence (pSOS in addition to your citation of QNX). Just for the sake of completeness, we could add the Next OS (of which OS X appears to be a descendent). However, the point remains that getting Unix on the desktop is A Good Thing, and the choice of Aqua-vs-terminal as the primary point of contact is a tomayto/tomahto issue AFAIAC. IMHO, the combination of VisiCalc and the Apple ][ probably had more to do with early penetration of the professional (e.g. accountants) and corporate markets by personal computing than anything else. Wouldn't it be great if the combination of Mac OS X (nee Unix) and REBOL could play a corresponding role in helping the larger market really get it about distributed computing as well? And even if it does so by motivating the Linux community to pay more attention to interfaces for the non-technical user, that's OK too... Take a look at http://slashdot.org/articles/02/09/27/148235.shtml?tid=120 for another Unix-on-desktop alternative: a $199 box sold by WalMart which runs Lindows (Debian deriviative with glue to run uSoft apps) now supported by AOL. Any foot in the door will do... ;-) -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ] -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.