Fixing the Rebol3 example calculator to use normal math operator precedence - rebol

In the example calculator:
REBOL [title: "Calculator"]
do %r3-gui.r3
stylize [
btn: button [
facets: [init-size: 50x50]
actors: [on-action:[set-face f join get-face f get-face face]]
]
]
view [
hgroup [
f: field return
btn "1" btn "2" btn "3" btn " + " return
btn "4" btn "5" btn "6" btn " - " return
btn "7" btn "8" btn "9" btn " * " return
btn "0" btn "." btn " / " btn "=" on-action [
attempt [set-face f form do get-face f]
]
]
]
...the resulting program doesn't (as Rebol traditionally doesn't) evaluate mathematical expressions with * having a higher precedence than +. E.g. 2 + 3 * 4 gives 20 instead of 14.
I thought I had read somewhere that Rebol3 contained a new function that would evaluate math expressions more the way folks are used from nearly every other context. Is that true? If so, can the above code be made to use it without a significant amount of change?

I'm not sure there's a specific function in Rebol 3 that evaluates operators according to formal precedence (I'd be pleased to be corrected), though there are attempts in the wild to implement such a function. If you were to locate such a function, you can just change the evaluator from do to do-expression (where do-expression is said function) in the on-action block of your "=" button.

Who said that "the normal order" to evaluate should be the best?
Some 'wiseguy' once came up with that because he could not handle being wrong unfortunately he was stronger than the others and threatened to hammer their heads in if they wouldnot do things like he had done, so we are taught to this day that multiplication precedes over addition despite of the order they were put in. Rebol rebels!
;)

Related

How can one dynamically update a progress indicator while a calculation started by changing an InputField value is running?

