How to modify each element of a block by "foreach" in red/rebol - rebol

I want to modify each element of a block by foreach. I tried like this but failed:
>> a: [3 4 5 6]
== [3 4 5 6]
>> foreach i a [i + 1]
== 7
>> a
== [3 4 5 6] ;; block a is not changed. What I want is [4 5 6 7]
Is there a better way to achieve it?

Changes that you made to values do not persist in a block itself. This ties back to your question about call-by-value parameter passing in Rebol and Red: you modify a copy on the stack (passed down to + along with 1), not the actual value slot that sits inside block a.
To achieve what you want, you need to increment integers in-place, without pushing them on the stack. One way to do so is by using forall.
>> block: [1 2 3]
== [1 2 3]
>> also block forall block [block/1: block/1 + 1]
== [2 3 4]
What forall does is setting a word to a series and then incrementally bumping its index:
>> forall block [probe block]
[1 2 3]
[2 3]
[3]
Since it doesn't extract the actual values, you can access them using path notation, and then modify them in place. block/1 always pick the first value on each iteration.

As usual, no reply with your foreach.
a: [2 3 4 5]
b: copy []
foreach i a [append b i + 1]
and if you wish you can set a to b now
a: b
The problem with doing this in one step is that you do not have an index you can use here (despite the suggestive letter i, but that is representing the content of each item inside the block).
So now you can choose your favourite solution.

>> help forall
USAGE:
FORALL 'word body
DESCRIPTION:
Evaluates body for all values in a series.
FORALL is a native! value.
ARGUMENTS:
'word [word!] "Word referring to series to iterate over."
body [block!]
use forall
> a: [3 4 5 6]
== [3 4 5 6]
>> forall a [a/1: a/1 + 1]
== 7
>> probe a
[4 5 6 7]
== [4 5 6 7]

Related

Value of local variables in a function seems not be released post function calling in Red/Rebol language

I construct a function named find-all to find all indexes of a given item in a series by "recursive".
The first calling of find-all gives the right output. However from the second calling, all outputs are appended together.
find-all: function [series found][
result: []
either any [empty? series none? s-found: find series found]
[result]
[append result index? s-found
find-all next s-found found]
]
;; test:
probe find-all "abcbd" "b" ;; output [2 4] as expected
probe find-all [1 2 3 2 1] 2 ;; output [2 4 2 4]
Since variables inside a function created with function are local, why does the value of variable result is still there during later funtion callings, which cause the result of the sencond calling of find-all does not begin with []?
And what is the correct recursive way to achieve this funciton?
The answer is evident if you inspect find-all after making these two calls:
>> ?? find-all
find-all: func [series found /local result s-found][
result: [2 4 2 4]
either any [empty? series none? s-found: find series found]
[result]
[append result index? s-found
find-all next s-found found
]
]
result is an indirect value, and its data buffer is stored on a heap. The data gets preserved between the calls and accumulated, because you do not re-create it with copy — result being local to function's context is unrelated to that.
Thanks to #9214's help, especially the description about indirect value. I give a solution like this:
find-all: function [series found][
either any [empty? series none? s-found: find series found]
[[]]
[append
reduce [index? s-found]
find-all next s-found found
]
]
;; test:
probe find-all "abcbd" "b" ;; output [2 4] as expected
probe find-all [1 2 3 2 1] 2 ;; output [2 4] as expected

Most elegant way to extract block by skipping every 2 element

Let's say I have
block: [a 1 b 2 c 3]
I want
[1 2 3]
Something like this is clunky and it doesn't work because I use word type (I'd like to have it word with word not string):
block: [a 1 b 2 c 3]
block2: []
counter: -1
foreach 'element block [
counter: negate counter
if counter append block2 element
]
The EXTRACT function should fit the bill here:
>> extract/index [a 1 b 2 c 3] 2 2
== [1 2 3]
It's fairly versatile for this type of thing.
>> help extract
USAGE:
EXTRACT series width
DESCRIPTION:
Extracts a value from a series at regular intervals.
EXTRACT is a function! value.
ARGUMENTS:
series [series!]
width [integer!] "Size of each entry (the skip)".
REFINEMENTS:
/index => Extract from an offset position.
pos [integer!] "The position".
/into => Provide an output series instead of creating a new one.
output [series!] "Output series".

Gurobi Optimization Result Writing into Csv file

