AltME groups: search
Help · search scripts · search articles · search mailing listresults summary
world | hits |
r4wp | 0 |
r3wp | 71 |
total: | 71 |
results window for this page: [start: 1 end: 71]
world-name: r3wp
Group: All ... except covered in other channels [web-public] | ||
Gregg: 17-May-2006 | Gabriele's need to delimit the rules with '| brings up another old mezzanine thought: rejoin/with. I created a separate mezz, called DELIMIT, but this is a fairly common need IME. Should we start another ML thread? :-) | |
Group: Core ... Discuss core issues [web-public] | ||
JaimeVargas: 7-Jul-2006 | Maybe this useful to someone delimit: func [data /quoted /with separator [string! char!] /local result quote][ result: copy {} unless with [separator: ","] quote: either quoted [:mold][func[x][x]] append result quote form first data foreach value next data [ append result separator append result quote form value ] ] delimit [1 2 3] ;== "1,2,3" delimit/with [1 2 3] ":" ;== "1:2:3" delimit/quoted [1 2 3] ;== {"1","2","3"} delimit/quoted/with [1 2 3] "|" ;== {"1"|"2"|"3"} | |
Gregg: 1-Jan-2007 | I have a DELIMIT function that will do it, changing the series in place, with the exception of the trailing element. So the final result would look like this: append delimit/skip series new-value record-size new-value The basic idea you want is this: series: skip series size series: head forskip series size + 1 [insert/only series value] My DELIMIT func also works with list! and any-string! types correctly, which simple code above doesn't account for (the +1 part is simplified). | |
Gregg: 25-Oct-2008 | as-utc: func [date] [ if all [date/zone 0:00 <> date/zone] [ date: add date negate date/zone ] date/zone: none if none? date/time [date/time: 0:0:0] date ] to-ISO8601-date: func [ "Converts a date! value to an ISO 8601 format string." date [date!] "The date to format" /T {Use T to delimit time value, rather than a space} /no-zone "Don't include the timezone" /local pad z ][ pad: func [val /to len] [ val: form val head insert/dup val #"0" ((any [len 2]) - length? val) ] rejoin [ pad/to date/year 4 "-" pad date/month "-" pad date/day either T ["T"] [" "] either none? t: date/time ["00:00:00Z"] [ ;<< reusing 'T here! rejoin [ pad t/hour ":" pad t/minute ":" pad round t/second either no-zone [""] [ either 0:00 = z: date/zone ["Z"] [ ;<< setting 'z here! rejoin [ pick ["+" "-"] z/hour > 0 pad abs z/hour pad abs z/minute ] ] ] ] ] ] ] | |
Group: I'm new ... Ask any question, and a helpful person will try to answer. [web-public] | ||
Gregg: 21-Jul-2007 | delimit: func [ "Insert a delimiter between series values." series [series!] "Series to delimit. Will be modified." value "The delimiter to insert between items." /skip ;<-- be sure to use system/words/skip in this func size [integer!] "The number of items between delimiters. Default is 1." ][ ; By default, delimiters go between each item. ; MAX catches zero and negative sizes. size: max 1 any [size 1] ; If we aren't going to insert any delimiters, just return the series. ; This check means FORSKIP should always give us a series result, ; rather than NONE, so we can safely inline HEAD with it. if size + 1 > length? series [return series] ; We don't want a delimiter at the beginning. series: system/words/skip series size ; Use size+n because we're inserting a delimiter on each pass, ; and need to skip over that as well. If we're inserting a ; series into a string, we have to skip the length of that ; series. i.e. the delimiter value is more than a single item ; we need to skip. size: size + any [ all [list? series 0] ; lists behave differently; no need to skip dlm. all [any-string? series series? value length? value] all [any-string? series length? form value] 1 ] head forskip series size [insert/only series value] ] | |
Gregg: 21-Jul-2007 | fmt-for-Excel: func [blk dlm] [ rejoin delimit collect fld [ foreach val blk [ val: form val replace/all val {"} {""} if find val #"," [val: rejoin [{"} val {"}]] fld: val ] ] dlm ] fmt-for-Excel [{"A"} "B" "C,C" {"4,4"}] #"," | |
Group: Parse ... Discussion of PARSE dialect [web-public] | ||
Gabriele: 4-Sep-2007 | it's not a bug - parse without a rule is meant for csv parsing, and quotes delimit a field. it's not as useful as it was intended to be, but it's intentional behavior. you need to provide your own rule if you don't want quotes to be parsed. | |
Group: Rebol School ... Rebol School [web-public] | ||
PatrickP61: 5-Jul-2007 | Tomc -- This version means that I need to have the entire file read in as a string -- Not with Read/Lines -- Because the newline will the the "delimiter" within the string while the Read/Lines will delimit each newline to a separate string inside a block. Do I have that right? | |
Andreas: 6-Jul-2011 | Janko: you can, in general, use string parsing for EDSLs. Use {..} to delimit your code blocks instead of [..], and a different set of lexical limitations will apply. | |
Oldes: 12-Jul-2011 | Also I can clearly understand, why Janko needs the delimiter in his dialect. It simplifies a lot when you can delimit values, where some of the values can be functions requiring arguments. Without the delimiter you must add pretty large complexity which will provide info, how many args require each funcion. | |
Gregg: 11-Aug-2011 | ; A dialected version of this could be very flexible; allowing more ; than just fixed size groupings. ; This could also be done by adding a /SKIP refinement to INSERT. delimit: func [ ;[throw catch] "Insert a delimiter between series values." series [series!] "Series to delimit. Will be modified." value "The delimiter to insert between items." /skip ;<-- be sure to use system/words/skip in this func size [integer!] "The number of items between delimiters. Default is 1." ][ ; Hmmm, I wonder if we could extend the function spec dialect ; to include constraints like this declaratively? And should ; we trap the arg like this, or just use MAX to make sure we ; have a positive value? I think I'll do the latter for now, ; but leave this here as a comment. ;if all [size not positive? size] [ ; throw make error! join [script invalid-arg] size ;] ; By default, delimiters go between each item. ; MAX catches zero and negative sizes. size: max 1 any [size 1] ; If we aren't going to insert any delimiters, just return the series. ; This check means FORSKIP should always give us a series result, ; rather than NONE, so we can safely inline HEAD with it. if size + 1 > length? series [return series] ; We don't want a delimiter at the beginning. series: system/words/skip series size ; Use size+n because we're inserting a delimiter on each pass, ; and need to skip over that as well. If we're inserting a ; series into a string, we have to skip the length of that ; series. i.e. the delimiter value is more than a single item ; we need to skip. size: size + any [ all [list? series 0] ; lists behave differently; no need to skip dlm. all [any-string? series series? value length? value] all [any-string? series length? form value] 1 ] head forskip series size [insert/only series value] ] | |
Gregg: 11-Aug-2011 | make-csv: func [block] [rejoin delimit copy block #","] | |
Group: rebcode ... Rebcode discussion [web-public] | ||
BrianH: 12-Oct-2005 | Gabriele, thanks for the info about the rewrite rules. That's an interesting way to lay them out - a little more traditional that I've come to expect from REBOL, but that #==> is unlikely to be found in REBOL code so its use to delimit the parse rules should work nicely. I look forward to trying it out! | |
Group: !REBOL3-OLD1 ... [web-public] | ||
JaimeVargas: 31-Aug-2006 | delimit [1 2 3] ;== "123" delimit/with [1 2 3] "," ;== "1,2,3" delimit/quoted [1 2 3] ;== {"1","2","3"} delimit/quoted/with [1 2 3] "|" ;== {"1"|"2"|"3"} npa: 703 nxx: 938 delimit [npa nxx] ;== "npa nxx" delimit/reduce [npa nxx] ;= "703938" delimit/reduce/with [npa nxx] "-" ;== "703-938" delimit/reduce/quoted/with [npa nxx] "|" ;== {"703"|"938"} | |
JaimeVargas: 31-Aug-2006 | ;; usage examples delimit [1 2 3] ;== "123" delimit/with [1 2 3] "," ;== "1,2,3" delimit/quoted [1 2 3] ;== {"1","2","3"} delimit/quoted/with [1 2 3] "|" ;== {"1"|"2"|"3"} npa: 703 nxx: 938 delimit [npa nxx] ;== "npa nxx" delimit/reduce [npa nxx] ;= "703938" delimit/reduce/with [npa nxx] "-" ;== "703-938" delimit/reduce/quoted/with [npa nxx] "|" ;== {"703"|"938"} | |
JaimeVargas: 31-Aug-2006 | ;; Here is my implementation, maybe in can be fine tuned. delimit: func [data [block!] /reduce /quoted /with separator [string! char!] /local result quote][ unless empty? data [ result: copy {} unless with [separator: ""] quote: either quoted [ func[x][rejoin [{"} x {"}]] ][ func[x][x] ] insert result quote form either reduce [do first data][first data] foreach value next data [ insert insert tail result separator quote form either reduce [do value][value] ] result ] ] | |
JaimeVargas: 31-Aug-2006 | ;; New version does proper reduction delimit: func [data [block!] /reduce /quoted /with separator [string! char!] /local result quote][ if reduce [data: system/words/reduce data] unless empty? data [ result: copy {} unless with [separator: ""] quote: either quoted [ func[x][rejoin [{"} x {"}]] ][ func[x][x] ] insert result quote form first data foreach value next data [ insert insert tail result separator quote form value ] result ] ] | |
JaimeVargas: 31-Aug-2006 | ;; example >> delimit/reduce/with [npa nxx square-root 4] " " ;== "703 938 2.0" | |
JaimeVargas: 31-Aug-2006 | And DELIMIT | |
JaimeVargas: 31-Aug-2006 | Do you want the added functionality of the DELIMIT above? | |
Anton: 31-Aug-2006 | conjoin is cool, language root are like "delimit/with" | |
Anton: 31-Aug-2006 | Ah yes, Jaime, I wanted to say "DELIMIT" lies to you when it is used without the /WITH refinement, because DELIMIT implies delimiters. If there aren't any delimiters, then it is lying. | |
Anton: 31-Aug-2006 | So an idea I would like to explore is to split the functionality of DELIMIT into perhaps two functions. As this kind of operation is very common, I suggest that this will save lots of typing. | |
JaimeVargas: 31-Aug-2006 | The description I have for DELIMIT is "Returns a string! constructed from the chained values in the block." | |
JaimeVargas: 31-Aug-2006 | I should not that I am not attached to DELIMIT. It stated like with a different purpose, but now I see that is more generic than REJOIN. So I offer it after modifying it a bit. | |
JaimeVargas: 31-Aug-2006 | Picking names is very hard. I kind of like to have all the functionality cram in one function, less words to remember. So I left the naming decision to the community, just hope the features of delimit are include in R3. | |
Anton: 31-Aug-2006 | So I would drop the /WITH refinement and make it implicit in a DELIMIT or CONJOIN function... (maybe..) 1) rejoin/quoted [...] ; <-- this is most similar to rejoin, or delimit without the /WITH 2) conjoin/quoted "," [...] ; <-- this is like delimit/with/quoted (and the non-optional "with" argument is specified first) | |
Anton: 31-Aug-2006 | The second function, CONJOIN, is like your DELIMIT, except with WITH refinement implicit. | |
JaimeVargas: 31-Aug-2006 | >> delimit [1 1 / 2 ] ; == "11/2" >> delimit/reduce [1 1 / 2] ; == "10.5" | |
JaimeVargas: 31-Aug-2006 | delimit [1 1 / 2] ;== "10.5" delimit/literal [1 1 / 2] ;== "11/2" | |
JaimeVargas: 31-Aug-2006 | Also, your implementation is slower than DELIMIT, by an order of magnitude. >> time-block [conjoin "," []] 0.05 ; == 4.953515625E-5 >> time-block [delimit/with [] ","] 0.05 ; == 2.453125E-6 | |
BrianH: 1-Sep-2006 | When I said I like conjoin, I meant the word "conjoin". I think it woud be a good name for the ONE function that would perform a useful subset of all of the tasks that have been specified here as part of the various functions suggested here, starting with Jaime's delimit, but with the delimiter mandatory. We already have a verson of delimit without the delimiter - it's called rejoin. | |
BrianH: 1-Sep-2006 | To me, delimit would intersperse the delimiter in the block but not join it. That what the word suggests, at least. | |
JaimeVargas: 1-Sep-2006 | So the suggestion of globing all the DELIMIT features into the new function. | |
BrianH: 1-Sep-2006 | I am currently rewriting delimit and conjoin to implement a few of my own ideas for it. You do yours and we'll compare. | |
BrianH: 1-Sep-2006 | As far as I'm concerned, delimit and conjoin are separate concepts. | |
BrianH: 1-Sep-2006 | Like I said before, the word "delimit" doesn't imply joining, while "conjoin" does. I'm expecting to make my conjoin function use my delimit. | |
BrianH: 1-Sep-2006 | Strings are not the typical usage for me. I saw those functions posted above and none of them would work for me. I'm writing my own right now, for posting here. I have delimit so far, and am now working on conjoin. | |
BrianH: 1-Sep-2006 | As an example, here is delimit. I'll post conjoin soon. | |
BrianH: 1-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." ] [ while either copy [ copy: make data 2 * length? data either empty? data [[false]] [[ copy: insert/only copy pick data 1 not empty? data: next data ]] ] [ copy: data [not empty? copy: next copy] ] either only [[ copy: insert/only copy delimiter ]] [[ copy: insert copy delimiter ]] head copy ] | |
BrianH: 1-Sep-2006 | Well, it will be a little hard to check against your delimit since that will be more comparable to my conjoin. Still, building the while statement this way is no slower than calling one of several different while statements depending on options, and it is a lot less redundant. Plus it's fun. | |
BrianH: 1-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." ] [ while either copy [ if empty? data [return make data 0] copy: make data 2 * length? data [ copy: insert/only copy first data not empty? data: next data ] ] [ copy: data [not empty? copy: next copy] ] pick [ [copy: insert/only copy delimiter] [copy: insert copy delimiter] ] only head copy ] | |
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. | |
Anton: 2-Sep-2006 | Brian, I think Jaime was making the same point, as I do above, about speed vs clarity, with regards to /copy. Some benchmarking is needed comparing: - delimit/copy data ; <--- delimit with /copy refinement implemented - delimit copy data ; <--- delimit without /copy refinement | |
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.) | |
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 copy refinement on the delimit function should be faster than pre-copying the data because the copy is preallocated to size. | |
BrianH: 9-Sep-2006 | I did understand your point about the /only and /pad-only refinements, but I realized that my delimit function made the change unnecessary, since its behavior was exactly what you were getting at. Using your example: >> delimit ["one" 2 [3]] '| == ["one" | 2 | [3]] | |
BrianH: 9-Sep-2006 | Keeping the concepts distinct wasn't the only reason I made seperate "conjoin" and "delimit" functions - it's more efficient too. | |
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 ] | |
Anton: 11-Sep-2006 | Brian, maybe delimiter needs to be parenthesised in DELIMIT as well ? | |
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? | |
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? | |
Anton: 13-Sep-2006 | Gregg, I think Brian's last post with DELIMIT and CONJOIN are probably the best in this thread. | |
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. | |
Anton: 12-Aug-2009 | For example, I think RobertS might be happier if a new special type of string which is delimited by ~{ and }~ was added to Rebol. In the content, single braces } or single tildes ~ would not need any escaping unless they happened to be together so that they look like the ending delimiter. Or maybe no escaping is possible/necessary in such a string. But now I'm also thinking of the start and end unique key strings used to delimit email attachments... | |
BrianH: 17-Nov-2009 | Paul, that function has been proposed as DELIMIT - not as REJOIN because that function needs to be low-level - but hasn't been added yet since there is no consensus about the feature set. No consensus means it goes in the library rather than the mezzanines. If you can make a version that is so awesome that everyone will agree with your feature set, we'll add it :) | |
Pekr: 18-Nov-2009 | hmm, there is a 'delimit function ... it seems to be renamed to 'split .... | |
Group: !REBOL3 ... [web-public] | ||
BrianH: 19-Jul-2011 | There is a conceptual conflict between the treatment of splitting into parts by length and splitting by delimiter, that has the effect of limiting both sets of behavior. It would be better to put the delimiter splitting into a separate function called DELIMIT. This would allow the dialected variants of SPLIT and DELIMIT to develop separately without conflict, and make the SPLIT dialect easier to understand. Then you would have two relatively simple functions with a clear distinction between them. | |
Gregg: 29-Jul-2011 | Brian, DELIMIT means something very different to me. My DELIMIT func inserts delimiters. I don't have a problem with using a 'skip keyword. As I said, the current behavior wasn't the original design and may be Carl's doing. Check with him on that. There is a conceptual conflict between the treatment of splitting into parts by length and splitting by delimiter... -- I don't see that, but I'm biased. I'm always happy to see alternative designs. | |
BrianH: 31-Jul-2011 | I checked a half-dozen online dictionaries to get that definition of DELIMIT. Perhaps you're checking different dictionaries. The conceptual conflict: - Dialected splitting has incompatible dialects, which makes both more limited than they should be. - Splitting a block based on a delimiter of one of the types used by length-based splitting isn't allowed. | |
BrianH: 31-Jul-2011 | I think that the word for inserting delimiters the way your old DELIMIT function did is "intersperse", but we can do better than that. | |
Kaj: 31-Jul-2011 | DELIMIT sounds OK to me for inserting delimiters, with TOKENIZE probably its reverse | |
Pekr: 1-Aug-2011 | wouldn't DELIMIT/ENLIMIT make sense? We have already en/decloak, de/encode, de/enbase, en/deline .... | |
Gregg: 1-Aug-2011 | delimit: set, mark, or draw the boundaries of something ENLIMIT doesn't make sense to me. | |
Gregg: 4-Aug-2011 | On the DELIMIT func name topic, my original suggestion, long ago, was to add /SKIP to INSERT, but that never went anywhere. What is the current feeling toward that (knowing that getting it added might be an obstacle). | |
Kaj: 4-Aug-2011 | It's currently associated with fixed length records. I'm not sure that's flexible enough for DELIMIT | |
Group: Core ... Discuss core issues [web-public] | ||
BrianH: 16-Oct-2010 | Three reasons: - The { and } are not chosen at random, they are the consequence of using those characters to delimit strings themselves. - There aren't many characters or character sequences that can be optional without conflicting with other stuff in the grammar. - Syntax processors with user-defined stuff in them are much slower than ones without them. |