Mailing List Archive: 49091 messages

# Combinations of things (small puzzler)

### [1/9] from: joel:neely:fedex at: 20-Oct-2001 16:06

I'm a bit puzzled about the difference in behavior between REPEAT var blockexpression and REPEAT var numericexpression as illustrated by the following little story. It's not clear to me whether this is an inconsistency or a bug. I have a small collection of some things: some-things: ["camel" "lemur" "mouse"] I'd like to print all possible combinations of three of these things (allowing replacement between selections). any3: function [ things [block!] ][ temp ][ temp: array 3 repeat item things [ temp/1: item repeat item things [ temp/2: item repeat item things [ temp/3: item print temp ] ] ] ] which behaves as expected:
>> any3 some-things
camel camel camel camel camel lemur camel camel mouse camel lemur camel camel lemur lemur camel lemur mouse camel mouse camel camel mouse lemur camel mouse mouse lemur camel camel lemur camel lemur lemur camel mouse lemur lemur camel lemur lemur lemur lemur lemur mouse lemur mouse camel lemur mouse lemur lemur mouse mouse mouse camel camel mouse camel lemur mouse camel mouse mouse lemur camel mouse lemur lemur mouse lemur mouse mouse mouse camel mouse mouse lemur mouse mouse mouse
>>
Of course, that function is specialized to picking exactly 3 at a time, which I can overcome with a little recursion. anyn: function [ n [integer!] things [block!] ][ temp ][ temp: array n do .anyn: func [ i [integer!] n [integer!] b [block!] ][ either i > n [ print b ][ repeat item things [ poke b i item .anyn i + 1 n b ] ] ] 1 n temp ] which allows me to say
>> anyn 3 some-things
camel camel camel camel camel lemur camel camel mouse ... and so forth, until ... mouse mouse camel mouse mouse lemur mouse mouse mouse
>>
Now, REPEAT is supposed to be able to step through either the values in a block (for a block argument) or the integers 1 through some limit (for an integer argument). Let's rework ANY3 to use an "indexing" strategy. any-3: function [ things [block!] ][ temp len ][ temp: array 3 len: length? things repeat i len [ temp/1: things/:i repeat i len [ temp/2: things/:i repeat i len [ temp/3: things/:i print temp ] ] ] ] Now, please notice that -- up to this point -- it hasn't mattered that each use of REPEAT in a single solution operates on the same word. But when we try to generalize ANY-3 to make a variable number of selections from our list of some things ... any-n: function [ n [integer!] things [block!] ][ temp len .any-n ][ temp: array n len: length? things do .any-n: func [ p [integer!] n [integer!] b [block!] ][ either p > n [ print b ][ repeat i len [ poke b p things/:i .any-n p + 1 n b ] ] ] 1 n temp ] ... we get a surprise!
>> any-n 3 some-things
camel camel camel camel camel lemur camel camel mouse camel none camel camel none lemur camel none mouse camel none camel camel none lemur camel none mouse none camel camel none camel lemur none camel mouse none none camel none none lemur none none mouse none none camel none none lemur none none mouse none camel camel none camel lemur none camel mouse none none camel none none lemur none none mouse none none camel none none lemur none none mouse
>>
If we get those pesky things out of the way, and just look at the indices ... any-n-dices: function [ n [integer!] things [block!] ][ temp len .any-n ][ temp: array n len: length? things do .any-n-dices: func [ p [integer!] n [integer!] b [block!] ][ either p > n [ print b ][ repeat i len [ poke b p i .any-n-dices p + 1 n b ] ] ] 1 n temp ] ... we see this...
>> any-n-dices 3 some-things
1 1 1 1 1 2 1 1 3 1 4 1 1 4 2 1 4 3 1 4 1 1 4 2 1 4 3 4 1 1 4 1 2 4 1 3 4 4 1 4 4 2 4 4 3 4 4 1 4 4 2 4 4 3 4 1 1 4 1 2 4 1 3 4 4 1 4 4 2 4 4 3 4 4 1 4 4 2 4 4 3
>>
... which shows that there appears to be an interaction between the values of the controlled word at different levels of recursive evaluation, which didn't appear to happen when REPEAT was given a block of values. The obvious work-around is to use an explicit FOR loop (or WHILE) ... for-any-n-dices: function [ n [integer!] things [block!] ][ temp len .for-any-n ][ temp: array n len: length? things do .for-any-n-dices: func [ p [integer!] n [integer!] b [block!] ][ either p > n [ print b ][ for i 1 len 1 [ poke b p i .for-any-n-dices p + 1 n b ] ] ] 1 n temp ] ... which behaves as expected ...
>> for-any-n-dices 3 some-things
1 1 1 1 1 2 1 1 3 1 2 1 1 2 2 1 2 3 1 3 1 1 3 2 1 3 3 2 1 1 2 1 2 2 1 3 2 2 1 2 2 2 2 2 3 2 3 1 2 3 2 2 3 3 3 1 1 3 1 2 3 1 3 3 2 1 3 2 2 3 2 3 3 3 1 3 3 2 3 3 3
>>
... but this certainly violates the expectation that ... REPEAT var number ... and ... FOR var 1 number 1 ... are equivalent REBOL phrases. Sooooooo... Have I missed something in the documentation somewhere? Note that the right number of lines get printed in all cases, it's just that the contents are goofy for recursive invocations of REPEAT with a numeric second argument. -jn- -- ; sub REBOL {}; sub head (\$) {@_[0]} REBOL [] # despam: func [e] [replace replace/all e ":" "." "#" "@"] ; sub despam {my (\$e) = @_; \$e =~ tr/:#/.@/; return "\n\$e"} print head reverse despam "moc:xedef#yleen:leoj" ;

