r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[Core] Discuss core issues

BrianH
28-Oct-2011
[2485x6]
Only one level, or all the way?
Also, in-place or as a copy?
>> a: [[1][2][3][[4]]]
== [[1] [2] [3] [[4]]]

One level:

>> b: copy a while [not tail? b] [either block? first b [b: change 
b first b] [++ b]] b: head b
== [1 2 3 [4]]

All levels (not cyclic reference safe):

>> b: copy a while [not tail? b] [either block? first b [change b 
first b] [++ b]] b: head b
== [1 2 3 4]
ChristianE's ODBC extension for R3 includes a native FLATTEN command, 
but I haven't tested whether or not it manages memory properly, and 
it doesn't help R2, or R3 not on Windows.
Using R3 PARSE:
>> b: copy a parse b [any [change [set x block!] x | skip]] b
== [1 2 3 [4]]

>> b: copy a parse b [while [and change [set x block!] x | skip]] 
b
== [1 2 3 4]
Or simpler:
>> parse copy a [return while [change [set x block!] x | skip]]
== [1 2 3 [4]]

>> parse copy a [return while [and change [set x block!] x | skip]]
== [1 2 3 4]
Sunanda
28-Oct-2011
[2491]
For some types of data (not embedded objects)
    to-block form [ .... ]
Andreas
28-Oct-2011
[2492]
in-place:
forall a [change a first a]

copying:
collect [foreach x a [keep x]]
BrianH
28-Oct-2011
[2493]
Andreas, FORALL won't work here:
>> a: [[1] [2] [3 [4]] [[5]]] forall a [change a first a] a
== [1 2 3 4]


If it's shallow, it should be [1 2 3 [4] [5]], if deep it should 
be [1 2 3 4 5].
Andreas
28-Oct-2011
[2494]
Sure, neither will it work in n other arbitrarily constructed border 
cases :)
BrianH
28-Oct-2011
[2495]
The PARSE and WHILE versions above will work in all cases where you 
don't run out of memory, and for the deep versions when there are 
no cyclic references.

>> parse [[1] [2] [3 [4]] [[5]]] [return while [change [set x block!] 
x | skip]]
== [1 2 3 [4] [5]]

>> parse [[1] [2] [3 [4]] [[5]]] [return while [and change [set x 
block!] x | skip]]
== [1 2 3 4 5]
Andreas
28-Oct-2011
[2496]
For the common flatten use-case of regular one-level nested blocks, 
it's fine. If that's not what you need, no warranties :)
BrianH
28-Oct-2011
[2497x2]
The FORALL version won't work if the embedded blocks have more than 
one element in them.
That is the common case :)
Andreas
28-Oct-2011
[2499]
True.
BrianH
28-Oct-2011
[2500x3]
It's a little better if you do this, but still not quite right:

>> a: [[1] 2 [[3] [4]] [[5]]] forall a [change/part a first a 1] 
a
== [1 2 [3] 4 [5]]  ; should be [1 2 [3] [4] [5]]
The WHILE trick above needs the same CHANGE/part (whoops):

>> b: [[1] 2 [[3] [4]] [[5]]] while [not tail? b] [either block? 
first b [b: change/part b first b 1] [++ b]] b: head b
== [1 2 [3] [4] [5]]

>> b: [[1] 2 [[3] [4]] [[5]]] while [not tail? b] [either block? 
first b [change/part b first b 1] [++ b]] b: head b
== [1 2 3 4 5]
Overall, I have to say I prefer the R3 PARSE version.
james_nak
28-Oct-2011
[2503]
Gentlemen, thank you. I will study your methods. It is just one level 
and it was to handle indexes I was receiving from a mysql db that 
were returned as [ [1] [2][ 3]]. Again thank you. You guys sure know 
your stuff!
BrianH
28-Oct-2011
[2504]
If you are copying from fixed records (as from DB results), Andreas's 
COLLECT version will use the least memory because you can preallocate:

>> a: [[1 2] [3 4] [5 6]] head collect/into [foreach x a [keep x]] 
make block! 2 * length? a
== [1 2 3 4 5 6]
james_nak
28-Oct-2011
[2505]
Brian, that reminds me. The ++ is something I have never seen before 
and it doesn't show up in the "dictionary" which is what I normally 
depend on for info. Is there some doc or source of info you recommend?
Thanks.
BrianH
28-Oct-2011
[2506]
HELP ++, or SOURCE ++ on R2.
james_nak
28-Oct-2011
[2507x3]
I mean even knowing that it exists.
collect ....Another one that is not in the dictionary
Interesting.
BrianH
28-Oct-2011
[2510]
Right, I forgot about that. There's a -- too, and other new functions 
like FIRST+ and TAKE. I tend to just do WORDS-OF lib in R3 and go 
from there. Most of the new functions in R2 in the last several years 
are backports from R3.
james_nak
28-Oct-2011
[2511x2]
Ah, that makes sense. I was just looking at R3 Collect.
Very cool thanks.
BrianH
28-Oct-2011
[2513x2]
R2's COLLECT is pretty similar. The backports try to be as compatible 
with R3 as is practical in R2, though is a couple cases they are 
a bit ahead of their R3 versions, where there are some tickets that 
haven't gone through yet. In particular ENLINE/with, DELINE block!, 
and MAP-EACH/into come to mind.
is -> in
Geomol
29-Oct-2011
[2515]
Yet an alternative:

>> load form [[1][2][3]]
== [1 2 3]
Ladislav
30-Oct-2011
[2516]
Please, do not publish such solutions, they are not recommended in 
the documentation
Geomol
30-Oct-2011
[2517]
? Are you joking?
Ladislav
30-Oct-2011
[2518]
No, that is serious
Geomol
30-Oct-2011
[2519]
Will you please point to that documentation?
Ladislav
30-Oct-2011
[2520]
Do not forget, that you destroy such properties as binding, etc.
Geomol
30-Oct-2011
[2521]
My solution works perfectly in this example, and don't tell me what 
to do or not to do.
Ladislav
30-Oct-2011
[2522x4]
OK, do whatever you want. I am changin my recommendation to: readers 
of the above, please do not use such code. Other affected datatypes 
are:

- decimals, functions, objects, ....
(and my list isn't complete)
As for the documentation, i.e. where exactly it is mentioned that 
this approach is not recommeded. Unfortunately, I forgot, where exactly 
it was. Nevertheless, the reasons are clear, I hope.
In general, Carl wrote REBOL to be its own metalanguage, especially 
to be able to manipulate blocks and their contents accurately. Solutions 
like the above are necessary only in languages, that do not have 
such abilities.
Geomol
30-Oct-2011
[2526]
Why shouldn't decimals work?

>> b: load form [[1.5] [2.5]]
== [1.5 2.5]
>> type? b/1
== decimal!
Ladislav
30-Oct-2011
[2527]
another example, which does not work:

type? load form [1] ; == integer! (i.e. not block!)
Sunanda
30-Oct-2011
[2528]
I suggested the same approach, geomol. I added a caveat that it works 
for some datatypes, not others. It is particularly bad for objects:
    load form reduce [make object! [a: 1]]
So, a useful approach if we are mindful of its limitations.
Ladislav
30-Oct-2011
[2529x4]
As to why decimals are affected, they simply are, and your example 
does not prove the contrary.
Regarding the usefulness:


- one problem is that it is useful only in special cases as Sunanda 
mentioned

- another problem is that this approach is circumventing the proper 
approach, hiding the fact, that it is not recommended
- last but not least, this approach is inefficient
One more note: there is a FLATTEN function definition somewhere, 
which was defined some time ago to be used to flatten hierarchical 
blocks. It should be possible to find it here, but, since it was 
long time ago, I will try to find my version and put it to rebol.org 
or somewhere to make it more available.
Decimals are discussed in the DocBase (Geomol beinng a coeditor of 
the article), and, for the interested, it should not be a problem 
to find relevant informations in there.
Geomol
30-Oct-2011
[2533x2]
type? load form [1] ; == integer! (i.e. not block!)


Yeah, that's a pity, I think. I would prefer LOAD to always return 
a block, so the result from LOAD could always be sent to e.g. PARSE. 
I guess, it's made this way to kinda let LOAD and SAVE reflect each 
other. But that doesn't quite make sense, as we can't save to a string. 
And LOAD can load an empty file giving an empty block, while we can't 
save an empty file with SAVE, afaik.
Example of what I find a bit strange:

>> load ""
== []
>> load "1"
== 1
>> load "1 2"
== [1 2]