On 5/10/06, Gregg Irwin <[EMAIL PROTECTED]> wrote:
>
> Hi All!
>
> I've posted this before--never got much response--but I'll try again,
> since I really want to pester Carl to add something like this to R3 if
> others think it would be useful.
>
> What is it?
>
>      A function to collect values into a block, so you can avoid the
>      local/copy/append/return dance in functions. e.g.
>
>      fn: func [series /local res] [
>          res: copy []
>          foreach val series [append res val]
>          res
>      ]
>
>      It was inspired by Brett Handley and Romano Paolo Tenca. I just
>      came up with a different approach that worked better for me.
>

I like that topic. Hard to find the one true universal solution. :)

> How does it work?
>
>     It takes a word and a block as arguments. Anytime the word appears
>     as a set-word! in the block, the value assigned to it is
>     "collected".
>
>     The above func would look like this:
>
>     fn: func [series] [
>         collect v [foreach val series [v: val]
>     ]
>

Looks good.

> Why bother?
>
>     1) It reduces tedious code.
>
>     2) It makes it clear that you're collecting values.
>

[rebol []
    {
Once i used this, its inspired by Carl convention to use 'emit,
and is short:
}
    collect: func [out code /local emit] [
        emit: func [val] [
            repend out val
        ]
        do bind code 'local
    ]
    probe collect copy [] [
        foreach val [1 2 3 4] [
            emit val * 2
        ]
    ]
    {
Now i prefer something like this
(interface debatable, quick patch of forskip. How about [val series body] ?=
):
}
    change-each: func [
        [throw catch] 'word [word!] body [block!] /local orig result
    ] [
        if not any [
            series? get word
            port? get word
        ] [throw make error! {change-each expected word argument to
refer to a series or port
!}]
        orig: get word
        while [not tail? get word] [
            change/only get word do body
            set word next get word
        ]
        set word orig
    ]
    data: copy [1 2 3 4]
    probe change-each data [
        data/1 * 2
    ]
    ?? data
{
But adds only one value per loop, while the other version , like yours, all=
ows
 collect[emit [<html><body>] foreach val data[emit val] emit [</body></html=
>]]
}
    wait 4 quit
]
> What are the downsides?
>
>     It's a subtle dialect that overrides the meaning of set-words.
>     (I've been using it for quite a while now, so I can't judge how
>     unnatural it feels to others)
>

Thats one reason to use 'emit instead of set-words.

> Where's the code?
>
>     collect: func [
>         [throw]
>         {Collects block evaluations.}
>         'word "Word to collect (as a set-word! in the block)"
>         block [any-block!] "Block to evaluate"
>         /into dest [series!] "Where to append results"
>         /only "Insert series results as series"
>         /local code marker at-marker? marker* mark replace-marker rules
>     ] [
>         block: copy/deep block
>         dest: any [dest make block! []]
>         ; "not only" forces the result to logic!, for use with PICK.
>         ; insert+tail pays off here over append.
>         ; FIRST BACK allows pass-thru assignment of value.
>         code: compose [first back (pick [insert insert/only] not only) ta=
il dest]
>         marker: to set-word! word
>         at-marker?: does [mark/1 =3D marker]
>         ; We have to use change/part since we want to replace only one
>         ; item (the marker), but our code is more than one item long.
>         replace-marker: does [change/part mark code 1]
>         marker*: [mark: set-word! (if at-marker? [replace-marker])]
>         parse block rules: [any [marker* | into rules | skip]]
>         do block
>         head :dest
>     ]
>
> Got any examples?
>
>         collect zz []
>         collect zz [repeat i 10 [if (zz: i) >=3D 3 [break]]]
>         collect zz [repeat i 10 [zz: i  if i >=3D 3 [break]]]
>         collect zz [repeat i 10 [either i <=3D 3 [zz: i][break]]]
>         dest: copy []
>         collect/into zz [repeat n 10 [zz: n * 100]] dest
>         collect zz [for i 1 10 2 [zz: i * 10]]
>         collect zz [for x 1 10 1 [zz: x]]
>         collect zz [foreach [a b] [1 2 3 4] [zz: a + b]]
>         collect zz [foreach w [a b c d] [zz: w]]
>         collect zz [repeat e [a b c %.txt] [zz: file? e]]
>         iota: func [n [integer!]][collect zz [repeat i n [zz: i]]]
>         iota 10
>         collect zz [foreach x first system [zz: to-set-word x]]
>         x: first system
>         collect zz [forall x [zz: length? x]]
>         x: first system
>         collect zz [forskip x 2 [zz: length? x]]
>         collect/only zz [foreach [a b] [1 2 3 4] [zz: a zz: b zz: reduce =
[a b a + b]]]
>         collect/only zz [
>             foreach [a b] [1 2 3 4] [
>                 zz: a zz: b zz: reduce [a b a + b]
>                 foreach n reduce [a b a + b] [zz: n * 10]
>             ]
>         ]
>
>         dest: copy ""
>         collect/into zz [repeat n 10 [zz: n * 100 zz: " "]] dest
>
>         dest: copy []
>         collect/into zz [
>             foreach [num blk] [1 [a b c] 2 [d e f] 3 [g h i]] [
>                 zz: num
>                 collect/only/into yy [
>                     zz: blk
>                     foreach word blk [zz: yy: num  yy: word]
>                     yy: blk
>                 ] dest
>             ]
>         ] dest
>
> Comments?
>
>     This is where you come in.
>
>     Is it something worth asking RT to include?
>
>     How could it be improved?
>
>
> -- Gregg
>
> --
> To unsubscribe from the list, just send an email to
> lists at rebol.com with unsubscribe as the subject.
>
>


--=20
-Volker

"Any problem in computer science can be solved with another layer of
indirection. But that usually will create another problem." David
Wheeler
-- 
To unsubscribe from the list, just send an email to 
lists at rebol.com with unsubscribe as the subject.

Reply via email to