### [2/9] from: lmecir:mbox:vol:cz at: 21-Oct-2001 0:55

Hi Joel, the cause of REPEAT is exactly the same as the case of USE or MAKE OBJECT!. I described this behaviour in the Ref-Words application you can launch from the DOCS folder in the View Desktop. Cheers Ladislav

### [3/9] from: g:santilli:tiscalinet:it at: 21-Oct-2001 12:18

Hello Joel! On 20-Ott-01, you wrote: JN> Sooooooo... Have I missed something in the documentation JN> somewhere? Note that the right number of lines get printed in JN> all cases, it's just that the contents are goofy for JN> recursive invocations of REPEAT with a numeric second JN> argument. It looks like REPEAT does something like: repeat: func ['word value body] [ either series? value [ ... ... bind/copy body word ... ... ] [ ... ... bind body word ... ... ] ] (I think you get the idea...) Indeed, any-n-dices: function [ n [integer!] things [block!] ][ temp len .any-n ][ temp: array n len: length? things do .any-n-dices: func [ p [integer!] n [integer!] b [block!] ][ either p > n [ print b ][ repeat i len copy [ poke b p i .any-n-dices p + 1 n b ] ] ] 1 n temp ] produces:
>> some-things: ["camel" "lemur" "mouse"]
== ["camel" "lemur" "mouse"]
>> any-n-dices 3 some-things
1 1 1 1 1 2 1 1 3 1 2 1 1 2 2 1 2 3 1 3 1 1 3 2 1 3 3 2 1 1 2 1 2 2 1 3 2 2 1 2 2 2 2 2 3 2 3 1 2 3 2 2 3 3 3 1 1 3 1 2 3 1 3 3 2 1 3 2 2 3 2 3 3 3 1 3 3 2 3 3 3 Sounds like something to report to feedback! Regards, Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/

### [4/9] from: rotenca:telvia:it at: 21-Oct-2001 23:47

Ciao Gabriele, I am not sure you are right, when you say:
> It looks like REPEAT does something like: > repeat: func ['word value body] [
<<quoted lines omitted: 6>>
> ... bind body word ... > ...
It seemes to me that repeat never make a copy of body:
>> x: copy [probe i]
== [probe i]
>> repeat i [1 2 3] x
1 2 3 == 3
>> print get second x
3
>> x: copy [probe i]
== [probe i]
>> repeat i 3 x
1 2 3 == 3
>> print get second x
4 --- Ciao Romano

### [5/9] from: joel:neely:fedex at: 22-Oct-2001 9:48

> the cause of REPEAT is exactly the same as the case of USE or > MAKE OBJECT!. I described this behaviour in the Ref-Words > application you can launch from the DOCS folder in the View > Desktop. >
Sorry for the delay in responding... I was View-less for a while (running on a box that only had Core, and didn't want to overlay that with View). The issue I was asking about was not the fact that REPEAT has an effect on its third argument, but that its behavior is different depending on the type of the second argument. -jn- -- This sentence contradicts itself -- no actually it doesn't. -- Doug Hofstadter joel<dot>neely<at>fedex<dot>com

### [6/9] from: rotenca:telvia:it at: 22-Oct-2001 20:12

Ciao Gabriele
> It looks like REPEAT does something like: > repeat: func ['word value body] [
<<quoted lines omitted: 8>>
> ] > ]
I have checked the version of anyn with series instead of number, and also that version requires a copy. The problem only seems not to exists but it is the same... --- Ciao Romano

### [7/9] from: lmecir:mbox:vol:cz at: 22-Oct-2001 22:13

Aha, ...skip...
> The issue I was asking about was not the fact that REPEAT has an > effect on its third argument, but that its behavior is different
<<quoted lines omitted: 4>>
> -- Doug Hofstadter > joel<dot>neely<at>fedex<dot>com
That is not correct, the behaviour of REPEAT is exactly the same - REPEAT modifies its second argument. The difference in your code was, that 'item in the case of (repeat item [1 2 3] [...]) did not have the same responsibility as 'i in the case of (repeat i 3 [...]). Here is a code that can show some similarity: recursive: func [x] [ repeat i x [ if x = 1 [ print ["X:" x "I before recursive call: " i] recursive 2 print ["X:" x "I after recursive call: " i] ] ] ] recursive 1
>> recursive 1
X: 1 I before recursive call: 1 X: 1 I after recursive call: 3 blk-recursive: func [x] [ repeat i x [ if (length? x) = 1 [ print ["X:" mold x "I before recursive call: " i] blk-recursive [1 2] print ["X:" mold x "I after recursive call: " i] ] ] ] blk-recursive [1]
>> blk-recursive [1]
X: [1] I before recursive call: 1 X: [1] I after recursive call: 2 Cheers Ladislav

### [8/9] from: lmecir:mbox:vol:cz at: 22-Oct-2001 22:29

Hi myself, ..
> That is not correct, the behaviour of REPEAT is exactly the same - REPEAT > modifies its second argument
cannot count to three properly, I wanted to say, that REPEAT modified the BODY argument, sorry.

### [9/9] from: g:santilli:tiscalinet:it at: 22-Oct-2001 19:47

Hello Romano! On 21-Ott-01, you wrote: RT> It seemes to me that repeat never make a copy of body: I didn't test it actually, I just based my observation on what reported by Joel... Regards, Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/

Notes
• Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted