Understanding Red Block Evaluation - rebol

Just starting with Red and am having a difficult time understanding how to evaluate blocks. The following gives me a *** Script Error: panel has no value error:
Red [
needs: 'view
]
my-panel: [
panel 300x300 [
text "World"
]
]
view [
title "Hello"
do my-panel
]
I can get it working if I inline the contents of the my-panel block, but can't find a way to split code up and then include it inside the view function's block. Could anyone give me a real quick pointer to what is wrong with the above code?

Red language contains several DSLs, the one you are using above after view call is VID. The do word has different meanings in different contexts. In Red regular language, it evaluates a block of Red Code, in VID, it's a keyword, that allows to embed Red code into VID. So far so good, but you are not passing a block of Red code to do, but a block of VID code.
I guess that you want to achieve is inserting the my-panel block dynamically. That can be achieved using different means, the easiest would be using compose function:
Red [
needs: 'view
]
my-panel: [
panel 300x300 [
text "World"
]
]
view compose [
title "Hello"
(my-panel)
]
We have several chat rooms on Gitter in case you need a more interactive help.
Cheers!

Related

Vega lite - accessing 'repeat' variable to use as filter

I'm attempting to make a trellis bar chart, with the grand total shown faintly behind each chart - see this image.
I've successfully managed to create this a verbose spec, but I want to make this more succinct, by using 'repeat' with a filter. Here is the working version.
Here is my version which almost works, but I can't work out how to allow the filter to access the 'repeat' variable.
How can I access the variable specified in 'repeat' to correctly filter the data?
I have tried the following but it doesn't work
{
"transform": [
{"filter": "datum.gender == repeat"}
]
}
This is not supported right now: https://github.com/vega/vega-lite/issues/2518. These kinds of use cases where you can reuse parts will work much better in DSLs like Altair. JSON is unfortunately not a good fit for reuse. As a side note, a succinct spec is not faster than the verbose spec you wrote. However, I understand that it would be easier to read. Another related proposal for shorter specs is: https://github.com/vega/vega-lite/issues/3384.

Dictionary with dynamic entries in StringTemplate

I'm using StringTemplate 4.0.8 with Java.
In the StringTemplate-4 documentation, it says that
Dictionary strings can also be templates that can refer to attributes
that will become visible via dynamic scoping of attributes once the
dictionary value has been embedded within a template.
How exactly do I do that? Can I do something like this:
output(input) ::= "The output is: <aDicitionary.input>"
aDictionary ::= [
"someKey":"someValue",
"someOtherKey":"someOtherValue",
"aCertainKey": **HERE** i want the value to be <input>,
default:"doesnt matter"
]
So that output("someKey") results in The output is: someValue
and output(aCertainKey) results in "The output is: aCertainKey". If so, how exactly would the syntax look like?
I know that I could achieve the same by just not passing an input in one case and then checking if I have an input or not. But that would result in a lot of if's on the Java side which I
To use a dynamic dictionary entry:
output(input) ::= <%The output is: <aDicitionary.(input)>%>
Use no quotes around the template and put input in parentheses to evaluate it.
To have dynamic content in a dictionary (the subject of the cited block):
aDictionary ::= [
"someKey":"someValue",
"someOtherKey":"someOtherValue",
"aCertainKey": {input from scope <inputFromScope>},
default:"doesnt matter"
]
Use braces around the keys and variable (or template) references inside. Now calling
<output(input="aCertainKey", inputFromScope="myInput")>
will output
The output is: input from scope myInput

Print a SortedCollection to screen using keysAndValueDo (smalltalk)