I have a Mathematica notebook that employs a fairly complicated user interface for controlling a long-running calculation. Among other things, the interface takes liberal advantage of Button, RadioButtonBar, Checkbox, and InputField.
When the effect of clicking a Button is an intermediate calculation that may take more than a couple seconds to complete, I like to provide a visual indication that the code hasn't crashed and is, in fact, doing something useful. A good way to do this is to start up a ProgressIndicator just before the intermediate calculation starts and then turn it off once the calculation is done. I have found this to be straightforward for calculations started by a Button click.
The same method does not work, however, for calculations that are initiated by changes to an InputField value. The simplified code below was written to do this but fails. The last two rows of the Grid are supposed to change automatically when updatingQ changes to True in the inner Dynamic command and then change back when updatingQ reverts to True, but it never happens. It appears that the outer Dynamic code is being blocked while the inner Dynamic code runs so it never even notices the changes to updatingQ.
On the other hand, the last two lines of the Grid respond as expected if one manually sets updatingQ=True on a separate input line.
(BTW, i) Pause[2] is just a stand-in for the intermediate calculation and ii) I multiply the input value by Pi is just to make it more obvious when the stand-in calculation is done.)
Apparently, the action portion of a Button behaves differently. Other pieces of code within the same Dynamic block can see and quickly respond when flags are changed there. It may be notable that I use Method->"Queued" in such cases. I tried the same with InputField (for which it is not a documented option) but to no effect.
I've tried various other things not shown here also without success.
A way to make this work would be much appreciated.
Clear[ProgressIndicatorTest]
updatingQ = False;
ProgressIndicatorTest = {
TextCell["ProgressIndicatorTest", "Subsubsection", Background -> LightBlue],
DynamicModule[
{filterTypes = {"Max energy", "Max length"}, filterValue, workingOn = "", iter = 0},
Scan[(filterValue[#[[1]]] = #[[2]]) &, Transpose#{filterTypes, {0.1, 100.}}];
Dynamic[
Grid[
Join[
Map[
Function[
filterType,
{filterType,
Dynamic#
InputField[
Dynamic[
filterValue[filterType],
Function[
value,
If[value > 0,
updatingQ = True;
Pause[2];
filterValue[filterType] = \[Pi] value;
updatingQ = False
]
]
], FieldSize -> 5, Alignment -> Right
]
}
], filterTypes
],
{{updatingQ, "-------"}},
{If[updatingQ,
{"Updating ... ",
ProgressIndicator[Appearance -> "Indeterminate"]},
Nothing
]}
], Alignment -> Left,
Background -> {None, {LightGreen, LightGreen, LightYellow, LightYellow}}
]
]
]
};
CellGroup[ProgressIndicatorTest]
As Forrest Gump never said, "Stackoverflow/Stackexchange is like a box of chocolates ... you never know what you'll get". And so today I found this answer which solves my problem.
Adapted to my particular case, the resulting code is as follows:
Clear[ProgressIndicatorTest]
calculation[n_] := Module[{a = .3}, Do[a = a (1 - a), {i, n 10^6}]]
updatingQ = False;
ProgressIndicatorTest = {
TextCell["ProgressIndicatorTest", "Subsubsection", Background -> LightBlue],
DynamicModule[{filterTypes = {"Max energy", "Max length"}, filterValue, upToDateQ = True},
Scan[(filterValue[#[[1]]] = #[[2]]) &, Transpose#{filterTypes, {0.1, 100.}}];
Dynamic[
Grid[
Join[
Map[
Function[
filterType,
{filterType,
DynamicWrapper[
InputField[
Dynamic[
filterValue[filterType],
Function[
value,
If[value > 0,
upToDateQ = False;
filterValue[filterType] = value
]
]
], FieldSize -> 5, Alignment -> Right
],
If[! upToDateQ,
Refresh[
updatingQ = True; calculation[2]; updatingQ = False;
upToDateQ = True,
None
]
],
SynchronousUpdating -> False
]
}
], filterTypes
],
{
If[updatingQ,
{"Updating ... ",
ProgressIndicator[Appearance -> "Indeterminate", ImageSize -> 80]},
Nothing
]
}
], Alignment -> Left,
Background -> {None, {LightGreen, LightGreen, LightYellow,}}]
]]
};
CellGroup[ProgressIndicatorTest]
This code does exactly what I want.
The key to success is wrapping DynamicWrapper around InputField and inserting a cleverly constructed second argument that performs the flag reset (upToDate=False in my case) that triggers the ProgressIndicator located elsewhere.
A couple more points.
Pause turns out not to be a good stand-in for a calculation. You may observe that the code behaves differently with a real function such as calculation.
It is interesting to note that upToDateQ can be a local variable whereas updatingQ cannot.
Kudos to Albert Retey for providing the code back in 2013.
The documentation for InputField says
"An InputField of type Expression [the default] replaces its
contents with the fully evaluated form every time the contents are
updated".
This seems to mean that InputField privately evaluates its content and all connected dynamics before releasing value changes, probably to prevent circular evaluations.
The following example condenses the problem. The first part works ok ...
changed = processing = False;
Column[{InputField[Dynamic[x, (changed = True; x = 2 #) &], FieldSize -> 5],
Dynamic[changed],
Dynamic[processing]}]
... until the dynamic below is also evaluated. Then changed never shows True because it is changed back to False before the update concludes.
Dynamic[If[changed,
processing = True;
Pause[2];
changed = processing = False]]
A alternative strategy would be to use a Button, e.g.
changed = False;
processing = Spacer[0];
Column[{InputField[Dynamic[y, (changed = True; y = #) &], FieldSize -> 5],
Button["Enter",
If[changed,
processing = ProgressIndicator[Appearance -> "Indeterminate", ImageSize -> 120];
Pause[2];
y = 2 y;
changed = False;
processing = Spacer[0]], Method -> "Queued", Enabled -> Dynamic[changed]],
Dynamic[changed],
Dynamic[processing]}]
This shorter version avoids the need to tab out of the input field.
changed = False;
processing = Spacer[0];
Column[{InputField[Dynamic[y], FieldSize -> 5],
Button["Enter",
processing = ProgressIndicator[Appearance -> "Indeterminate", ImageSize -> 120];
Pause[2];
y = 2 y;
processing = Spacer[0], Method -> "Queued"], Dynamic[processing]}]
Note the use of Method -> "Queued" gives Button the advantage over InputField. Without it Button appears to have the same problem.

How can I write conditional expression in output of a minizinc program?

I have the following code:
output["\(w) \(l)\n\(n)\n"] ++ [if rotation[i] then "\(x[i]) \(y[i]) \(p_x[i]) \(p_y[i]) R\n" else "\(x[i]) \(y[i]) \(p_x[i]) \(p_y[i])\n" endif |i in CIRCUITS];
My purpose is to print each row and the vaue "R" whether rotation[i] is true, false otherwise.
For instance:
w l
n
x[1] y[1] p_x[1] p_y[1] "R"
x[2] y[2] p_x[2] p_y[2]
In this example rotation[1] is true and rotation[2] is false
Your sample MiniZinc code was almost there. The important change you will have to make if to force the "rotation" variable to take its "solution value" using the "fix" builtin function.
output ["\(w) \(l)\n\(n)\n"]
++ ["\(x[i]) \(y[i]) \(p_x[i]) \(p_y[i])"
++ if fix(rotation[i]) then " R" else "" endif
++ "\n"
| i in index_set(rotation)];
Additionally, I would suggest trying to make the conditional part as small as possible to improve readability, as incorporated in the above code fragment.

Rebol code gui working but not clearing fields

I am trying following code where user enters 2 numbers and on clicking calculate button, answer should be shown. There are also buttons for clearing fields and for exiting.
REBOL[]
fields: [f-ht f-wt ans]
reset-fields: does [
unfocus
f-ht/text: " " ; Changing this to "ENTER NUMBER HERE" does not help
f-wt/text: " "
focus f-ht
]
oncalc: does [
ans/text: (to integer! f-wt/text) / ((100 * to integer! f-ht/text) * (100 * to integer! f-ht/text))
show fields
]
lo: layout [
style tx label 200x24 center
style fld field 200x24 center
style btn button 200x24 center
tx "First Number:"
f-ht: fld
tx "Second Number:"
f-wt: fld
btn "Calculate" [oncalc]
ans: tx "Answer"
btn "Clear" [reset-fields show fields] ; NOT WORKING- NOTHING HAPPENS
btn "Exit" escape [unview/only lo]
]
reset-fields
view center-face lo
The GUI is showing all right. However, there are following problems:
On clear button clicking, nothing is happening.
There are no changes on GUI and no errors are being reported. Where is the problem and how can this be solved? Thanks for your help.
Clear the fields instead of setting to new strings
reset-fields: does [
unfocus
clear f-ht/text
clear f-wt/text
focus f-ht
]

REBOL layout: How to create layout words automatically - word has no context?

Using the REBOL/View 2.7.8 Core, I would like to prepare a view layout beforehand by automatically assigning words to various layout items, as in the following example.
Instead of
prepared-view: [across
cb1: check
label "Checkbox 1"
cb2: check
label "Checkbox 2"
cb3: check
label "Checkbox 3"
cb4: check
label "Checkbox 4"
]
view layout prepared-view
I would thus like the words cb1 thru cb5 to be created automatically, e.g.:
prepared-view2: [ across ]
for i 1 4 1 [
cbi: join "cb" i
cbi: join cbi ":"
cbi: join cbi " check"
append prepared-view2 to-block cbi
append prepared-view2 [
label ]
append prepared-view2 to-string join "Checkbox " i
]
view layout prepared-view2
However, while difference prepared-view prepared-view2 shows no differences in the block being parsed (== []), the second script leads to an error:
** Script Error: cb1 word has no context
** Where: forever
** Near: new/var: bind to-word :var :var
I've spent hours trying to understand why, and I think somehow the new words need to be bound to the specific context, but I have not yet found any solution to the problem.
What do I need to do?
bind prepared-view2 'view
view layout prepared-view2
creates the correct bindings.
And here's another way to dynamically create layouts
>> l: [ across ]
== [across]
>> append l to-set-word 'check
== [across check:]
>> append l 'check
== [across check: check]
>> append l "test"
== [across check: check "test"]
>> view layout l
And then you can use loops to create different variables to add to your layout.
When you use TO-BLOCK to convert a string to a block, that's a low-level operation that doesn't go through the "ordinary" binding to "default" contexts. All words will be unbound:
>> x: 10
== 10
>> code: to-block "print [x]"
== [print [x]]
>> do code
** Script Error: print word has no context
** Where: halt-view
** Near: print [x]
So when you want to build code from raw strings at runtime whose lookups will work, one option is to use LOAD and it will do something default-ish, and that might work for some code (the loader is how the bindings were made for the code you're running that came from source):
>> x: 10
== 10
>> code: load "print [x]"
== [print [x]]
>> do code
10
Or you can name the contexts/objects explicitly (or by way of an exemplar word bound into that context) and use BIND.

How to create a Popup Window in Rebol?

I tried to implement a save-as-ftp button in Rebol embedded editor. Implementation of the save-as-button is this:
save-as-ftp: has [file-content][
file-content: t1/text
prefs-file: rejoin [_self-path %ftp.preferences.txt]
either exists? prefs-file [
prefs-ftp: construct load prefs-file; see article application configuration file
user: prefs-ftp/user
password: prefs-ftp/password
server-path: prefs-ftp/server-path
][
user: ask "User: "
password: ask/hide "Password: "
server-path: ask "Server-Path: "
]
view ftp-view: layout [
origin 10x10 space 8x4
style btn btn 140
ftp-field: text bold "" 140 center
pad 0x4
btn-enter 140 "Save" #"s" [hide-popup result: ftp-field/text]
btn red + 50 "Quit - No Save" [hide-popup quit-now]
]
file-target: result
ftp-target: rejoin [ftp:// user ":" password "#" server-path file-target]
write ftp-target file-content
print ["uploaded" file-target "to" rejoin [ftp:// "XXXXXXX" ":" "XXXXXXX" "#" server-path]]
true
]
My problem is with view ftp-view : I cannot even type in ftp-field text box as the popup window loses focus.
hide-popup is used to close a modal window.
A modal window is opened by using 'inform
I don't see any modal windows here.
Oh .. this is a button or something that you are attaching to the rebol editor?
I modified mine some years ago to edit ftp files ... I'll have to see if I can find what I did.