• Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

AltME groups: search

Help · search scripts · search articles · search mailing list

results summary

worldhits
r4wp237
r3wp1294
total:1531

results window for this page: [start: 401 end: 500]

world-name: r3wp

Group: RAMBO ... The REBOL bug and enhancement database [web-public]
Anton:
28-Dec-2006
BASE-TEXT/init assumes that font/colors is a series, which means 
that this makes an error:

>> view layout [text "Hello" font svv/vid-styles/FIELD/font]

** Script Error: change expected series argument of type: series 
port
** Where: forever
** Near: change font/colors font/color
if none?
Anton:
8-Jan-2007
You misunderstand - the bug is not because the series index is at 
the TAIL, it is because the copy/part RANGE is -2147483648
Anton:
8-Jan-2007
To be clear ;  when the copy/part RANGE is *negative* it copies *backwards* 
from the series index.  This is useful, but not well known, I think.
Maxim:
11-Feb-2007
ladislav, many funcs are intended to support all of a given set of 
types (numbers, series, etc).


we must not turn rebol into a "strict" language... the "looseness" 
in the case where some effects are irrelevent are not really bugs.
Maxim:
11-Feb-2007
but that depends where the "" comes from... your human sense sees 
this as a bug, but an algorythm merging a set of series of abstract 
types would not...  ;-)
Anton:
10-May-2007
and you can move the word into other series datatypes like path, 
then back to a block and see the new-line has followed it.
Anton:
22-May-2007
This is interesting because a path is a series, supposedly very similar 
to a block.
Dockimbel:
16-Jul-2007
btw, a/(:b/c) is quite heavy => 3 series instead of 1.
Group: Core ... Discuss core issues [web-public]
Volker:
12-Oct-2005
I rarely change values by reference, only series/objects. values 
i simply assign new.
 f: func[variable][100]
 variable: variable 100
If not, i at least mark the word, like
 f: func[variable][ set variable 100]
 f 'variable

Its style, but in rebol i rarely see a function changes a word, so 
i am avoiding to be surprised.
Graham:
24-Oct-2005
what happens to the series if you insert elements  into the list 
while you're in a forskip loop?

what position are you at  now?
Graham:
4-Nov-2005
I wonder if it would be possible to implement a dialect to get at 
parts of a series as in python.  With rebcode?


instead of copy/part string 4 ... , string/[:4], or if I want the 
5 and 6 elements, then string/[5,6]
Graham:
4-Nov-2005
what's the difference between

series/1

and 

series/[ 1 ]
JaimeVargas:
4-Nov-2005
series/1 has clear defined meaning under rebol. series/[1] is undefined.
BrianH:
4-Nov-2005
For that matter, series/[1] violates REBOL data syntax for paths, 
AFAIK.
BrianH:
4-Nov-2005
A lot of the time I do my dialect processing with functors, functions 
that create functions. Sometimes these functors run in pre-rebol, 
some at runtime function creation time. Then the actual work is done 
by the generated functions. This gives me the advantages of dialects 
without the drawbacks. On the other hand, dialects like draw are 
examples of my principle of low overhead in proportion to the that 
of the work performed - the dialect overhead isn't that much different 
to that of a series of function calls in the do dialect.
Graham:
5-Nov-2005
And other one dimensional series.
DideC:
5-Nov-2005
>> help foreach
USAGE:
    FOREACH 'word data body

DESCRIPTION:
     Evaluates a block for each value(s) in a series.
     FOREACH is a native value.

ARGUMENTS:

     word -- Word or block of words to set each time (will be local) (Type: 
     get-word word block
)
     data -- The series to traverse (Type: series)
     body -- Block to evaluate each time (Type: block)