I am using Gurobi 7 to solve my MIP. I have several different variables. However, I am specifically interested in two of those, "x" and "y" namely. For the reference, I am giving my code that shows how I added x and y variables into the solver:
# Creating Variables
x = {}
y = {}
# Adding Variables
for i in range(I):
x[i+1,P[i]-d[0]] = m.addVar(vtype=GRB.BINARY, name="x%s" % str([i+1,P[i]-d[0]]))
x[i+1,P[i]] = m.addVar(vtype=GRB.BINARY, name="x%s" % str([i+1,P[i]]))
for i in range(I):
for k in range(len(rangevalue)):
y[i+1, rangevalue[k] - E[i]] = m.addVar(vtype=GRB.BINARY,
name="y%s" % str([i+1, rangevalue[k] - E[i]]))
Even though the above code may not really make any sense, I just wanted to show it in case you may use it for my problem.
After I solve the problem, I get the following results:
m.printAttr('X')
Variable X
-------------------------
x[1, 3] 1
sigmaminus[1] 874
x[2, 2] 1
sigmaminus[2] 1010
x[3, 2] 1
sigmaminus[3] 1945
x[4, 4] 1
sigmaplus[4] 75
x[5, 4] 1
sigmaminus[5] 1153
x[6, 5] 1
sigmaminus[6] 280
x[7, 3] 1
sigmaplus[7] 1138
x[8, 2] 1
sigmaplus[8] 538
x[9, 1] 1
sigmaplus[9] 2432
x[10, 5] 1
sigmaminus[10] 480
omega[1] 12
OMEGA[1] 12
omega[2] 9
OMEGA[2] 12
omega[3] 8
OMEGA[3] 9
omega[4] 8
OMEGA[4] 8
OMEGA[5] 8
y[1, 2] 1
y[2, 9] 1
y[3, 5] 1
y[4, 6] 1
y[5, 4] 1
y[6, 6] 1
y[7, 3] 1
y[8, 11] 1
y[9, 8] 1
y[10, 1] 1
phiplus[6] 1
phiminus[7] 1
phiminus[10] 1
I specifically want to display x and y variables with their indexes. Other variables are not necessary. My question is how can I write these results into an csv file on one column as following?
x[1,3]
x[2,2]
x[3,2]
.
.
.
x[10,5]
y[1,2]
y[2,9]
y[3,5]
.
.
.
y[10,1]
I do not need their corresponding value which can only be "1" since they are binary variables. I just need to write the variables which have the value "1".
I would do something along these lines:
import csv
if m.SolCount == 0:
print("Model has no solution")
exit(1)
var_names = []
for var in m.getVars():
# Or use list comprehensions instead
if 'x' == str(var.VarName[0]) and var.X > 0.1:
var_names.append(var.VarName)
# Write to csv
with open('out.csv', 'wb') as myfile:
wr = csv.writer(myfile, quoting=csv.QUOTE_ALL)
wr.writerows(var_names)
I hope this helps. I am going to test this snippet a bit later. Update: works as intended.

unique for a block doesn't remove duplicates

The strings are part of urls of which I stripped out the base.
parse detects four urls in some html file. I've narrowed down the problem to this:
REBOL []
images: [{,W,H,wi,1TV1Rvu8EF9FDdUxKy+hTKK/RNifw3WQDJEI/sYkX78tyNifGd0/U4RpaBox1rO448B4dv24sYoTgxOMVC7Lz5J9sJXlk0nkM89n55HzX7qbRiX/cSkd3lepAEIj3LVTN7gmQLCI2+INwwg18IyDklZ3VZWkw011+77dkfgTTRlRaY397ricx4dk4BTHvCLZ} {,W,H,wi,1TV1Rvu8EF9FDdUxKy+hTKK/RNifw3WQDJEI/sYkX78tyNifGd0/U4RpaBox1rO448B4dv24sYoTgxOMVC7Lz5J9sJXlk0nkM89n55HzX7qbRiX/cSkd3lepAEIj3LVTN7gmQLCI2+INwwg18IyDklZ3VZWkw011+77dkfgTTRlRaY397ricx4dk4BTHvCLZ} {,W,H,wi,1TV1Rvu8EF9FDdUxKy+hTKK/RNifw3WQDJEI/sYkX78wvYn3cKtEeN/9Y8EfNR8J48B4dv24sYoTgxOMVC7Lz5J9sJXlk0nkM89n55HzX7qbRiX/cSkd3lepAEIj3LVTN7gmQLCI2+INwwg18IyDklZ3VZWkw011+77dkfgTTRlRaY397ricx4dk4BTHvCLZ} {,W,H,wi,1TV1Rvu8EF9FDdUxKy+hTKK/RNifw3WQDJEI/sYkX78wvYn3cKtEeN/9Y8EfNR8J48B4dv24sYoTgxOMVC7Lz5J9sJXlk0nkM89n55HzX7qbRiX/cSkd3lepAEIj3LVTN7gmQLCI2+INwwg18IyDklZ3VZWkw011+77dkfgTTRlRaY397ricx4dk4BTHvCLZ}]
print join "before: " length? images
unique images
print join "after: " length? images
print join "1=2? " images/1 = images/2
print join "1=3? " images/1 = images/3
print join "1=4? " images/1 = images/4
print join "2=3? " images/2 = images/3
print join "2=4? " images/2 = images/4
print join "3=4? " images/3 = images/4
As can be seen, urls 1 and 2 are identical, and the same can be said to urls 3 and 4. Still, unique doesn't remove the duplicates. Why does this happen, how to deal with it?
UNIQUE does not modify original series. Whether function modifies is usually mentioned in it's help string, see SORT for example. Just set your block to the result of UNIQUE, like this:
>> a: [1 2 3 4 3 4 4]
== [1 2 3 4 3 4 4]
>> unique a
== [1 2 3 4]
>> a
== [1 2 3 4 3 4 4]
>> a: unique a
== [1 2 3 4]
>> a
== [1 2 3 4]