Hello i'm learning and am new to smalltalk and I'm trying to print my SortedCollection to screen trying to use keysAndValueDo but im not sure how its done, if anyone could give me a general example that would be great
Part 1 - Displaying to the screen
The most straight forward way to print to the screen in a GUI-based Smalltalk is to use the message:
Transcript show: 'some text'
(The Transcript is a system object that displays into a scrollable window).
To make sure there is a newline before each line of display text, we send the message cr to the Transcript
Transcript cr.
Transcript show: 'some text'.
A shorthand method, that saves us re-typing Transcript over and over, is to send Transcript a series of messages one after another. This is called a message cascade. Each time we end a message in ; it means send to the same receiver as the last message was sent to.
We can then shorten this again, as Smalltalk pays no attention to newlines in expressions.
The final display message cascade becomes:
Transcript cr; show: 'some text'.
Part 2: Enumerating aSortedCollection using keysAndValuesDo:
This keyword message is SequencableCollectionand its method header is:
keysAndValuesDo: aBlock
"Enumerate the receiver with all the keys (aka indices) and values."
(It works the same way in Dolphin, and in Squeak and its derivatives, Pharo and Cuis).
The keyword message keysAndValuesDo: takes a block argument.
A block is an anonymous object, with one method. Its method is defined between a matched pair of square brackets - a [ ... ] pair.
In this case, we need a local variable in the block for the key of each element of the collection, and another local variable for the value of each element.
We can call them anything we like, and in this case, it is the order that they appear in that is important. keysAndValuesDo: will put the element's key into the first local variable in the block, and will put the element's value into the second local variable in the block.
Local variables in a block are declared at the start of the block, and each variable name is identified by prefixing it with :. The local variable declarations are ended with a |.
The block then looks like
[:local1 :local2 |
"do something for each element, with the key in local1 and the value in local2"
]
I prefer meaningful local variable names, so I'll use eachKey and eachValue.
Part 3: Putting it all together
To enumerate through mySortedCollection
"Declare the mySortedCollection variable"
|mySortedCollection|
"Initialise the collection"
mySortedCollection := SortedCollection new.
"add in some data to the collection"
mySortedCollection add: ('First') ;
add: ('Second') ;
add: ('Third').
"Enumerate through the collection, displaying to the Transcript window"
mySortedCollection keysAndValuesDo:
[:eachKey :eachValue |
Transcript cr; show: eachKey; show: ' '; show: eachValue
] .
Paste the code into a Workspace (known as a Playground in Pharo, from version 4.0 onwards). Select the text. Once selected, right-click (on a two or three button mouse) and select "Do it" from the menu. Or use Ctrl-d as a keyboard shortcut. (The exact chording key may vary on your platform)
Final notes
In a SortedCollection or an OrderedCollection, the key is the index. The value is what is stored at element[index].
In a Dictionary, the key of the element is the key, and the value of the element is the value.
SortedCollections are sorted in order of the element values, according to the definition of the collections sort block. In the absence of a custom sort block, they will be added in ascending order. 'First', 'Second' and 'Third' are, coincidentally, in alphabetical order. It happens to work out nicely in this example.
The following example works with Pharo Smalltalk, other Smalltalk implementation might work similar.
First, look at existing print methods as examples. In case of SortedCollection, you find them in the printing protocol of its superclass Collection.
You will find that the printing of elements is defined in printElementsOn:. So you could overwrite this method in SortedCollection.
Here is a printElementsOn: method that will use keysAndValuesDo:, as you were asking for:
printElementsOn: aStream
aStream nextPut: $(.
self keysAndValuesDo: [:key :value |
aStream
nextPut: $(;
print: key;
nextPut: $:;
space;
print: value;
nextPut: $)].
aStream nextPut: $)
Now a collection that before printed:
"a SortedCollection(1 2 3 3 5 10)"
will print:
"a SortedCollection((1: 1)(2: 2)(3: 3)(4: 3)(5: 5)(6: 10))"

What exactly happened when not using "copy" to deal with a string?

The purpose of the function below is to return a string having inserted the argument value between two stars.
star-name: func [name /local stars] [
stars: "**"
insert next stars name
stars
]
print star-name "test" ;*test*
print star-name "this" ;*thistest*, but what I really want is *this*
The second time I call the function, the argument of the first call still remains inserted. I know the answer is to use copy "**".
My question is, doesn't it reassign the stars variable to "**" every time the function is called?
In the case of the function there is just one "**" string definition. That definition is used by Rebol load function just once, since load is run just once to translate the code to Rebol internal form - a block. It is true that the assignment occurs twice if you call the function twice, but the assignment does not create anything, it just makes the variable refer to the same string again.
In your comment you should notice that you actually have two "**" string definitions leading to two strings being created by load. If you use
code: [stars: "**" insert next stars something]
something: "this"
do code
something: "that"
do code
you will notice that there is just one string definition and while you do not have any function the behaviour is the same as it was when a function was used.
If you use a set-word on a series, then the default behavior is to allocate the memory for that series just the once. This allows you to use that as a static variable that persists between function calls as you have found.
If you don't want that behavior, then you need to explicitly copy the series to create a new series each time.
This is another way you can do this as the stars local is not required
star-name: func [ name ][
rejoin [ "*" name "*" ]
]

Rebol 3 - R3-GUI - How to access text from an area?

I'm struggling a lot coming from R2 and dealing with faces. get-facet seems extremely unintuitive to me.
Let's say I have an area:
view [c: area "hello"] print get-facet c 'text-edit
get-facet always returns "hello" even if I type something else in the area. What is going on with this? The 'caret and 'state facet objects contain the correct text, but I cannot find a way to access them.
The correct command is get-face. Get facet should be used for
For the example above, it is fixed by:
view [c: area "hello"] print get-face c
From an explanation from Cyphre: get-face is intended for the application programmers but get-facet is intended for style developers because it directly accesses the style internals. If styles are updated it may break code if get-face is not used. One should avoid using refinements such as /text or /data on faces as it was easy to do in R2
AREA's facet TEXT-EDIT looks like it just stores the initialization, and the state/caret facet objects contain run-time data