Volker:
16-Nov-2005
But isnt that what insert/only does? putting a new value in front 
of a series? To match exactly it would be into a copy of the series, 
but i guess that does not matter.
Volker:
16-Nov-2005
cons: func[left rest][
 if all[ [] = left [] = rest ][ return copy [] ]
 head insert/only copy rest left
]
car: :first
null?: :tail?
cdr: func[series][ copy next series ]
subst: func[new old slist /local left rest][
 if null? slist[return make slist 0] ; same series-type please
 (cons 
  subst-in-symbol-expression new old car slist
  subst new old cdr slist
 )
]
subst-in-symbol-expression: func[new old se][
 if not any-block? se[
  if equal? se old [ return new ]
  return se
 ]
 subst new old se  
]
print "10 9 8 7 6 5 4 3 2 1 0 ??"
probe l: first[ ((b c) (b () d)) ]
probe subst 'a 'b l
Volker:
12-Dec-2005
forall: func [
    "Evaluates a block for every value in a series." 
    [catch throw] 

    'word [word!] {Word set to each position in series and changed as 
    a result} 
    body [block!] "Block to evaluate each time"
][
    throw-on-error [forskip :word 1 body]
]
Group: Syllable ... The free desktop and server operating system family [web-public]
Kaj:
22-Oct-2007
We've gone through a series of hosters, and it's a pain. We're consolidating 
on S3 now
Kaj:
23-Sep-2010
Syllable Desktop has the first article of a series of I think two 
in PCLinuxOS magazine:
Group: Linux ... [web-public] group for linux REBOL users
BrianH:
30-Apr-2009
Gabriele, they switched to the gradual change model with the 2.6.x 
series.
Kaj:
17-Dec-2009
But the issue can be any ot a whole series
Group: Rebol School ... Rebol School [web-public]
BrianH:
2-Jan-2009
REBOL doesn't include the standard higher-order functions, though 
they can be written in REBOL. Since there is no way to practically 
specify literal function values that work properly, the standard 
in REBOL is to use blocks for control function parameters rather 
than functions. Even though we are making the series mezzanines more 
friendly to function values, even in R3 the standard HOFs are being 
translated to REBOL style before inclusion.
BrianH:
2-Jan-2009
So R3's MAP takes 3 parameters:
- The data

- The word or block of words that will serve as "parameters" for 
the block.
- The block of code.

>> help map
USAGE:
        MAP 'word data body

DESCRIPTION:

        Evaluates a block for each value(s) in a series and returns them 
        as a block.
        MAP is a native value.

ARGUMENTS:

        word -- Word or block of words to set each time (local) (word! block!)
        data -- The series to traverse (block!)
        body -- Block to evaluate each time (block!)
Janko:
2-Jan-2009
this seems to work as simple map   fpmap: func [ series mod ] [ new: 
copy [ ] foreach item series [ append new mod item ] new ]
Janko:
2-Jan-2009
fpreduce: func [ series samp mod ] [ foreach item series [ samp: 
mod samp item ] samp ]           fpreduce [ 1 2 3 ] 0 func [s a][ 
s + a] == 6
BrianH:
2-Jan-2009
Start with this spec from R3:
map: func [

    {Evaluates a block for each value(s) in a series and returns them 
    as a block.}

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
] [...]
BrianH:
2-Jan-2009
map: func [

    {Evaluates a block for each value(s) in a series and returns them 
    as a block.}

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
] [
    foreach :word data reduce [:append [] to-paren body]
]
BrianH:
2-Jan-2009
map: func [

    {Evaluates a block for each value(s) in a series and returns them 
    as a block.}

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
] [

    foreach :word data reduce [:append make block! either word? word 
    [length? data] [divide length? data length? word] to paren! body]
]
BrianH:
2-Jan-2009
map: func [
    [throw]

    {Evaluates a block for each value(s) in a series and returns them 
    as a block.}

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
] [
    foreach :word data reduce [

        :append make block! either word? word [length? data] [divide length? 
        data length? word] to paren! body
    ]
]
BrianH:
2-Jan-2009
Here's the fastest version for R2:
map: func [
    [throw]

    "Evaluates a block for each value(s) in a series and returns them 
    as a block."

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
] [
    head foreach :word data reduce [

        :insert :tail make block! either word? word [length? data] [divide 
        length? data length? word] to paren! body
    ]
]
BrianH:
2-Jan-2009
map: func [
    [throw]

    "Evaluates a block for each value(s) in a series and returns them 
    as a block."

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
    /into "Collect into a given series, rather than a new block"
    output [series!] "The series to output to"
] [

    unless into [output: make block! either word? word [length? data] 
    [divide length? data length? word]]

    foreach :word data reduce [:insert :tail output to paren! body
    output
]
BrianH:
2-Jan-2009
I'm going to do a study of all of the REBOL functions that generate 
series (even natives) and determine which would benefit from the 
/into option, then get it added. It might be tricky to modify actions 
though. REDUCE and COMPOSE are getting the /into option.
BrianH:
2-Jan-2009
No, it doesn't change in place, and the /into should be able to insert 
in the middle of a provided series if necessary.
BrianH:
2-Jan-2009
If you want to replace, clear the series before providing it.
BrianH:
3-Jan-2009
It will be used in many functions, and natives. REDUCE and COLLECT 
/into get rid of chained inserts, for instance. It also reduces series 
copy overhead. It will be a big deal when we hahve rolled it out 
across the board.
Steeve:
3-Jan-2009
map: func [
    [throw]

    "Evaluates a block for each value(s) in a series and returns them 
    as a block."

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
    /into "Collect into a given series, rather than a new block"
    output [series!] "The series to output to"
] [

    unless into [output: make block! either word? word [length? data] 
    [divide length? data length? word]]

    head foreach :word data compose [output: (:insert)  output (to paren! 
    body)]
]
>> map x [1 2 3 4][x + x]
== [2 4 6 8]
>> map [x y][1 2 3 4][x + y]
== [3 7]
>> map/into [x y][1 2 3 4][x + y][10 11 12]
== [3 7 10 11 12]

But still a problem with the output var collision
Gregg:
3-Jan-2009
fold: func [ ; i.e. Haskell foldl (fold left). Same as 'reduce in 
Python?
        series [series!]
        fn     [any-function!]
        /with  value "starting value; used as accumulator"
    ][
        if not with [value: pick series 1  series: next series]
        foreach item series [value: fn value item]
    ]
    sum: func [block [any-block!]] [fold block :add]

    product: func [block [any-block!]] [fold/with block :multiply 1]
    sum-of-squares: func [block [any-block!]] [
        fold block func [x y] [x * x + y] 0
    ]
BrianH:
3-Jan-2009
Here's a version of MAP with the /into semantics and no variable 
capture problems. I had to add a local function, though it is only 
created once per call. Binding issues prevent the use of a literal 
function. While i was at it I added unset! handling like the R3 version.

map: func [
    [throw]

    "Evaluates a block for each value(s) in a series and returns them 
    as a block."

    'word [word! block!] "Word or block of words to set each time (local)"
    data [block!] "The series to traverse"
    body [block!] "Block to evaluate each time"
    /into "Collect into a given series, rather than a new block"
    output [series!] "The series to output to"
] [

    unless into [output: make block! either word? word [length? data] 
    [divide length? data length? word]]
    foreach :word data reduce [func [val [any-type!]] [
        if value? 'val [output: insert output :val]
    ] to paren! body]
    either into [:output] [head :output]
]
BrianH:
4-Jan-2009
The /into option is not just for MAP. It is intended to be added 
to a lot of series generating functions. The point of it is to allow 
those functions to optionally use INSERT semantics, so that we can 
make it easier to use buffers in a lot of places for memory savings. 
It's part of an overall strategy to reduce the memory overhead of 
REBOL code. INSERT semantics were chosen because INSERT is the most 
basic function here. CHANGE and APPEND can be implemented with INSERT 
(and REMOVE, HEAD and TAIL), but not so easily the other way.
BrianH:
4-Jan-2009
If you are going to retrofit one series function onto all of the 
series generation functions, INSERT is the most general.
Gregg:
4-Jan-2009
I understand. I just think it's bad design to have the same function 
return a different location in the series based on a refinement. 
 Whether they return the head, tail, or point of change, consistency 
is the thing.
Steeve:
4-Jan-2009
Brian, your last function is 2 time slower (on big series) just to 
avoid the collision with the 'result var and because you don't want 
2 distinct foreach blocks (one for /into, one for default).

You also forget to pre-insert void spaces when using the /into option, 
so that your implementation is incoherent with your initial statement 
of the need to avoid memory overhead

Actually, It's your choices (not the best ones to my mind) so i don't 
follow you. 

Finally, i don't see the interest to have not the fastest implementation 
of map in R2 just to have a strict retrocompatibilty with R3.
BrianH:
4-Jan-2009
The problem with preinserting with the /into option is break handling. 
If you break in the middle of the process, you end up with a bunch 
of nones in the middle of your series. I am interested in solutions 
to this.
BrianH:
4-Jan-2009
Only in one case: Inserting into the middle of a series, which is 
usually slow. We could just special case that one situation, or accept 
that it is as slow as it is in the rest of REBOL.
BrianH:
4-Jan-2009
We should check if it was in the rest of the 2.7 series - 2.7.6 is 
recent, but 2.7.5 is 2 years old.
kib2:
8-Feb-2009
I said my book wasn't clear because in presenting blocks, it uses 
the words "arrays", then "lists" and "series" inside : it's quiet 
confusing.
Geomol:
8-Feb-2009
I guess, words like "arrays" and "lists" are common in other languages. 
In REBOL, you'll see the word "series" a lot.
Geomol:
8-Feb-2009
A block is a series of elements (inside [ and ]).
Henrik:
8-Feb-2009
you can ask whether a datatype is a series with 'series?.
Henrik:
8-Feb-2009
not all series are alike. We tend to differ between strings and blocks 
and blocks come in a few different types, optimized for specific 
use, but they may hold the same content.
Geomol:
8-Feb-2009
A computer language theorist might tell you differences between arrays, 
lists and series. I suggest, you take the practical view and look 
at what datatypes, you find in REBOL.
Geomol:
8-Feb-2009
>> series? "abc"
== true
>> series? []
== true
>> series? make list! 10
== true

So there are many kinds of series.
Anton:
8-Feb-2009
A pair! is a datatype which looks like a series, but is unfortunately 
(for this case) a scalar. That means any modification causes the 
whole pair to be copied.
Group: rebcode ... Rebcode discussion [web-public]
btiffin:
1-Nov-2007
Mich; I'm not real up on rebcode, but I don't think apply can't be 
applied to make.  Apply can't evaluate action! or op! types.  So 
for that part you'd want    m: does [make image! 0x0]  f: rebcode 
[] [apply j m [] return j]


Then; I've never got the series opcodes to work.  insert, change 
... none of those.  mold system/internal/rebcodes/insert makes it 
look like they are not implemented.


So I would    f: rebcode [] [apply j m []  do j [insert j 1]  return 
j]  to get your to work, but with the do it's not going to be rebcode 
speedy.
Group: !REBOL3-OLD1 ... [web-public]
BrianH:
4-May-2006
As for the hash (or assoc) index and list data combo, it has some 
advantages. When you are inserting and removing data a lot lists 
have a known speed benefit but the real advantage as far as indexes 
are concerned is in how lists handle series offsets (I'm using the 
word offset here because I'm using the word index to refer to the 
external hash/assoc index).


Blocks encode their offsets as a number offset from the beginning 
of the series:

>> a: [a b c]
== [a b c]
>> b: skip a 2
== [c]
>> index? b
== 3
>> insert next a 'd
== [b c]
>> b
== [b c]
>> index? b
== 3

List offsets are pointers to the associated list element.

>> a: make list! [a b c]
== make list! [a b c]
>> b: skip a 2
== make list! [c]
>> index? b
== 3
>> insert next a 'd
== make list! [b c]
>> b
== make list! [c]
>> index? b
== 4


If you are indexing your data and your data in in a block, you need 
to update your index with almost every insertion and removal because 
the references to latter positions of the block in the index will 
be invalid. With list insertion and removal, external references 
are likely to still be valid unless the referenced elements themselves 
are deleted. If you are sure to delete the reference from the index 
(or replace it with nones) the rest of the index should be OK. New 
index references can just be tacked on the end, or put into the first 
empty entry. This makes live indexes a lot more practical.


On the down side, if you are using lists and they are long enough 
to make linear searches impractical, you really do need an external 
index for them to be useful. Also you need to balance the overhead 
and complexity of keeping the indexes updated against their benefit. 
This technique is not for the faint of heart unless you can get some 
guru to do algorithms for you.
Henrik:
14-May-2006
I've been wondering about an extension to EXTRACT as I haven't been 
able to find this particular functionality anywhere else. If it exists, 
then I'm wrong and you can ignore this.


I would like to propose adding a /size refinement to set the number 
of values extracted at each point. This would make it very easy to 
split a string in equal-sized chunks. It could also be used to retrieve 
equal sized parts of a set of database records. Combining this with 
/index, I think this could be very useful.

Here's how I would like it to work:

>> block: [1 2 3 4 5 6 7 8 9]
>> extract block 2
== [1 3 5 7 9]
>> extract block 4
== [1 5 9]
>> extract/index block 2 2
== [2 4 6 8 none]

The refinement at work:

>> extract/size block 4 2
== [[1 2] [5 6] [9 none]]
>> num: to-string 123456789
== "123456789"
>> extract num 3
== [#"1" #"4" #"7"]
>> extract/size num 3 1
== ["1" "4" "7"]
>> extract/size num 3 2
== ["12" "45" "78"]
>> extract/size num 3 3
== ["123" "456" "789"]
>> extract/size num 3 5
== ["12345" "45678" "789"]
>> extract/size/index num 3 5 2
== ["23456" "56789" "89"]
>> extract/size num 3 12
== ["123456789"]

/size would always return a block of series.
Gregg:
14-May-2006
Looks like it could be useful Henrik. I might call the refinement 
/part, to match other funcs. For the case of splitting a series into 
equal-sized pieces, or a fixed number of pieces, here's what I use:
Gregg:
14-May-2006
split: func [  ; subdivide, chunk, segment  ?

        {See: CLOS pg. 937. Not that mine works the same, but that was
        the inspiration.}
        series [series!]

        size   [integer!] "The size of the chunks (last chunk may be shorter)"

        /into  "split into a set number of chunks (last chunk may be longer 
        than others)."
        /local ct cur-piece result
    ][

        ct: either into [size] [round/down divide length? series size]
        if into [size: to-integer divide length? series size]
        result: copy []
        if zero? size [return result]
        parse series [
            ct [

                copy cur-piece size skip (append/only result cur-piece) mark:
            ]
        ]
        if any [into  not zero? remainder length? series size] [
            cur-piece: copy mark
            either into
                [append last result cur-piece]
                [append/only result cur-piece]
        ]
        result
    ]
Gregg:
14-May-2006
Hmm, should look at my notes. You'll probably want to add this as 
the first line in that func, or something similar, that handles the 
case where SIZE is larger than the series:

        size: min size length? series
Gregg:
20-May-2006
I'd bet a lot of us have thought of that one. I haven't pushed for 
it, because it seems like the places I think I'd use it most would 
have exceptions in the other direction. That is, I want to reduce 
*almost* everything, but there are exceptions. I also thought about 
a version that let you specify the words you wanted reduced (reduce-only 
series words), and would do a deep reduce, then RT added /only, which 
works backwards from that, so I thought my idea would be confusing.
Gabriele:
22-Aug-2006
i.e. insert series value is like  series.insert(value) in oop languages.
JaimeVargas:
22-Aug-2006
Humm. I don't like it. It violates  the contract for REPEAT.

USAGE:
   
	 REPEAT 'word value body

 

DESCRIPTION:
     
	Evaluates a block a number of times or over a series.
	REPEAT is a native value

.

ARGUMENTS:
	word -- Word to set each time (Type: word)
     

 value -- Maximum number or series to traverse (Type: integer series)
 
  ;;;;; This part of the contract is being broken by the example. 
  
	body -- Block to evaluate each time (Type: block)
Oldes:
31-Aug-2006
I think that thw word GLUE would be better for joining objects together, 
than joining series like strings
JaimeVargas:
31-Aug-2006
concatenate: 
verb [ trans. ] formal or technical 
link (things) 
together in a chain or series : some words may be concatenated, such 
that certain sounds are omitted.
BrianH:
1-Sep-2006
Volker, joins don't return strings all of the time, they return series. 
If the first value is a series, the result will be a series of the 
same type. Since your urls there are series types, join will join 
them as-is.
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
]
JaimeVargas:
1-Sep-2006
BTW not using the /copy is not changing the series directly.
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
]
BrianH:
1-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: either series? local: first data [copy local] [form local]

    while [not empty? data: next data] either any-string? local [pick 
    [

        [local: insert local reduce [delimiter {"} first data {"}]]
        [local: insert insert local delimiter first data]
    ] quoted] [pick [
        [local: insert insert/only local delimiter first data]
        [local: insert insert local delimiter first data]
    ] only]
    head local
]
Anton:
2-Sep-2006
I agree that conjoin should keep the type of series, as rejoin does, 
not just create strings.
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]]
BrianH:
6-Sep-2006
Anton, I put the data argument first on purpose, to make the function 
fit in with the standard function argument order of series functions 
in REBOL.
BrianH:
7-Sep-2006
The series function standard is
    function data-to-be-operated-on modfier-arguments

That's what I used with conjoin. It was also intentional that the 
data block not be reduced by conjoin. I see conjoin as an operation 
that you pipe data through, like utilities on Unix. If you want the 
data reduced, go ahead and do so - if not, don't.
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
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
]
Anton:
8-Sep-2006
Brian:

The series function standard is
    function data-to-be-operated-on 
modfier-arguments

Yes I understand, but this standard doesn't make sense to me. For 
comparison my preferred pattern is:
    function smaller-argument larger-argument
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
]
Ladislav:
5-Oct-2006
anybody able to find good  names for zero-based index series functions 
like variants of PICK, POKE, etc...?
Tomc:
5-Oct-2006
yes   get/set  for a   0 based series seems reasonable at the moment
Volker:
5-Oct-2006
can it be a long name?
  pick-before series 27
is what it does.
Gabriele:
25-Jan-2007
eg: append: func [series value /only /etc] [series: tail series head 
apply :insert [series value only etc]]
Volker:
26-Jan-2007
apply and refinements - in Gbriele  example  refinementsare handled 
like normal variables.

 append: func [series value /only /etc] [series: tail series head 
 apply :insert [series value only etc]]
Here they get their values by position.
Geomol:
10-Feb-2007
Actually we're already used to the way INC/DEC would work, just with 
other datatypes. If I wanna sort a series, I e.g. write:

