Closed rand5 closed 6 years ago
I think the problem is (probably surprisingly) that your map is being garbage collected.
Fixes:
2 & 3 are useful in cases like the above where your aim is to produce a side effect (e.g. printing stuff), and you don't care about the value of the map signal, and thus you don't assign it to a variable (nothing
in this case since println
returns nothing
)
I'm guessing the images possibly just increased the chance of garbage collection because they use more memory, that's why you saw the different behaviour
This seems to be a common problem btw. I'm just curious did you notice anything about garbage collection in the Reactive.jl docs? It is mentioned somewhere, but I don't think it's clear enough, and we should probably add it to the docstring for Reactive.map
.
@JobJob thanks for the solutions. After reading your comment I went back and looked at the Reactive.jl docs and found only the following reference to garbage collection: "Note that, signal nodes that do not have any reference in Reactive are admissible to garbage collection and subsequent termination of updates." As someone who is new to this sort of thing, that sentence didn't mean a whole lot to me and it never crossed my mind that garbage collection could be the issue.
I like the way Interact.jl has put some notebooks in the doc folder to serve as a tutorial to the package. I think it may be worth adding one on garbage collection.
I think this is easily the biggest "gotcha" in using Reactive, especially if you avoid preserve
(e.g., if you want to make sure that each GUI window holds references to its own resources, and gets cleaned up after you close the window). More discussion about a possible alternative here.
@rand5 thank you, that is helpful. A GC notebook sounds like a good idea.
I think this is easily the biggest "gotcha" in using Reactive...
yeah completely, it keeps coming up. We should definitely try make the default behaviour more friendly to new users, or at the very least make it much more obvious that preserve
and/or foreach
needs to be used in cases like the above.
I only skimmed what you wrote in Observables - is it fair to say that trigger
is somewhat analogous to foreach
? Is there more there that should perhaps be adapted to Reactive? Are the defaults different?
I only skimmed what you wrote in Observables - is it fair to say that trigger is somewhat analogous to foreach?
Yes and no. The real difference is that it doesn't create a new object, so there's nothing to garbage-collect. It's the collection of the object that removes the callback.
Closing as this is no longer an issue in latest (unreleased) Interact, because the map
information is stored in the Observable
observe(A)
. Btw, the new syntax would be:
function Test2()
A = button("Click Here")
on(v->println("Hello World"),observe(A))
@manipulate for a=A
WebIO.render(testimage("cameraman"))
end
end
I'm not sure why WebIO.render
is needed, but have opened an issue about it.
When I am using Interact and the TestImages package, I seem to be getting variable behavior of a button.
For example, the following code executes as expected, printing "Hello World" once for each button click:
function Test1()
A = button("Click Here")
map(v->println("Hello World"),signal(A),init=nothing)
@manipulate for a=A
img = testimage("cameraman");
t=1;
end
end
However, if I execute the following (the line
t=1
has been removed), clicking the button prints only "Hello World" a few times (2-5) before seeming to stop working:function Test2()
A = button("Click Here")
map(v->println("Hello World"),signal(A),init=nothing)
@manipulate for a=A
img = testimage("cameraman");
end
end
I've also tested this with the
Images
package and loading a local image and I get the same results.