Home   Archive   Permalink

Make a block with name supplied at run time

It seems like I should be able to do this. I want to read an unknown amount of data at run time, and depending on what I get I want to put it into one or more blocks, the names of which will be determined by the data itself. For example, some of the data might be for street names, and some header in the data will indicate this, perhaps by a header record containing the text STREETNAMES. So after reading this data and determining that it contains street names, I want to make a block called STREETNAMES and put data into that block. But the data might not be street names; I won't know until I actually read it, and so I want to pick the block name AFTER reading the data. I can't quite see how to do that, or if it can be done.
The reason I want to determine the block name at run time is that I want to make an arbitrary number of blocks. I could use, for example, six generic names like BLOCK1...BLOCK6, but then I might get a set of data that contains data for seven blocks. Being able to set the number of blocks and their names at run time gives generality.    
As an example, in the following script, I am prompted to enter a word that will become the name of a block. I get the name, but then what do I do with it to make it into the name of a block, and then to start adding data to the block?
Thank you.    
R E B O L []
BLOCKNAME: ask "Enter name for a new block: "
;to-set-word BLOCKNAME copy [] ;; This does not work
;to-set-word BLOCKNAME make block! ;; This does not work

posted by:   Steven White       23-Oct-2017/17:17-7:00

This would make a good StackOverflow question.
(When something is more conversational and less Q&A...e.g. the kind of thing StackOverflow prohibits...forums are good. But something like this is of general interest, and having access to Markdown formatting and being able to edit and improve posts is worthwhile.)
You will probably find the answer to this question illustrative, in particular the part after "But producing a SET-PATH! doesn't mean it runs."

posted by:   Fork       23-Oct-2017/18:26:51-7:00

I agree that this is typically a 'dodgy' solution, but I have found such a technique useful, especially when dealing with dynamically generated GUI layouts. This snake game example from http://re-bol.com/shorter_examples.r , makes use of dynamically generated labels for the GUI boxes, and the color values of those faces are dynamically evaluated and altered throughout game play. There's a rough explanation of how it works at https://youtu.be/rnKvmwe2F6w
f: random 400 p: .3 d: 20 s: copy [1] g: copy [
    across key #"w"[d: -20]key #"s"[d: 20]key #"a"[d: -1]key #"d"[d: 1]origin
] repeat i 400 [
    append g reduce [to-set-word join "p"i 'box 'snow 20x20]
    if i // 20 = 0 [append g 'return]
] e: does [alert "Dead" unview break] w: view/new layout g forever [
    if any [all[d = -1 s/1 // 20 = 1] all[d = 1 s/1 // 20 = 0]] [e]
    if find s h: s/1 + d[e]insert head s h do rejoin["p"last s"/color: snow"]
    either f = s/1 [f: random 400 p: p - .01][remove at s length? s]
    repeat i length? s[if error? try[do rejoin["p"s/:i"/color: red"]][e]]
    do rejoin ["p"f"/color: blue"] show w if not viewed? w [break] wait p
I've used such a technique a number of times over the years when I didn't know all the widgets that would be included in a user interface layout (i.e., when the interface of the app was created dynamically based on the data being presented). That has invariably led to hairy code, but it's always been an interesting effect for the user.
I can also imagine that such a technique could be useful in converting CSV, JSON, or some other data into native Rebol data structures. Here's a convoluted little example:
remove-each l old: read/lines http://re-bol.com/structureddata.txt [l = ""]
new: copy "["
foreach l old [
    either 1 = length? p: parse l none [
     append new rejoin [ "]^/" p ": [" ]
     foreach i p [append new join mold i " "]
write %mynewdata.r rejoin ["R E B O L []" at new 3 "]"]
Run that, then this (this could be in a separate script, for example):
do %mynewdata.r
probe header1
probe header2
probe header3

posted by:   Nick       23-Oct-2017/23:21:40-7:00

As it stands, that last example answers a different question than what you're asked about. The simple answer to your question is even easier than the snake game example:
BLOCKNAME: ask "Enter name for a new block: "
do rejoin [BLOCKNAME ": []"]

posted by:   Nick       23-Oct-2017/23:32:13-7:00

There's some of that sort of thing, for example, in scripts such as http://www.rebol.org/view-script.r?script=gui-crud-app-builder.r

posted by:   Nick       23-Oct-2017/23:49:27-7:00

In any case, the simple solution that has been useful to me most often has been to generate a string of code, and then to 'do that code. Think of it just like writing to a script, and then 'do-ing the script file.
If you generate a BLOCK of code (AS OPPOSED TO a string (a string of characters, as in a script)), then set-words need to be created with 'to-set-word (as in the snake example above)

posted by:   Nick       24-Oct-2017/8:48:23-7:00