>> blk: [3 5 2]
>> sort blk
== [2 3 5]
>> blk
== [2 3 5]


The block is changed directly by the sort command (function). Without 
this mechanism, I would have to write:

>> blk: sort blk

In this regard, it makes very much sense to be able to write:

>> a: 4
>> inc a
== 5
>> a
== 5
Geomol:
10-Feb-2007
A function increasing something by 2, which can handle direct values 
and words holding values and series, today have to be something like:

inc2: func ['value] [
	either word? value [
		either series? get value [
			set value skip get value 2
		][
			set value (get value) + 2
		]
	][
		value + 2
	]
]

With set-word arguments, it might be:

inc2: [value:] [
	either series? value [
		skip value 2
	][
		value + 2
	]
]

With INC, it could be:

inc2: [value] [inc inc value]


Maybe an increase function taking two arguments should be native 
too (like INC and DEC):

increase value 2


All these are just ideas to think about, when you guys create REBOL3.
Maxim:
11-Feb-2007
lad: a reference to a number is a common usage term which means get 
the pointer to the memory area where the number is contained... not 
the value at that pointer.  in C series variables have to be pointers, 
but numbers aren't usually pointers.  thus the reference to that 
number is its pointer.
Maxim:
11-Feb-2007
so I guess in your terminology, only series can be "references" in 
rebol right?
Ladislav:
11-Feb-2007
series can be references
 - actually not
Geomol:
12-Feb-2007
Initially I'll suggest these of type action! to accept 'arguments:
abs, back, complement, head, negate, next, tail
Maybe also: first, second, ...

And what if SORT was changed, so it both took arguments as today, 
but also lit-words, and only change the series, if it got a lit-word? 
Same with TRIM.
Maxim:
13-Feb-2007
geomol and others...  INC with lit-words is seriously flawed in actual 
use ... a: inc a  ?? what's the point of it...


lit-words are not word values they are labels, they are not usable 
unless the word exists "somewhere else"  its not THE a you are evaluating 
but AN a somewhere... which is why this is as alien to rebol as anywhere 
else.


if all series can change values "in-place" like append... why not 
allow this for scalars (and others) too?  its already an integral 
part of REBOL ... I don't see the "confusion" in   INC a   changing 
THE a... its exactly like  append a, but for another type... hell, 
I've wanted in-place editing for many things which aren't series 
and it would speed up code, just like not having to copy series all 
the time like python. 

ADD-TO a 10


when you do INC 'a  you HAVE to declare 'A somewhere else... which 
is not in rebol's philosphy.  this is completely different thinking 
to rebol... its much closer to C style... where you expect a to exist 
somewhere...    the lit word syntax, just cause a big confusion within 
the normal chain of rebol coding IMHO its not simple, and certainly 
not obvious... most newbies don't even get what a lit-word is.  just 
like SET which is used only (usually) to implement other tricks in 
the language... we shouldn't be using SET in normal code.  INC is 
not a trick word... its something I'd be using in many scripts, unlike 
SET which I seldom need to.  

just giving my view on this topic.  ;-)
BrianH:
13-Feb-2007
Well, because only series, any-word and object types have internal 
state that could be changed.
Group: !Cheyenne ... Discussions about the Cheyenne Web Server [web-public]
BrianH:
13-May-2008
Watch out with EXTRACT: There is a bug in the 2.7.6 version with 
binary values that was fixed, but the fix never made it into 2.7.6. 
You can get the working version from DevBase r2-mezz-series #396.
Dockimbel:
7-Nov-2008
Are you directly modifying the response/buffer series somehow ? Are 
you using 'on-status-code keyword ?
CharlesW:
4-Dec-2008
A colleague of mine showed me an Object Relational Mapping product 
that generates a series of DLL for .net. (Abstracts the database 
tables as objects with methods for inserts, updates, deletes, joins, 
etc..) I don't know if I am a fan of such a tool but I was wondering 
if anyone is doing something similar with rebol or if this type of 
functionality is built in Cheyenne. Is it possible to provide abstraction 
of the databases in Cheyenne using a series of RSP's, web services, 
ORM technology? What's the best approach for enterprise portal development 
with Rebol?
Graham:
14-Feb-2009
I've used YUI with Cheyenne before ... but am now looking at a different 
Javascript library.

jQuery seems to have a lot of traction, and there is this great set 
of introductory videos on how to use it http://nettuts.com/articles/web-roundups/jquery-for-absolute-beginners-video-series/
BrianH:
2-Apr-2009
2/4-22:54:04.266-## Error in [uniserve] : On-received call failed 
with error: make object! [
    code: 303
    type: 'script
    id: 'expect-arg
    arg1: 'insert
    arg2: 'series
    arg3: [series! port! bitset!]
    near: [insert/part tmp/port s skip e]
    where: 'process-bounded-content
] !
BrianH:
3-Apr-2009
Same error after upgrading Chromium, here's the verbose 5 log of 
the request:


3/4-01:38:00.891-[HTTPd] ================== NEW REQUEST ==================

3/4-01:38:01.531-[HTTPd] Request Line=>POST /ecg/blah.rsp HTTP/1.1

3/4-01:38:02.109-[HTTPd] Trying phase method-support ( mod-static 
)

3/4-01:38:02.828-[HTTPd] Trying phase url-translate ( mod-static 
)
3/4-01:38:03.062-[uniserve] Calling >on-received< with {^M
Host: localhost:8080^M
Connection: keep-alive^M
Us}
3/4-01:38:03.547-[HTTPd] Request Headers=>
Host: localhost:8080
Connection: keep-alive

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 
(KHTML, like Gecko) Chrome/2.0.173.0 Safari/530.5
Referer: http://localhost:8080/ecg/blah.html
Content-Length: 153149
Cache-Control: max-age=0
Origin: http://localhost:8080

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryEv3SZArZWdjyznJZ

Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,bzip2,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3



3/4-01:38:03.797-[HTTPd] Trying phase url-to-filename ( mod-alias 
)
3/4-01:38:04.031-[HTTPd] => request processed
3/4-01:38:04.766-[HTTPd] Trying phase url-to-filename ( mod-rsp )
3/4-01:38:05-[HTTPd] => request processed

3/4-01:38:05.469-[HTTPd] Trying phase url-to-filename ( mod-internal 
)

3/4-01:38:05.719-[HTTPd] Trying phase url-to-filename ( mod-static 
)
3/4-01:38:05.969-[HTTPd] => request processed

3/4-01:38:06.453-[uniserve] >> Port: 3789, low-level reading: 17520

3/4-01:38:06.703-[uniserve] >> Port: 3789, low-level reading: 17520

3/4-01:38:06.953-[uniserve] >> Port: 3789, low-level reading: 17520

3/4-01:38:07.437-[uniserve] >> Port: 3789, low-level reading: 17520

3/4-01:38:07.906-[uniserve] >> Port: 3789, low-level reading: 19980

3/4-01:38:08.391-[uniserve] Calling >on-received< with "------WebKitFormBoundaryEv3SZArZWdjyznJZ^M^/Content-"

3/4-01:38:08.875-[uniserve] >> Port: 3789, low-level reading: 16680

3/4-01:38:09.344-[uniserve] >> Port: 3789, low-level reading: 17520

3/4-01:38:09.844-[uniserve] >> Port: 3789, low-level reading: 17520

3/4-01:38:10.312-[uniserve] >> Port: 3789, low-level reading: 1149

3/4-01:38:10.797-[uniserve] Calling >on-received< with {037.17923" 
"4429 SUNNYSLOPE RD SW" "Port Orchard" }

3/4-01:38:11.266-## Error in [uniserve] : On-received call failed 
with error: make object! [
    code: 303
    type: 'script
    id: 'expect-arg
    arg1: 'insert
    arg2: 'series
    arg3: [series! port! bitset!]
    near: [insert/part tmp/port s skip e]
    where: 'process-bounded-content
] !
3/4-01:38:11.734-[uniserve] Port closed : 127.0.0.1
401 / 15311234[5] 67...1213141516