I'm trying to copy binary data to an array, and I'm getting a result I don't expect. I reduced it to this smaller problem that demonstrates it.
b: #{0102030405060708}
c: array (length? b)
repeat num (length? b) [
print [
{Setting location}
num
{to value of}
to-binary reduce [(pick b num)]
]
poke c num (to-binary reduce [(pick b num)])
]
This results in:
Setting location 1 to value of #{01}
Setting location 2 to value of #{02}
Setting location 3 to value of #{03}
Setting location 4 to value of #{04}
Setting location 5 to value of #{05}
Setting location 6 to value of #{06}
Setting location 7 to value of #{07}
Setting location 8 to value of #{08}
== #{08}
>> c
== [#{08} #{08} #{08} #{08} #{08} #{08} #{08} #{08}]
I can see that I am returning the ==#{08}
with my repeat block, but I don't konw where that is coming from. I checked with trace on
and it seems that the poke statement is setting all elements of the block at every step of the repeat. This seems to be a pointer issue and I can resolve it with copy
. Can someone give me an idea of what is happening?
Some more tests:
>> to-binary reduce [pick b 1]
== #{01}
>> poke c 1 to-binary reduce [pick b 1]
== #{01}
>> c
== [#{01} #{01} #{01} #{01} #{01} #{01} #{01} #{01}]
>> poke c 2 #{02}
== #{02}
>> c
== [#{01} #{02} #{01} #{01} #{01} #{01} #{01} #{01}]
>> u: to-binary reduce [pick b 4]
== #{04}
>> poke c 4 u
== #{04}
>> c
== [#{04} #{02} #{04} #{04} #{04} #{04} #{04} #{04}]
Response to Ladislavs answer:
Thank you for the answer about the bug.
The first example gives a different result than what I am expecting. The binary elements are each of 8 length, whereas I was interested in length 1 (hence the use of the block argument to to-binary
. )
>> c
== [#{0000000000000001} #{0000000000000002} #{0000000000000003} #{0000000000000004} #{0000000000000005} #{0000000000000006} #{0000000000000007} #{0000000000000008}]
The second works, by replacing c: array (length? b)
with c: copy []
You encountered a known bug. (the correcting pull request has already been submitted, AFAIK) The workaround is to never use a block as an argument of the to-binary function. The following code should work:
b: #{0102030405060708}
c: array (length? b)
repeat num (length? b) [
print [
{Setting location}
num
{to value of}
to-binary pick b num
]
poke c num to-binary pick b num
]
However, the whole code looks overcomplicated to me, and I would rather achieve your goal using:
b: #{0102030405060708}
c: make block! length? b
repeat num (length? b) [
print [
{Setting location}
num
{to value of}
copy/part at b num 1
]
append c copy/part at b num 1
]
If you want just to create a short (length 1) binary from an integer, you may use this formula:
append copy #{} 255