AltME groups: search
Help · search scripts · search articles · search mailing listresults summary
world | hits |
r4wp | 5907 |
r3wp | 58701 |
total: | 64608 |
results window for this page: [start: 26801 end: 26900]
world-name: r3wp
Group: !REBOL3-OLD1 ... [web-public] | ||
Anton: 2-Sep-2006 | Brian, delimit function: - For long-term readability, I would avoid reusing 'copy as a variable. I suggest 'result, even if it means using another word. - I understand with the /copy refinement you are able to get more speed in creating the result block, but I think I would prefer just letting the user copy the data before passing to delimit. This would give a simpler implementation, easier to read again. I don't wish to devalue your effort in getting this version - I did a similar thing optimizing conjoin - made it harder to read. | |
BrianH: 5-Sep-2006 | I was just using the same refinement /copy that bind uses, but I agree that its reuse as a local variable isn't very readable. I should use /local like my conjoin does. Speaking of conjoin, what do you think of the one above? The only speedup I can see to do is to replace the insert reduce with four inserts, but otherwise it seems useful. | |
Anton: 5-Sep-2006 | A function which joins values into a string might be named CONFORM. | |
Anton: 5-Sep-2006 | Brian, I've read carefully through your conjoin (but haven't tested yet), and I like it, except for *one* thing - I would reverse the order of the data and delimiter arguments. (Actually, I'm searching now for a better word than "delimit". It doesn't quite seem right.) | |
Anton: 6-Sep-2006 | Brian, your last version of CONJOIN, a minor problem: ** Script Error: pick expected index argument of type: number logic pair ** Where: conjoin ** Near: pick [ [local: insert local reduce [delimiter {"} first data {"}]] [local: insert insert local delimiter first ... | |
Anton: 6-Sep-2006 | Brian, if you are going to use a get-word for safety with the first value, ie. [form :local] , then it's probably consistent to be safe with the rest of the data too ? eg. instead of insert local first data use: insert local pick data 1 | |
Anton: 6-Sep-2006 | ; Brian H's version corrected by Anton: ; - LOCAL starts at its tail ; - PICK converted to EITHER (PICK doesn't work with NONE) ; - /QUOTED applied to first value conjoin: func [ "Join the values in a block together with a delimiting PAD value." data [any-block!] "The series to join" pad "The value to put into the series" /only "Inserts a series PAD as a series." /quoted "Puts string values in quotes." /local ; <- used to track tail of the result as we build it ] [ if empty? data [return make data 0] local: tail either series? local: first data [copy local] [form :local] if all [quoted any-string? local][local: insert tail insert head local {"} {"}] ; quote the first value ; <- (local should be at its tail at this point) while [not empty? data: next data] either any-string? local [ either quoted [ [local: insert insert insert insert local pad {"} first data {"}] ][ [local: insert insert local pad first data] ] ] [ either only [ [local: insert insert/only local pad first data] ][ [local: insert insert local pad first data] ] ] head local ] ; test conjoin [] "" conjoin [] "," conjoin [1 2 3] '| conjoin [[1] 2 3] '| conjoin ["one" 2 3] ", " conjoin [["one"] 2 3] '| conjoin [1 2 [3]] [pad] conjoin [[1] 2 [3]] [pad] conjoin/only [[1] 2 [3]] [pad] conjoin/only [[1] 2 [3]] 'pad conjoin/quoted [1 2 3] '| conjoin/quoted [[1] 2 3] '| conjoin ["one" 2 3] ", " conjoin [1 2 [3]] [pad] conjoin/only [1 2 [3]] [pad] conjoin/only [1 2 [3]] 'pad | |
Anton: 6-Sep-2006 | ; Anton's enhanced version: ; - /quote is applied to first value, if a string ; - reorders PAD and DATA arguments so PAD is first (being likely always short) ; - distinguishes /only and /pad-only ; - renames /quoted -> /quote conjoin: func [ "Join the values in a block together with a delimiting PAD value." pad "The value to put into the series" data [any-block!] "The series to join" /only "Inserts a series value in DATA as a series." /pad-only "Inserts a series PAD as a series." ; <-- this might not be used much in practice (easy to add extra brackets around PAD) /quote "Puts string values in quotes." /local ; <- used to track tail of the result as we build it ] [ if empty? data [return make data 0] local: tail either series? local: first data [copy local] [form :local] if all [quote any-string? local][local: insert tail insert head local {"} {"}] ; quote the first value ; <- (local should be at its tail at this point) while [not empty? data: next data] either any-string? local [ either quote [ [local: insert insert insert insert local pad {"} first data {"}] ][ [local: insert insert local pad first data] ] ] [ either only [ either pad-only [ [local: insert/only insert/only local pad first data] ][ [local: insert/only insert local pad first data] ] ][ either pad-only [ [local: insert insert/only local pad first data] ][ [local: insert insert local pad first data] ] ] ] head local ] ; test conjoin "" [] conjoin "," [] conjoin '| [1 2 [3]] conjoin '| [[1] 2 [3]] conjoin ", " [{one} 2 [3]] conjoin '| [["one"] 2 [3]] conjoin/only '| [["one"] 2 [3]] conjoin/only [pad] [1 2 [3]] ; ONLY and PAD-ONLY make no difference in string mode conjoin/only [pad] [[1] 2 [3]] conjoin/pad-only [pad] [1 2 [3]] ; ONLY and PAD-ONLY make no difference in string mode conjoin/pad-only [pad] [[1] 2 [3]] conjoin/only/pad-only [pad] [1 2 [3]] ; ONLY and PAD-ONLY make no difference in string mode conjoin/only/pad-only [pad] [[1] 2 [3]] conjoin/quote "" [] conjoin/quote "," [] conjoin/quote '| [1 2 [3]] conjoin/quote '| [[1] 2 [3]] ; QUOTE doesn't work in block mode conjoin/quote ", " [{one} 2 [3]] conjoin/quote '| [["one"] 2 [3]] conjoin/quote/only '| [["one"] 2 [3]] conjoin/quote/only [pad] [1 2 [3]] ; ONLY and PAD-ONLY make no difference in string mode conjoin/quote/only [pad] [[1] 2 [3]] conjoin/quote/pad-only [pad] [1 2 [3]] ; ONLY and PAD-ONLY make no difference in string mode conjoin/quote/pad-only [pad] [[1] 2 [3]] conjoin/quote/only/pad-only [pad] [1 2 [3]] ; ONLY and PAD-ONLY make no difference in string mode conjoin/quote/only/pad-only [pad] [[1] 2 [3]] | |
Anton: 7-Sep-2006 | Years ago, I successfully argued to Carl that SWITCH's VALUE argument should go before the CASES argument. My reasoning today is the same - it is easier to parse visually when the smaller or less frequently changing parts of an expression go together. As you can see above, all the conjoins with the same PAD argument are easy to see, and the more likely to vary DATA blocks begin sometimes at the same horizontal position (thus, easier to compare). Just scroll up and compare with the tests for your version; look at each line and try to see what the differences between them are. The reasoning that a standard argument order is a good memory guide isn't strong enough for me; there is always HELP, and I think the particularities of each function are more important when determining the order of arguments. | |
Volker: 7-Sep-2006 | BTW i would rething the name for 'decimal! . To me its base-10. float or such are better for floats IMHO. If that does not break to much, but should be a global replace. | |
Volker: 7-Sep-2006 | Re argument-oder: To me big inline block comes last, vars first. Else the standard, the important thing first. With conjoin i am unsure, it looks to me as if it rarely has inline-data. If i pad things together, i usually have a list, conjoin list-of-things "," Its not like 'reduce or 'rejoin, where i mix inline-data with variables, which can span some codelines. If i am wrongand its used like cojoin "," ["I" "who writes this" "has more to think about it"] i am with Anton, small thing first. | |
Anton: 7-Sep-2006 | Yes, overflow either results in an overflow error or a conversion. | |
Ladislav: 7-Sep-2006 | I remember that once there was an issue with a value that MOLD was unable to process. Sunanda gave an example of a MONEY! value of this kind, but I guess, that there was something else, what was it? - a past-tail block/string? | |
Volker: 7-Sep-2006 | Anton, i think that conjion will be used often, but will the argument be an inline-block, or a block in a variable? 'rejoin is used as an template, rejoin["Its" now/time "o'clock"] In that case the block should be last. 'append is used with block in a var, 'append this-block something With conjoin i expect it less like a template and more like 'append. | |
Anton: 7-Sep-2006 | I try to avoid using extra variables. They can be a real pain when it comes to optimization and make things look messier. Of course, when using a variable the argument order becomes less important. It's only important when no variables are used and specified directly. | |
BrianH: 7-Sep-2006 | Looking at your conjoin with the /only and /pad-only refinements, it seems that with the /only you are trying to recreate the delimit function, but not as usefully. I thought of using pad as a variable name, but "delimiter" was more appropriate since padding functions usually pad outside the data, not within it. Let me try to add you fixes to my version and see what I get. | |
BrianH: 7-Sep-2006 | delimit: func [ "Put a value between the values in a series." data [series!] "The series to delimit" delimiter "The value to put into the series" /only "Inserts a series delimiter as a series." /copy "Change a copy of the series instead." /local ] [ while either copy [ if empty? data [return make data 0] local: make data 2 * length? data [ local: insert/only local first data not empty? data: next data ] ] [ local: data [not empty? local: next local] ] pick [ [local: insert local delimiter] [local: insert/only local delimiter] ] none? only head local ] conjoin: func [ "Join the values in a block together with a delimiter." data [any-block!] "The series to join" delimiter "The value to put into the series" /only "Inserts a series delimiter as a series." /quoted "Puts string values in quotes." /local ] [ if empty? data [return make data 0] local: tail either series? local: first data [copy local] [form :local] while [not empty? data: next data] either any-string? local [ either quoted [ local: insert tail insert head local {"} {"} [local: insert insert insert insert local delimiter {"} first data {"}] ] [[local: insert insert local delimiter first data]] ] [pick [ [local: insert insert local delimiter first data] [local: insert insert/only local delimiter first data] ] none? only] head local ] | |
BrianH: 7-Sep-2006 | The pick pattern is also good for nested options, like this pick pick [[no-a-no-b no-a-yes-b] [yes-a-no-b yes-a-yes-b]] none? a none? b | |
BrianH: 7-Sep-2006 | If you want to try something really fun, pass a no-argument function value as the delimiter argument. You can use this for all sorts of tricks, though if you are doing that the references to delimiter in the conjoin function should be put in parentheses for safety. Like this: | |
BrianH: 7-Sep-2006 | conjoin: func [ "Join the values in a block together with a delimiter." data [any-block!] "The series to join" delimiter "The value to put into the series" /only "Inserts a series delimiter as a series." /quoted "Puts string values in quotes." /local ] [ if empty? data [return make data 0] local: tail either series? local: first data [copy local] [form :local] while [not empty? data: next data] either any-string? local [ either quoted [ local: insert tail insert head local {"} {"} [local: insert insert insert insert local (delimiter) {"} first data {"}] ] [[local: insert insert local (delimiter) first data]] ] [pick [ [local: insert insert local (delimiter) first data] [local: insert insert/only local (delimiter) first data] ] none? only] head local ] | |
Volker: 7-Sep-2006 | Anton, "I try to avoid using extra variables". In my scenario its not an extra variable. I have a block of data from elsewhere, so it is in a variable. I want that nicely formed, with delemiters. If i want the data inline, i need no conjoin, i can join it by putting all in one string. | |
Volker: 7-Sep-2006 | I have problems to find a case where using it for inline-blocks makes much sense. Maybe i have a blackout here, can you give a non-artificial case? | |
Anton: 8-Sep-2006 | >> time-it: func [iterations code /local t0 t1][t0: now/precise loop iterations code t1: now/precise print difference t1 t0] >> time-it 4000000 [pick [[a][b]] none? true] 0:00:04.306 >> time-it 4000000 [either true [[a]][[b]]] 0:00:03.555 >> time-it 4000000 [pick [[a][b]] none? none] 0:00:04.266 >> time-it 4000000 [either none [[a]][[b]]] 0:00:03.525 | |
Anton: 8-Sep-2006 | ... which surprised me a little bit. I think maybe the reason pick is favoured in general use is because there's less typing. | |
Anton: 8-Sep-2006 | Brian, I think you might have misunderstood how I reworked the /only and /pad-only refinements, or I've misunderstood what you're trying to say about it. Let's consider /ONLY: The first value in DATA is a block, so the result is a block. The second value 2 is inserted as is. The third value [3] is a block, but the contents are INSERTed, so the block is unwrapped: >> conjoin '| [["one"] 2 [3]] == ["one" | 2 | 3] Same result except this time the /ONLY refinement causes the third value [3] to be inserted as is, so it remains a block: >> conjoin/only '| [["one"] 2 [3]] == ["one" | 2 | [3]] This seems to me to be a necessary option in the treatment of the input data. | |
Anton: 8-Sep-2006 | pad -> "delimiter" - I am forced to agree that "delimiter" is a better word, I'll probably align with you on that, although it's hard to go up to such a longer word again :) | |
Anton: 8-Sep-2006 | No, I have thought of a reasonable situation. | |
Volker: 8-Sep-2006 | So i think its rare and acceptable. While i would use it a lot for printing a result-block nicely delemited. | |
Anton: 8-Sep-2006 | Maybe it's hard to think of the usages now, but, you know, it took a while to learn when and how to use rejoin. | |
Oldes: 8-Sep-2006 | Just wanted to remind, that Rebcode was here for a short time:-) Hope it will come back:-) | |
BrianH: 9-Sep-2006 | As for the word "delimiter" I made sure it wouldn't be exported to the external programming environment - no keyword arguments in REBOL, and I didn't use it for a function name or refinement. The more precise meaning of the word makes it a better choice for source that may serve as documentation, using the help or source commands. | |
Anton: 10-Sep-2006 | Yes, please. I think I lost sight of the overall picture when I added /only and /pad-only. (Reminds me of a similar thought process in another frenetic function creation a year or two ago (?)) I was not thinking of the functionality that DELIMIT covered when I was "designing" those refinements. So on further reflection, it looks to me like you are right, for CONJOIN, using INSERT rather than INSERT/ONLY on the DATA values is more useful. | |
BrianH: 10-Sep-2006 | delimit: func [ "Put a value between the values in a series." data [series!] "The series to delimit" delimiter "The value to put into the series" /only "Inserts a series delimiter as a series." /copy "Change a copy of the series instead." /local ] [ while either copy [ if empty? data [return make data 0] local: make data 2 * length? data [ local: insert/only local first data not empty? data: next data ] ] [ local: data [not empty? local: next local] ] either only [ [local: insert/only local delimiter] ] [[local: insert local delimiter]] head local ] conjoin: func [ "Join the values in a block together with a delimiter." data [any-block!] "The values to join" delimiter "The value to put in between the above values" /only "Inserts a series delimiter as a series." /quoted "Puts string values in quotes." /local ] [ if empty? data [return make data 0] local: tail either series? local: first data [copy local] [form :local] while [not empty? data: next data] either any-string? local [ either quoted [ local: insert tail insert head local {"} {"} [local: insert insert insert insert local (delimiter) {"} first data {"}] ] [[local: insert insert local (delimiter) first data]] ] [ either only [ [local: insert insert/only local (delimiter) first data] ] [[local: insert insert local (delimiter) first data]] ] head local ] | |
Tomc: 10-Sep-2006 | consider /delimiter accepting a block that is rotated through. ["|" "|" "|" "|^/"] | |
Anton: 11-Sep-2006 | You can do this and anything else when passing in a function as delimiter. | |
BrianH: 11-Sep-2006 | Tom, you can do that by passing a function as the delimiter, like this: has [x y] [x: ["|" "|" "|" "|^/"] y: first x if tail? x: next x [x: head x]] | |
BrianH: 11-Sep-2006 | You don't need to parenthesise delimiter in delimit because every reference to it is at the end of a block. Using parentheses is slower in REBOL, so why use them when you don't have to? | |
Anton: 12-Sep-2006 | d: has [x i][i: [1] i/1: i/1 + 1 pick [a b c] (i/1 - 2 // 3 + 1)] | |
Anton: 12-Sep-2006 | d: has [x][x: [[a b c]] x/1: next either tail? x/1 [head x/1][x/1] first back x/1] | |
Gregg: 12-Sep-2006 | Wow. A lot of thought here. I've skimmed it (trying to catch up on things quickly), and will just post a couple quick thoughts. * REJOIN is probably a good enough name to stick with; I don' t know that any of the others are that much more meaningful in the context of REBOL. * Changing JOIN's params would break a lot of code. * I have a DELIMIT function as well, and like the name. Mine doesn't have /copy or /only refinements (it always uses insert/only), but it has /skip. | |
Pekr: 12-Sep-2006 | i did not follow the whole discussion, so dunno what exactly 'delimit does, but could we have also a 'pad function? | |
Pekr: 14-Sep-2006 | concat came to my mind - because, really guys, for me, czech speaking person, conjoin sounds like something rude I even don't know. So concat, I at least know as a term from other languages :-) | |
Volker: 14-Sep-2006 | conjoin inserts delemiters too, did i get that right? How about a simple 'list, i feel its a good match, listing things. But not native speaker.. Another idea: it icould be related to csv (this spreadsheet-format, got i the letters right), a conjoin is close to exporting? | |
Pekr: 14-Sep-2006 | we have already list-dir, so list is a good match imo ... | |
BrianH: 14-Sep-2006 | The word "concat" is usually used for a function similar to join rejoin. | |
BrianH: 15-Sep-2006 | Well, REBOL blocks can double as datasets, with either nested blocks or fixed-length records. You could probably do a variant on conjoin that could convert either of these types to a CSV file, even with one that has its records delimited by something other than a comma, like a tab. Creating a new function to do this based on the techniques in conjoin would currently be easier than using conjoin to perform this task. | |
BrianH: 15-Sep-2006 | On the other hand, if you don't want a full copy of the CSV fie in memory and would rather just convert to disk, conjoin should work just fine. It might be a good idea to add a /part option for fixed-length record blocks. | |
Anton: 18-Sep-2006 | Ladislav, I'm not sure what the main question is. Could you explain the control flow that would lead to a 1 result ? | |
Volker: 18-Sep-2006 | i do not like that a break can break function-nesting. | |
Ladislav: 18-Sep-2006 | i do not like that a break can break function-nesting. - you can always "break out of a function", unless the BREAK implementation is faulty | |
Volker: 18-Sep-2006 | I think lexically. if i pass a closure with a break, it should at least break into my code, and not inside some foreign code where it creates havoc. | |
Volker: 18-Sep-2006 | But we need a way to enforce cleanup? something like 'finally? If a module provides an open-do-close [my-code] my code should not be able to avoid the close? | |
Ladislav: 18-Sep-2006 | so in REBOL2 we cannot (at least not in a simple way) use loop when implementing a control struct | |
BrianH: 18-Sep-2006 | I would normally be on the side of dynamic break - it would be easier to teach, and the rest of REBOL follows that model. What would be the major advantage of lexical break in a non-compiled language? REBOL code blocks aren't really lexically associated with their control structures in the DO dialect, as my conjoin and delimit functions above demonstrate. This isn't rebcode you know. | |
Ladislav: 18-Sep-2006 | right. OK, in case we will use dynamic BREAK in REBOL3 (highly probable), I will propose to introduce a new /THROW refinement for the WHILE cycle to "pass along" BREAK and that is all | |
Ladislav: 18-Sep-2006 | no, because in the case I am programming a control function I do not want to force the users to specify the destination just because they are using my control function | |
BrianH: 18-Sep-2006 | There are function attributes to prevent a function from catching a return or throw, should there be one for break? | |
Ladislav: 18-Sep-2006 | no, because this is a loop business, function attributes cannot help | |
BrianH: 18-Sep-2006 | For that matter, I thought the point to runing a block of code with a loop 1 was to catch breaks. Can you rebreak? | |
Ladislav: 18-Sep-2006 | while: native [ {While a condition block is TRUE, evaluates another block.} cond-block [block!] body-block [block!] /throw {pass along break} ] | |
Ladislav: 18-Sep-2006 | For that matter, I thought the point to runing a block of code with a loop 1 was to catch breaks. - sorry for my oversimplification, I didn't mean to use *only* 1 | |
Ladislav: 18-Sep-2006 | Add it to the other loop functions too. - this is a "higher level" business and I will be content with having at least WHILE/THROW. I guess, that it will not be used frequently (?) | |
Ladislav: 18-Sep-2006 | Moreover, it looks to me, that we are able to "simulate" such a construct using PARSE in REBOL2 | |
Ladislav: 18-Sep-2006 | just a side note: it looks, that we will get CONTINUE in REBOL 3 too and I suppose the /THROW to "pass along" CONTINUE too | |
Ladislav: 18-Sep-2006 | regarding the structural problem: we should convince Carl to give us a comfortable APPLY function, shouldn't we? | |
Ladislav: 18-Sep-2006 | so, I guess that it would be nice if you found a spec for APPLY that would be able to handle refinements in some way | |
BrianH: 18-Sep-2006 | I used it quite a bit. You remember how much I posted in the rebcode group :) | |
BrianH: 18-Sep-2006 | APPLY would take refinements as positional arguments. That meant you would need to match the order of refinements in the declaration of the function you are calling, and that your function call would break if the function changed the order of its arguments - fragile. For some reason APPLY was slow too, and would crash REBOL if run too many times in a rebcode function. | |
Ladislav: 18-Sep-2006 | function call would break if the function changed the order of its arguments - fragile I am afraid, that it is hard to find a less fragile spec, though | |
BrianH: 18-Sep-2006 | Look back on the rebcode group. It was a standing problem. I was more concerned about it being slow as dirt though - the instability was likely to get fixed, but the slowness may be structural. | |
BrianH: 18-Sep-2006 | Can you get from a refinement to the word it is based on? Are refinements bound? | |
BrianH: 18-Sep-2006 | If so, you could pass along the refinements as keyword arguments in a REBOL version of APPLY. | |
BrianH: 18-Sep-2006 | Oh well, there goes one idea for a less fragile interface. | |
Ladislav: 18-Sep-2006 | ...but if you write f: func [/a] [/a 'a], then the /a refinement isn't bound, but the 'a *is* | |
BrianH: 18-Sep-2006 | But if you write a: none apply :f [/a] then the apply function can't tell that it should be passing the /a refinement as none. | |
BrianH: 18-Sep-2006 | If /a is not bound, I mean. | |
Ladislav: 18-Sep-2006 | right, you would need to write apply :f [/a a] | |
Gabriele: 21-Sep-2006 | hmm, that depends on a lot of things. i'd say yes, but otoh there may be cases where that is not a good idea. it's to early to say anything about that, anyway. | |
Maxim: 21-Sep-2006 | I agree... and with dual cores becoming increasingly main stream... there is a definite advantage in that. | |
Maxim: 21-Sep-2006 | hehe if windows didnt design "kill a task" from inception... I can only imagine how well its threads must be implemented. <sigh> | |
Gabriele: 21-Sep-2006 | there is a crossplatform library iirc, i hope it works :) | |
BrianH: 21-Sep-2006 | Threads are actually done very well on Windows. They also have a fast shared-memory thread-like thing called fibers. It was only recently that some of the Unixes were able to catch up (except Solaris, which may be better). | |
Anton: 5-Oct-2006 | Three letters start to look a little bit cryptic. Reminds me of LISP's car, cdr, cadr etc. | |
Tomc: 5-Oct-2006 | yes get/set for a 0 based series seems reasonable at the moment | |
Henrik: 5-Oct-2006 | will we need a 'zeroth too? | |
Volker: 5-Oct-2006 | can it be a long name? pick-before series 27 is what it does. | |
Cyphre: 14-Nov-2006 | Pekr: The 'old' licence for AGG 2.3 and 2.4 remains. GPL is for 2.5 which is at the moment at the same leve as 2.4(regarding functionality). So far noone from the AGG comunity(or at least at the ML) don't know why Maxim decided to change the licence.(everyone is waiting for his reply) Maxim also wrote "Current AGG users who are willing to continue using AGG under the old terms and conditions are encouraged to contact me and I will consider their requests." so nothing is lost if we would like to use 2.5. Anyway, even the AGG2.3 framework is very stable and have 99% of the features same like 2.4 and up. The whole code quality is very good so it is possible to enhance it...so this shouldn't be a big problem for Rebol. Another thing is that in the 'worst case' current AGG users/developers who don't want or cannot use the GPL version are planning to continue with improving the 2.4 codebase separately. | |
Henrik: 14-Nov-2006 | That would shave off a lot of development time for an app, I'm developing. Just this one feature. Thanks. | |
Robert: 17-Nov-2006 | I'm always wondering why people depend on the next release to start their app... take what you have and do it. There is always a way. It's like with a team. You got the people you have and good management is, to get to the goal with your team you have. Winning with a dreamteam is no art. | |
Louis: 23-Nov-2006 | rebol [ purpose: "Demonstrate how to use the findany function." note: {This is a function I would like included in Rebol3. One of you experts (I don't remember who) made this function for me, and I use it all the time. Do you see any ways it can be improved before I submit it? --- Louis } ] s: "findany will return true if it finds in this sentence any of the strings you enter in the request box." print [s newline] forever [ bs: copy parse (request-text/title "Enter the strings you want to find separated by a space.") none findany: func [ "Searches string x for any substring found in block ys." x [string!] "string" ys [block!] "block of substrings" /local pos ] [ foreach y ys [ if pos: find x y [return pos] ] ] either findany s bs [print true][print false] ] halt | |
Louis: 23-Nov-2006 | rebol [ purpose: "Demonstrate how to use the findall function." note: {This is a function I would like included in Rebol3. This is my function. Do you see any ways it can be improved before I submit it? --- Louis} ] s: "findall will return true only if it finds in this sentence all the strings you enter in the request box." print [s newline] forever [ bs: copy parse (request-text/title "Enter the strings you want to find separated by a space.") none findall: func [ "Seaches string s for all substrings find in block bs." s [string!] "string to search in" bs [block!] "block of strings to search for" ][ findit: func [ s [string!] "string to search in" b [string!] "string to search for" ][ if find s b [either find s b [true][false]] ] foreach b bs [either findit s b [true][break/return false]] ] either findall s bs [print true][print false] ] halt | |
Anton: 24-Nov-2006 | Functions like these are very useful to have. I could have used them recently while doing file searching. However, I wouldn't like to see these functions included as is. - Not very efficient. That's ok for searching small strings or the contents of short files, but bad when searching large files for many strings. - Not generic. The name suggests many datatypes are supported. Better names might be find-any-string, find-all-strings - The above FINDALL does not keep FINDIT as a local. - The argument names are too short, so they are not distinct or descriptive enough. - The return values are not defined clearly in the function doc strings. The above issues are fixable, but it will take some time. | |
Louis: 24-Nov-2006 | Who can make these functions the most efficient, and display them in a benchmark program to prove it? And correct all the other problems mentioned by Anton. | |
[unknown: 5]: 24-Nov-2006 | Louis, the way I benchmark in REBOL is to do a trace count. In other words if the execution of the trace generates more output than another method then I assume that method is less efficient. | |
Anton: 25-Nov-2006 | Stayed up all night, and succeeded in making a parse rule generator, so if we want to search a string for any substrings: string: {Hello there Anton. Arrow in the box. What nice antlers you have.} substrings: ["ant" "antler" "anton" "arrow" "bar" "box"] rule: [start: [["a" [["nt" action ["ler" action | "on" action]] | "rrow" action]] | ["b" ["ar" action | "ox" action]]] | skip] Found at: 13 Substring: "Ant" Found at: 13 Substring: "Anton" Found at: 20 Substring: "Arrow" Found at: 33 Substring: "box" Found at: 48 Substring: "ant" Found at: 48 Substring: "antler" true | |
Anton: 25-Nov-2006 | Thus we are able to search large files for any number of substrings in a single pass parse. :) | |
Anton: 25-Nov-2006 | Thankyou, Jerry. I wonder if anyone else made a parse generator like that ? | |
Louis: 25-Nov-2006 | Maxim and Anton, what difference does it make which value is returned? It is the true or false that I am looking for. If any of the strings are found, why look any farther? I'm sure you guys have a reason, but I want to know what it is. | |
Anton: 25-Nov-2006 | .. and a name like FINDALL suggests that it returns those matches. | |
Louis: 25-Nov-2006 | But I would really like to see funtions that find-any-substring and that find-all-substrings included in REBOL3, as they make programming a lot easier---at least for me. |
26801 / 64608 | 1 | 2 | 3 | 4 | 5 | ... | 267 | 268 | [269] | 270 | 271 | ... | 643 | 644 | 645 | 646 | 647 |