Home   Archive   Permalink



One liner does the unexpected (because I'm new?)

f:
Is a list of first names
l:
Is a list of last names
    
>> append voters join pick f random length? "+" f pick l random length? l
** Script Error: John has no value
** Where: repend
** Near: John
David
Michael
Chris
Mike
    
Without the "+"
    
>> append voters join pick f random length? f pick l random length? l
== ["PaulBouck" "JoanneRodriguez" "CarolLerner" "ChrisRodriguez" "AliceGriffin" "JamesLerner"]
    
What I need is to join a "+" between the first and last name.
I will clean this up... I was just playing with what can be done in one line 'without' compose.
    
It also brings up the question: Does REBOL has a function like ruby's Array#Zip ?
    
x: [2 4 6 8]
y: [1 3 5 7]
    
z: zip y x
== [1 2 3 4 5 6 7 8]
    
    


posted by:   Gus (gt)     7-Aug-2013/20:25:33-7:00



OOPS...
noticed the typo.
    
The unexpected is this:
    
>> append voters join pick f random length? f "+" pick l random length? l
== Griffin
>> voters
== ["Betty+"]

posted by:   Gus (gt)     7-Aug-2013/20:27:40-7:00



haha!
join join
    
That's cute :)
    
append voters join join pick f random length? f "+" pick l random length? l
    
== ["Daniel+Johnson" "Mark+Garcia" "Erica+Lerner" "Erica+Case"]
    
lol

posted by:   Gus (gt)     7-Aug-2013/20:30:04-7:00



There are some functions to do that:
    
b: ["one" "two" "three"]
rejoin b
;== "onetwothree"
reform b
;== "one two three"
ajoin b
;== "onetwothree"
    
So you can do that:
reform ["one" "+" "two"]
;== "one + two"
    
join "one" "+"
;== "one+"
    
etc.

posted by:   Endo     8-Aug-2013/10:45:17-7:00



Here I wrote a MERGE function which merges the given block:
    
merge: func [
     "Merge a block using a delimiter. Default is coma."
     b [block!] "Block to merge."
     /with c [char! string! none!] "Delimiter char or string."
     /tab "Merge with tab (shortcut)"
][
     if empty? b [return copy ""]
     c: to-string any [c if tab ["^-"] ","]
     head clear skip foreach x b [insert tail s: "" join form x c] negate length? c
]
    
merge/with b " + "
;== "one + two three"
    
merge b
;==one,two,three


posted by:   Endo     8-Aug-2013/10:47:01-7:00



REBOL needs a built in function that interleaves two blocks.
It doesn't sound that useful, but it's surprising how handy it is to have.
Called "zip" in python or ruby.
    
Or "zip_ with"


posted by:   Gus     8-Aug-2013/13:21:04-7:00



You can simply use APPEND,
    
     x: [1 2 3]
     y: [4 5 6]
     append x y
;== [1 2 3 4 5 6]
Notice that it modifies X.
if you don't want to modify X then you should COPY it:
     append copy x y
    
One last thing, you don't need to "pick random x 1"
You can simply use RANDOM/ONLY
    
     random/only [1 2 3 4]
     ;==3
    


posted by:   Endo     8-Aug-2013/18:43:12-7:00



Endo, you are the best

posted by:   Gus     8-Aug-2013/20:12:29-7:00



Theoretically it would work like this.
    
x: [1 3 21 32]
y: [blue red cow water]
    
    
zip x y
;== [1 blue 3 red 21 cow 32 water]
    
zip y x
;== [blue 1 red 3 cow 21 water 32]
    
You're still the best :)
    
Thanks for the replies.

posted by:   Gus     8-Aug-2013/21:43:39-7:00



R E B O L []
    
zip: func [b1 b2 /local temp] [
     temp: copy []
     repeat x max length? b1 length? b2 [
         if not none = f1: pick b1 x [append temp f1]
         if not none = f2: pick b2 x [append temp f2]
     ]
     temp
]
    
    
probe zip [1 2 3] [4 5 6 7]
probe zip [4 5 6 7] [1 2 3]
probe zip system/locale/months system/locale/days
probe zip system/locale/days system/locale/months
halt

posted by:   Nick     11-Aug-2013/7:48:07-7:00



Hey Nick, that's pretty clean looking.
Why do you add halt at the end of your scripts?

posted by:   Gus     11-Aug-2013/19:36:08-7:00



Just in case someone tries to paste the code into a text file and run by double clicking the icon, run from REBOL's text editor, etc. If you run from a script file (as opposed to pasting directly into REBOL's console), the program will run and close, before you have time to see the results. I've had so many people over the years contact me about scripts "not running" properly, that I now just toss that in by default :)