Understanding PsychoPy's data logging

I have a test PsychoPy Builder script that I am using to investigate some counter-intuitive behaviour. The structure is four routines:
"Init", not in a loop, the following code in "Begin Experiment":
x = 0
y = 0
z = 0
foo = [0, 0, 0]
"One", in a loop, the following code in "End Routine":
x = x + 1
foo[0] = foo[0] + 1
thisExp.addData("x", x)
thisExp.addData("y", y)
thisExp.addData("z", z)
thisExp.addData("foo", foo)
"Two", in a loop, the following code in "End Routine":
y = y + 2
foo[1] = foo[1] + 2
thisExp.addData("x", x)
thisExp.addData("y", y)
thisExp.addData("z", z)
thisExp.addData("fooY", foo[1])
thisExp.addData("foo", foo)
"Three", in a loop, the following code in "End Routine":
z = z + 3
foo[2] = foo[2] + 3
thisExp.addData("x", x)
thisExp.addData("y", y)
thisExp.addData("z", z)
thisExp.addData("foo", foo)
There is no other code, no other components. The routines "One", "Two", and "Three" form a loop in that order executed five times. The relevant columns of the CSV output file are as follows:
trials.thisRepN trials.thisTrialN trials.thisN trials.thisIndex x y z foo fooY
0 0 0 0 1 2 3 [5, 10, 15] 2
1 0 1 0 2 4 6 [5, 10, 15] 4
2 0 2 0 3 6 9 [5, 10, 15] 6
3 0 3 0 4 8 12 [5, 10, 15] 8
4 0 4 0 5 10 15 [5, 10, 15] 10
Is this the expected output? If so, why? Note that the individual variables, x, y, and z, are displaying updated values each time through the loop (at the end of the loop), while the list foo shows only the final value after the loop iterates all five times, but it shows this in every line. But calling out individual elements of the list displays as individual variables do.
What is the logic and rationale behind this?
Is there a way to make the list output perform as the others do?
Is there a way to force the output to capture/display any of these variables as they are when the addData() is invoked rather than waiting until the end of the loop?
I think I know what is going wrong here. It's probably because python assigns by reference rather than copy. This is explained in detail elsewhere but briefly,
original = [1, 2]
new = original # new is simply a reference to original! It is not a copy.
new[0] = 'Oops' # original is now ['Oops', 2] as is new (which is just a reference or pointer
In your case, the TrialHandler receives the reference, which simply points to the "foo" variable which is updated throughout the experiment. Since the log is only saved in the end of the experiment, all the rows in "foo" now points to the "foo variable" which now holds the value [5, 10, 15].
This assignment-by-reference can be extremely beautiful and handy, but sometimes cause headache like in your example. It applies to all python mutables: lists, dicts, functions, and classes. But not for immutables, like numbers, tuples and strings! That's why your script works for digits but not for the list.
There are different solutions. The simplest is probably to replace the addData calls with thisExp.addData("foo", tuple(foo)) which converts the mutable list to an immutable tuple. One can also do thisExp.addData("foo", [x for x in foo]). A more all-round solution for all kinds of objects is to run import copy in the beginning of the experiment and then add data like thisExp.addData("foo", copy.copy(foo)) in the other codeblocks (if you have a complicated object, use copy.deepcopy instead).