posted by:   Nick     12-Aug-2013/9:49:10-7:00



Here I a little bit improved Nick's ZIP function,
    
     zip: func [
         "Combine two blocks" b1 [block!] b2 [block!]
         /pad "Include none values" /local temp
     ] [
         temp: copy []
         repeat x max length? b1 length? b2 [
             if any [
                 f1: pick b1 x
                 pad
                 not tail? at b1 x
             ] [append temp f1]
             if any [
                 f2: pick b2 x
                 pad
                 not tail? at b2 x
             ] [append temp f2]
         ]
         temp
     ]
    
Nick's version was not safe if there is none values inside the blocks, none values was not included in the result block anyway:
    
Here are some test:
     x: compose [1 2 3 (none)]
     y: compose [(none) a b c d e] ;notice that none values!
    
;Nick's version;
     >> zip x y
     == [1 2 a 3 b c d e] ;none values removed
    
The version above;
     >> zip x y
     == [1 none 2 a 3 b none c d e]
    
And I've added /pad refinement to be able to combine even if one of the blocks has more item than the other.
    
     >> zip/pad x y
     == [1 a 2 b 3 c none d none e]
    
So the result block has always even number of values, safe to use with FOREACH:
    
     FOREACH [a b] zip x y []
    
     >> zip [1 2] [a]
     == [1 a 2]
     >> zip/pad [1 2] [a]
     == [1 a 2 none]
     >> zip/pad [] [a]
     == [none a]
    
Credit goes to Nick, I just improved a bit.


posted by:   Endo     13-Aug-2013/8:11:52-7:00



Oh f1 and f2 should be added to /local
zip: func [
    "Combine two blocks" b1 [block!] b2 [block!]
    /pad "Include none values" /local temp f1 f2
] [...]

posted by:   Endo     13-Aug-2013/8:14:07-7:00



By the way it would be nice try to write a ZIP function to combine *any* number of blocks.
Something like:
    
x: [1 2] y: [a b c] z: [p q]
>> zip reduce [x y z]
== [1 a p 2 b q none c none]


posted by:   Endo     13-Aug-2013/8:24:47-7:00



I'd imagine you would have to have,
[blks [block!]]
    
Then set your locals 'f join index of each block within the blks block.
    
JavaScript is one language where it doesn't care how many args you supply to a function, and you see a common for loop pattern used to handle the arg count supplied.
In REBOL, I suspect you might use length? And check if its not at the end of the arg list. ?


posted by:   Gus     16-Aug-2013/18:14:51-7:00



In Rebol we usually use one (reduced) block argument to supply any number of arguments for a function:
    
     f: func [b [block!] "Block of arguments (reduced)"] [
         foreach v reduce b [probe v]
     ]
    
So we can use it as below:
    
     >> a: 5 b: "x" c: [a]
     >> f [a b c]
    
And sometimes it is better to use COMPOSE instead of REDUCE:
     f: func [b [block!] "Block of arguments (reduced)"] [
         foreach v compose/only b [probe v]
     ]
    
So you can use it like:
     >> a: 5 b: "x" c: [a]
     >> f [a (b) c]
     == a "x" c ;note that only B evaluated

posted by:   Endo     27-Aug-2013/4:33:46-7:00



Here's a repost from my answer in the "function arity" topic, along the same lines. This allows you to have any number of arguments lists, each with any number of items:
    
myFunc: func [blks] [
     foreach blk blks [
         count: 1
         foreach b blk [
             print rejoin [
                 "Item #" count " in " mold blk ": "
             ]
             ++ count
         ]
     ]
]
    
myFunc [[1 2 3] [x y z] [2 4 6]] halt

posted by:   Nick     28-Aug-2013/13:06:30-7:00



Here's a repost from my answer in the "function arity" topic, along the same lines. This allows you to have any number of arguments lists, each with any number of items:
    
myFunc: func [blks] [
     foreach blk blks [
         count: 1
         foreach b blk [
             print rejoin [
                 "Item #" count " in " mold blk ": "
             ]
             ++ count
         ]
     ]
]
    
myFunc [[1 2 3] [x y z] [2 4 6]] halt

posted by:   Nick     28-Aug-2013/13:06:33-7:00