juliagizmos / reactive.jl Goto Github PK
View Code? Open in Web Editor NEWReactive programming primitives for Julia
Home Page: http://juliagizmos.github.io/Reactive.jl/
License: Other
Reactive programming primitives for Julia
Home Page: http://juliagizmos.github.io/Reactive.jl/
License: Other
Hi,
do you mind tagging the fix for apply(f, args...) , so it's available via Pkg.add(..) ?
Best,
Simon
This looks different enough from #42, failure occurs in .julia/v0.4/Reactive/tests/basics.jl
in statement push!(a, 1.0)
(line 15)
8 a = Input(number())
9 b = lift(x -> x*x, a)
10
11 # Lift type
12 @test isa(b, Reactive.Lift{Int})
13
14 # type conversion
15 push!(a, 1.0)
julia> using Reactive
julia> include("test.jl")
WARNING: int(x::FloatingPoint) is deprecated, use round(Int,x) instead.
in depwarn at ./deprecated.jl:40
in int at deprecated.jl:29
in number at /home/alain/.julia/v0.4/Reactive/tests/basics.jl:4
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
in push! at /home/alain/.julia/v0.4/Reactive/src/Reactive.jl:224
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
ERROR: LoadError: LoadError: MethodError: `getindex` has no method matching getindex(::Tuple{DataType,DataType})
Closest candidates are:
getindex(::Tuple, ::Int64)
getindex(::Tuple, ::Real)
getindex(::Tuple, ::AbstractArray{Bool,N})
...
in push! at /home/alain/.julia/v0.4/Reactive/src/Reactive.jl:273
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
while loading /home/alain/.julia/v0.4/Reactive/tests/basics.jl, in expression starting on line 15
while loading /home/alain/.julia/v0.4/Reactive/tests/test.jl, in expression starting on line 1
versioninfo()
Julia Version 0.4.0-dev+4500
Commit 30b94a1* (2015-04-25 15:54 UTC)
Platform Info:
System: Linux (x86_64-linux-gnu)
CPU: Intel(R) Core(TM) i5-2467M CPU @ 1.60GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge)
LAPACK: libopenblas
LIBM: libopenlibm
LLVM: libLLVM-3.3
Can you provide higher order functions. E.g. zip function to covert a structure of Reactive variables to a reactive stream of the structure
Things seem to fail on 0.5, so I tried this:
steve:~/.julia/v0.5/Reactive(sjk/node-call)$ git diff
diff --git a/src/core.jl b/src/core.jl
index 14e2b76..d45a748 100644
--- a/src/core.jl
+++ b/src/core.jl
@@ -189,7 +189,8 @@ let timestep = 0
timestep += 1
iter += 1
- let message = take!(_messages)
+ let
+ @show @which take!(_messages)
node, value, onerror = message
try
send_value!(node, value, timestep)
and got this error:
steve:~/.julia/v0.5/Reactive(sjk/node-call)$ julia5 ./test/runtests.jl
INFO: Recompiling stale cache file /home/steve/.julia/lib/v0.5/Reactive.ji for module Reactive.
Killing Task (runnable) @0x00007efb5a0528b0
fatal: error thrown and no exception handler available.
Base.AssertionError(msg="shift!(Workqueue).state == :queued")
rec_backtrace at /home/steve/Software/julia5/usr/bin/../lib/libjulia.so (unknown line)
jl_throw at /home/steve/Software/julia5/usr/bin/../lib/libjulia.so (unknown line)
wait at ./task.jl:359
task_done_hook at task.jl:173
jl_apply_generic at /home/steve/Software/julia5/usr/bin/../lib/libjulia.so (unknown line)
unknown function (ip: 0x7efd5c0deda6)
unknown function (ip: (nil))
JuliaLang/julia@312e65c made some changes to channels so I jumped back to before it was merged but got the same error.
System: Windows 8.1 (x64)
Julia: 0.4.0
when i use GLFW.PollEvents() and sleep(0.01) in a while loop it seems signals are not updated. sometimes it works and sometimes not. (this often happens when i move the glfw window. it just breaks and i get no more updates)
May its a common problem when using GLFW. Is there a workround for it?
I use signals to check a file update, it prints me a msg when i change the file.
Code:
function isUpdated(file::File, updatewhile=Reactive.Signal(true), update_interval=1.0)
fn = filename(file)
file_edited = foldp((false, mtime(fn)), fpswhen(updatewhile, 1.0/update_interval)) do v0, v1
time_edited = mtime(fn)
(!isapprox(0.0, v0[2] - time_edited), time_edited)
end
filter(identity, false, map(first, file_edited))
end
function watchFileUpdate(path::AbstractString, OnUpdate::Function)
map(isUpdated(query(path))) do _unused
println("OnUpdate: ", path)
end
end
As mentioned in #12 it's easy to think that React.jl has anything to do with Facebook's React. Now that this has been moved to JuliaLang organization, this may be a good time to reconsider changing the name. Possible names:
Any suggestions? cc @stevengj @StefanKarpinski @IainNZ @JuliaLang/admin
I would like to do real time signal processing in Julia. By this I mean a replacement for simulink (MATLAB) or LabView (NI). I would like to be able to take measurements, set up a processing chain and output the result.
Reactive looks like a nice framework for this processing. With the previous()
command most filtering configurations can be implemented. Ideally this could be integrated with DSP.jl (@simonster, @JayKickliter). Combined with AudioIO.jl (@ssfrr, @wherrera10) for input and output, I have proposed a basic acquisition example in AudioIO issues.
For my uses I need to process data at a minimum of a 1kHz rate. I know the processing time will depending on the complexity. But will Reactive.jl be a limiting factor?
My questions are
(edit: added processing rate requirements)
In #65 the consensus was that the exported name for Node
should be Signal
.
I am seeing:
Reactive.Input is deprecated, use Reactive.Node instead
Might be nice to define (in addition to what you have now):
push!{T}(inp::Input{T}, value) = convert(T, value)
instead of requiring the value
argument to have exactly the same type.
When I tried the following code on my MacOSX, Julia v0.4, I get an "ERROR: Timing is not defined." or "fpswhen is not defined". I understand that fpswhen is used in the lift step to control the acquisition timing of VideoIO.read, but I am not sure what I could do to make it work with the latest VideoIO package from Tim Holy. It would be nice to be able to do filtering and tracking on live video feed from the webcam. Is this problem due to the changes from React to Reactive? The same script worked for me last week with the previous version of VideoIO and when I had React (not Reactive).
VideoIO and ImageView are working fine since I can obtain video from the built-in camera using the f = VideoIO.opencamera() and img = read(f, image).
using ImageView
import ImageView
using VideoIO
import VideoIO
#Reactive should have replaced React by now
using GLPlot, Reactive, GLAbstraction
#VideoIO.DEFAULT_CAMERA_DEVICE
device = "Innebygd iSight"
format = VideoIO.DEFAULT_CAMERA_FORMAT
camera = VideoIO.opencamera(device, format)
img = VideoIO.read(camera)
# Just for fun, lets apply a laplace filter:
kernel = [-1 -1 -1;
-1 8 -1;
-1 -1 -1]
#async=true, for REPL use. Then you don't have to call renderloop(window)
window = createdisplay(#=async=true =#)
img = glplot(Texture(img, 3), kernel=kernel, filternorm=0.1f0)
#Get Gpu memory object
glimg = img.uniforms[:image]
#Asynchronous updating with React:
lift(Timing.fpswhen(window.inputs[:open], 30.0)) do x
newframe = VideoIO.read(camera)
update!(glimg, mapslices(reverse, newframe, 3)) # needs to be mirrored :(
end
renderloop(window)
Starting in the Example: A stupid line-droid section.
Is it simple to implement an optional stop signal for every lift?
Background: if I animate a large array, e.g. particles, it would be great if I can stop it at some point and clean up the resources.
Similar thing for cameras. It is sometimes simpler to just stop one camera and create a new one, instead of trying to recycle a pool of cameras.
Best,
Simon
Difference code from the introduction results in bounds error. When this line
diff = lift(x->x[1], foldl(difference, 0.0, signal))
is modified by providing a tuple as the initial fold value instead
diff = lift(x->x[1], foldl(difference, (0.0, 0.0), s))
then everything seems to work.
Hi,
just wanted to check, that this the is intended behavior:
julia> a = Input(0)
julia> b = Input(false)
julia> keepwhen(b, 0, a)
julia> c = keepwhen(b, 9, a)
julia> println(c)
DropWhen{Int64}(0x0000000000000017,Signal[],Lift{Bool}(0x0000000000000016,Signal
[],(anonymous function),(Input{Bool}(0x0000000000000013,Signal[Lift{Bool}(0x0000
000000000014,Signal[],(anonymous function),(Input{Bool}(#= circular reference =#
),),true),Lift{Bool}(#= circular reference =#)],false),),true),Input{Int64}(0x00
00000000000012,Signal[DropWhen{Int64}(0x0000000000000015,Signal[],Lift{Bool}(0x0
000000000000014,Signal[],(anonymous function),(Input{Bool}(0x0000000000000013,Si
gnal[Lift{Bool}(#= circular reference =#),Lift{Bool}(0x0000000000000016,Signal[]
,(anonymous function),(Input{Bool}(#= circular reference =#),),true)],false),),t
rue),Input{Int64}(#= circular reference =#),9),DropWhen{Int64}(#= circular refer
ence =#)],9),9)
The circular references seem weird, and I think on some platform it crashes, when you try to print this.
Best,
Simon
Passing in the right types to lift
, foldl
and flatten
(and finally resorting to Any
) in these lines caused me a lot of distress. This was mainly because a signal of type Board{true}
will not update to Board{false}
, and you are forced to annotate the type in each node in the subgraph.
This has got me wondering if there is any use to having the default type be the tightest possible type depending on the initial value in lift
, foldl
and flatten
. It would be useful if one could statically warn of potential errors due to wrong types, Julia does not do this anyway. I am inclining towards using Any
as default, and making tighter types as opt-in.
Also need consistency in the API for specifying types. I am thinking a typ
keyword argument for lift
, foldl
and flatten
can be consistent.
@stevengj @SimonDanisch what do you think of this?
In the Maintaining State section a copy-paste of the leading
definition generates an error
julia> leading = lift((a, b) -> if a > b ? :Alice : a < b ? :Bob : :Tie, alice, bob)
ERROR: syntax: unexpected ,
Wouldn't it be better to use Base.UUID
to match IPython?
From worker 3: MethodError: `filter` has no method matching filter(::Function, ::Bool, ::Bool)
From worker 3: Closest candidates are:
From worker 3: filter{T}(::Function, ::Any, !Matched::Reactive.Signal{T})
From worker 3: filter(::Any, ::Any)
From worker 3: filter(::Any, !Matched::Array{T,1})
using:
eventloop = fpswhen(true,7)
Hi,
I made a little benchmark, to see how big the performance gap is between React and "unrolled" code.
Here's the code
https://gist.github.com/SimonDanisch/fe5eaa964a5a1c197f01
Results:
unrolled: 6.8611264019997655e-6
React: 6.653197434700169e-5
Which isn't too bad, considering what React does.
I'm wondering, if my benchmark code is a good comparison though.
Also, I want to start a discussion on how to make React faster ;)
Maybe we can start to emit customized code, instead of putting the lifts in data structures?
PackageEvaluator.jl is a script that runs nightly. It attempts to load all Julia packages and run their tests (if available) on both the stable version of Julia (0.3) and the nightly build of the unstable version (0.4). The results of this script are used to generate a package listing enhanced with testing results.
Tests pass.
Tests fail.
This issue was filed because your testing status became worse. No additional issues will be filed if your package remains in this state, and no issue will be filed if it improves. If you'd like to opt-out of these status-change messages, reply to this message saying you'd like to and @IainNZ will add an exception. If you'd like to discuss PackageEvaluator.jl please file an issue at the repository. For example, your package may be untestable on the test machine due to a dependency - an exception can be added.
Test log:
>>> 'Pkg.add("Reactive")' log
INFO: Cloning cache of Reactive from git://github.com/JuliaLang/Reactive.jl.git
INFO: Installing FactCheck v0.2.7
INFO: Installing Reactive v0.2.0
INFO: Package database updated
>>> 'Pkg.test("Reactive")' log
INFO: Testing Reactive
ERROR: LoadError: LoadError: LoadError: syntax: local declaration in global scope
in include at ./boot.jl:254
in include_from_node1 at ./loading.jl:133
in reload_path at ./loading.jl:157
in _require at ./loading.jl:69
in require at ./loading.jl:52
in include at ./boot.jl:254
in include_from_node1 at ./loading.jl:133
in include at ./boot.jl:254
in include_from_node1 at loading.jl:133
in process_options at ./client.jl:304
in _start at ./client.jl:404
while loading /home/vagrant/.julia/v0.4/Reactive/src/Reactive.jl, in expression starting on line 33
while loading /home/vagrant/.julia/v0.4/Reactive/test/basics.jl, in expression starting on line 2
while loading /home/vagrant/.julia/v0.4/Reactive/test/runtests.jl, in expression starting on line 1
==============================[ ERROR: Reactive ]===============================
failed process: Process(`/home/vagrant/julia/bin/julia --check-bounds=yes --code-coverage=none --color=no /home/vagrant/.julia/v0.4/Reactive/test/runtests.jl`, ProcessExited(1)) [1]
================================================================================
INFO: No packages to install, update or remove
ERROR: Reactive had test errors
in error at ./error.jl:21
in test at pkg/entry.jl:746
in anonymous at pkg/dir.jl:31
in cd at file.jl:22
in cd at pkg/dir.jl:31
in test at pkg.jl:71
in process_options at ./client.jl:280
in _start at ./client.jl:404
>>> End of log
It seems to create a signal of negatively accumulated timestamps instead of a Δt values
julia> using Reactive
julia> lift((delta) -> println(delta), fps(0.5))
1.437081000427725e9
nothing
julia> -1.4370810026088e9
-2.8741620071283436e9
-4.311243013650205e9
-5.74832402217328e9
-7.185405032698582e9
tested in Julia 0.3.10
For example, to delay a signal -
function delay_func(state, value)
older_value, prev_value = state
return (prev_value, value)
end
delay(init_value, signal) = map(x -> x[1], foldl(delay_func, (0, init_value), signal))
It seems that older_value
is unnecessary. To compare with Elm,
delay init_value signal = foldp (\value state -> value) init_value signal
One way around is to define a foldp
using foldl
, but then I wonder why foldl
and its extra state is needed in the first place.
julia> versioninfo()
Julia Version 0.4.0-dev+4319
Commit ef06211* (2015-04-17 03:26 UTC)
Platform Info:
System: Darwin (x86_64-apple-darwin13.4.0)
CPU: Intel(R) Core(TM)2 Duo CPU P7350 @ 2.00GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Penryn)
LAPACK: libopenblas
LIBM: libopenlibm
LLVM: libLLVM-3.6.0
julia> using Reactive
WARNING: uint(x) is deprecated, use UInt(x) instead.
in depwarn at ./deprecated.jl:40
in uint at no file
in anonymous at no file
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
in reload_path at ./loading.jl:153
in _require at ./loading.jl:68
in require at ./loading.jl:52
ERROR: LoadError: MethodError: `start` has no method matching start(::Type{Reactive.Signal{T}})
in append_any at no file
in include at ./boot.jl:250
in include_from_node1 at ./loading.jl:129
in reload_path at ./loading.jl:153
in _require at ./loading.jl:68
in require at ./loading.jl:52
while loading /Users/Administrator/.julia/v0.4/Reactive/src/Reactive.jl, in expression starting on line 63
Since the only operations on children
that you seem to need are push!
and iterating over elements, a Set
seems like overkill (it introduces the overhead of a hash table, which is only useful if you want fast inclusion testing).
When using signals heavily, it quickly becomes very annoying that only one signal can update at a time. What is the reason for this? I understand that you have to detect the same signal updating recursively, but why can't multiple independent signals update simultaneously? @shashi
It looks worrisome that push!
updates everything in a global roots
array. This seems like it will scale badly.
Surely, pushing a value to an input should only affect the signals that depend on that input. Aren't you already storing the dependency DAG via the children
field etcetera?
The following code runs fine under Julia 0.3.10 but it produces an error under Julia 0.4.0
using Interact, Reactive, Gadfly
sl_β = slider(0:1:50, label="Npoints")
display(sl_β) #displays the slider at the output of the current cell
#tie the slider with the plotting routine
plt_pa = lift(β->begin
plt_pagw = plot(x=rand(β),y=rand(β),Geom.point, Geom.line)
end,sl_β)
The output in Julia 0.4.0 is
UndefVarError: Patchable not defined
in anonymous at D:\JuiliaPackages\v0.4\Gadfly\src\Gadfly.jl:891
in lift at D:\JuiliaPackages\v0.4\Reactive\src\Reactive.jl:364
in writemime at D:\JuiliaPackages\v0.4\Gadfly\src\Gadfly.jl:891
in sprint at iostream.jl:206
in display_dict at D:\JuiliaPackages\v0.4\IJulia\src\execute_request.jl:39
I'm running this on the release of Julia 0.4.0 and I have checked out the Interact.jl master - here's the specific package versions I'm using
- Gadfly 0.3.17
- IJulia 1.1.7
- Interact 0.2.1+ master
- Patchwork 0.1.8
- Reactive 0.2.4
Thanks for having a look into this!
It is helpful to have function which:
See:
http://reactivex.io/
https://github.com/GPars/GPars
http://hopac.github.io/Hopac/Hopac.html
https://github.com/reactor/reactor
Hey guys,
i've tried to install GLPlot but always got the error:
Pkg.test("GLPlot")
ERROR: `lift` has no method matching lift(::Function, ::Type{Vector2{Float64}}, ::Input{Vector2{Float64}}, ::Input{Vector4{Int64}})
in createwindow at /Users/Max/.julia/v0.3/GLWindow/src/reactglfw.jl:359
in createdisplay at /Users/Max/.julia/v0.3/GLPlot/src/GLPlot.jl:51
in include at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in include_from_node1 at loading.jl:128
in process_options at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in _start at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
while loading /Users/Max/.julia/v0.3/GLPlot/test/runtests.jl, in expression starting on line 3
So i did a Pkg.test("Reactive") and got this message:
INFO: Testing Reactive
Basic checks
- lift
InexactError()
in push! at /Users/Max/.julia/v0.3/Reactive/src/Reactive.jl:261
in anonymous at /Users/Max/.julia/v0.3/FactCheck/src/FactCheck.jl:178
in do_fact at /Users/Max/.julia/v0.3/FactCheck/src/FactCheck.jl:201
in anonymous at /Users/Max/.julia/v0.3/Reactive/test/basics.jl:177
in context at /Users/Max/.julia/v0.3/FactCheck/src/FactCheck.jl:341
in anonymous at /Users/Max/.julia/v0.3/Reactive/test/basics.jl:15
in facts at /Users/Max/.julia/v0.3/FactCheck/src/FactCheck.jl:315
in include at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in include_from_node1 at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in include at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in include_from_node1 at loading.jl:128
in process_options at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in _start at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
- merge
- foldl
- filter
- sampleon
- droprepeats
- dropwhen
28 facts verified.
trylift
- trylift
5 facts verified.
Call counting
600 facts verified.
push! inside push!
push! called when another signal is still updating.
in push! at /Users/Max/.julia/v0.3/Reactive/src/Reactive.jl:257
in crash at /Users/Max/.julia/v0.3/Reactive/test/concurrency.jl:7
in update at /Users/Max/.julia/v0.3/Reactive/src/Reactive.jl:95
in push! at /Users/Max/.julia/v0.3/Reactive/src/Reactive.jl:286
in anonymous at /Users/Max/.julia/v0.3/FactCheck/src/FactCheck.jl:178
in do_fact at /Users/Max/.julia/v0.3/FactCheck/src/FactCheck.jl:201
in anonymous at /Users/Max/.julia/v0.3/Reactive/test/concurrency.jl:177
in facts at /Users/Max/.julia/v0.3/FactCheck/src/FactCheck.jl:315
in include at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in include_from_node1 at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in include at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in include_from_node1 at loading.jl:128
in process_options at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
in _start at /Applications/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib
1 fact verified.
@lift
- @lift input expressions
- @lift basics
- @lift inside a function
7 facts verified.
Flatten
- Signal{Signal} -> flat Signal
- Initial update count
- Current signal updates
- Signal swap
11 facts verified.
INFO: Reactive tests passed
INFO: No packages to install, update or remove
I'm using Julia 0.3.8 on my Macbook with OS X Yosemite installed.
Maybe you could help to find a solution.
Thanks Max
Consider a hypothetical text box which has a character counter and an upper limit on the number of characters (and possibly also a pattern matcher to validate input). Now we want to be able to create a signal which can represent both valid and invalid input. This can be done nicely with an Either
type
I am thinking of introducing a variation of the Either type called Try
:
abstract Try{T}
immutable Success{T} <: Try{T}
value::T
end
success(T, value) = Success{T}(value)
immutable Failure{T} <: Try{T}
value::Exception
end
failure(T, value) = Failure{T}(value)
get(t::Try) = t.value
A text box described above could give out a signal of Try{String}
values. Further, it can define the type
immutable TooLong <: Exception
value::String
end
Now, a valid update would result in a Success{String}("text here")
value on which you can call get
to get the string. an invalid string can result in a Failure{String}(TooLong("longer text here"))
.
Can these types be any better? Are there any better ways to handle invalid values?
cc @stevengj
My code runs through perfectly on first pass (inside an Escher page request). The next time I refresh the page all hell breaks loose.
It looks like
Using Type:
immutable recordingUpdate
sess::Base.Random.UUID
prop::Symbol
value::Any
dt::DateTime
end
And signal:
Signal(recordingUpdate, recordingUpdate(Base.Random.uuid4(),:status,"BOOTED",now()))
After a while, (indeterminate time) this happens:
Failed to push!
recordingUpdate(29c04b23-aa04-4b17-81a4-5fb1479246f1,:label,"END",2016-03-09T18:39:51)
to node
WeakRef(Signal{recordingUpdate}(recordingUpdate(29c04b23-aa04-4b17-81a4-5fb1479246f1,:label,"END",2016-03-09T18:39:51), nactions=1))
MethodError: `convert` has no method matching convert(::Type{Void}, ::recordingUpdate)
This may have arisen from a call to the constructor Void(...),
since type constructors fall back to convert methods.
Closest candidates are:
call{T}(::Type{T}, ::Any)
convert{T}(::Type{T}, !Matched::T)
Void()
in send_value! at /home/a/.julia/v0.4/Reactive/src/core.jl:128
in anonymous at /home/a/.julia/v0.4/Reactive/src/operators.jl:37
in do_action at /home/a/.julia/v0.4/Reactive/src/core.jl:135
in send_value! at /home/a/.julia/v0.4/Reactive/src/core.jl:130
in send_value! at /home/a/.julia/v0.4/Reactive/src/core.jl:133
in run at /home/a/.julia/v0.4/Reactive/src/core.jl:190
in run at /home/a/.julia/v0.4/Reactive/src/core.jl:181
[inlined code] from /home/a/.julia/v0.4/Reactive/src/core.jl:228
in anonymous at task.jl:447
I added this to core:
function send_value!(node::Signal, x, timestep)
# Dead node?
!node.alive && return
# Set the value and do actions
if string(typeof(x)) == "recordingUpdate"
remotecall(print,1,typeof(node.value),typeof(x))
end
node.value = x
for action in node.actions
do_action(action, timestep)
end
end
And it turns out the Signals are doubling up (notice the Void):
**recordingUpdaterecordingUpdateVoidrecordingUpdate**Failed to push!
recordingUpdate(88c3f609-4ca8-40dc-99ec-ba9f9227d3e6,:label,"BLACK",2016-03-09T19:42:15)
to node
WeakRef(Signal{recordingUpdate}(recordingUpdate(88c3f609-4ca8-40dc-99ec-ba9f9227d3e6,:label,"BLACK",2016-03-09T19:42:15), nactions=1))
MethodError: `convert` has no method matching convert(::Type{Void}, ::recordingUpdate)
This may have arisen from a call to the constructor Void(...),
since type constructors fall back to convert methods.
Closest candidates are:
call{T}(::Type{T}, ::Any)
convert{T}(::Type{T}, !Matched::T)
Void()
in send_value! at /home/a/.julia/v0.4/Reactive/src/core.jl:131
in anonymous at /home/a/.julia/v0.4/Reactive/src/operators.jl:37
in do_action at /home/a/.julia/v0.4/Reactive/src/core.jl:138
in send_value! at /home/a/.julia/v0.4/Reactive/src/core.jl:133
in send_value! at /home/a/.julia/v0.4/Reactive/src/core.jl:136
in run at /home/a/.julia/v0.4/Reactive/src/core.jl:193
in run at /home/a/.julia/v0.4/Reactive/src/core.jl:184
[inlined code] from /home/a/.julia/v0.4/Reactive/src/core.jl:231
in anonymous at task.jl:447
After further tests, I can confirm I'm only calling the method push! once so I think this is definitely a bug.
Hi,
Maybe I'm just missing something obvious, but I'm not able to get the "lift" part of the tutorial working. I'd really like to use it! I've tried on Julia 0.3.8/10 and 0.4-dev
#40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015
$ ./julia-dev
...
Version 0.4.0-dev+5696 (2015-06-29 15:30 UTC)
Commit 1544e4e* (0 days old master)
x86_64-unknown-linux-gnu
julia> Pkg.add("Reactive")
INFO: Initializing package repository /home/dehann/.julia/v0.4
INFO: Cloning METADATA from git://github.com/JuliaLang/METADATA.jl
INFO: Installing Compat v0.4.6
INFO: Installing FactCheck v0.2.8
INFO: Installing Reactive v0.2.2
INFO: Package database updated
julia> using Reactive
julia> x = Input(0)
0
julia> xsqr = lift(a -> a*a, Int, x)
ERROR: MethodError: consume
has no method matching consume(::Function, ::Type{Int64}, ::Reactive.Input{Int64})
Closest candidates are:
consume(::Task, ::Any...)
consume(::Union{DataType,Function}, ::Reactive.Signal{T}...)
consume(::Union{DataType,Function}, ::Reactive.SignalSource...)
in lift at /home/dehann/.julia/v0.4/Reactive/src/Reactive.jl:362
Thanks,
Dehann
Since you are doing a foldl
operation, you should call the function this. Also, it would be nice to mimic the Base.foldl
function in making v0
optional (if it is not given, you initialize with the current value of the signal.)
You should probably also have a foldr
function for completeness.
Not sure if this should go on the mailing list instead, but what is the correct pattern to propagate changes from one input to another? I tried this:
using Reactive
a = Input(0)
b = Input(0)
lift(x -> push!(a,x), b)
But with push!(b, 1)
I get the error "push! must be called asynchronously".
In http://julialang.org/Reactive.jl/index.html#do-you-even-lift:
julia> xsquared = lift(a -> a*a, Int, x)
4
julia> typeof(xsquared)
Lift{Int64} (constructor with 1 method)
julia> super(Lift{Int64})
ERROR: Lift not defined
Lift
does not seem to be exported.
Hi,
I've been speaking about this with Shashi, but I think so far I haven't had good examples, so the conclusion was mostly, that I'm using react wrong.
I did some more thinking, and I came to the conclusion, that we really need some mechanisms, to connect different react graphs, as you can't always construct the whole graph.
Example:
In an API I want to offer, to make a shader out of some string signal. But at shader creation, I don't want to force the user to decide, from which string signal he wants to create the shader.
function makeshader(defaultsource::String)
sourcecode = ascii(defaultsource)
dummyInput = Input(sourcecode)
lift(dummyInput) do sourcecode
... Make new shader
... Delete old shader
return shader
end
return dummyInput # return "socket" to which one can connect
end
# At initializsation, by some API, somewhere, where the user has no access
shader = makeshader(SomeShaderSource)
# At a different time point, user wants to interact with the shader, namely updating it
newsource = lift(x -> readall(open("filename")), every(1.0)) # this is just exemplary and a really wasteful way of doing this
# Now, this doesn't work in the current API:
lift(x-> push!(shader, x), newsource)
# So something like this is needed!?
connect(shader.dummyInput, newsource)
Another example:
I'm working on widgets for my plots.
The data for a plot in GLPlot looks a little like this:
[
:attributename => Input(someValue)
:attributname => SomeLift
....
]
Now, at the part where I initialize this datastructure, I don't even remotely know, if the person wants to change the value via a my glwidgets, via the commandline with push!(), or if someone builds, for example, some tk wrapper.
Best,
Simon
Why bother passing time()
when the dependencies are updated? I don't understand the need for this.
See: https://travis-ci.org/shashi/React.jl/builds/27664969. The problem seems to be that Base.foldl and Base.foldr are not getting imported in the juliareleases build environment. This doesn't fail in julianightlies build environment.
I would suggest defining it as:
lift(f::Function, output_type::Type, inputs::Signal...)
so that:
Function
argument first allows one to use do
-block syntax with lift
.Type
rather than DataType
allows functions that return tuples of types.It would eventually be nice to have:
valtype{T}(::Signal{T}) = T
lift(f::Function, inputs::Signal...) = lift(f, return_type(f, tuple(map(valtype, inputs))), inputs...)
so that you don't need to specify the return type if Julia can infer it. The return_type
functionality is not in Julia yet, though; see JuliaLang/julia#6692
Julia Version 0.4.3
WARNING: New definition
map(Any, Reactive.Signal...) at /home/ul/.julia/v0.4/Reactive/src/operators.jl:26
is ambiguous with:
map(Function, Lazy.List...) at /home/ul/.julia/v0.4/Lazy/src/liblazy.jl:98.
To fix, define
map(Function)
before the new definition.
WARNING: New definition
map(Any, Reactive.Signal...) at /home/ul/.julia/v0.4/Reactive/src/operators.jl:26
is ambiguous with:
map(DataType, Lazy.List...) at /home/ul/.julia/v0.4/Lazy/src/liblazy.jl:99.
To fix, define
map(DataType)
before the new definition.
I'm pretty interested in learning more about this, but since I don't speak javascript, http://facebook.github.io/react/ isn't very useful to me as documentation, and neither is http://library.elm-lang.org/catalog/evancz-Elm/0.12/Signal. Is there another source for this? Or can the README be expanded?
One small point: in your current README, the Usage section seems to contain a mix of material that mimics "declarations" and code one might actually type. So for example, it's not entirely obvious that Signal{T}
is something that's defined in React.jl code. Perhaps a clearer separation between API-documentation and demo would be helpful?
I'm trying to keep a .jl process running when i run julia xxxx.jl with the signals running Ie s = fps(3) then a map(s) ...
But julia always exits, is there something to help me keep the process alive?
Thanks
A
says :
Reactive programming primitives for Julia http://julialang.github.io/React.jl/
Should update the URL, but I don't have the right to.
julia> sensor_input = Input([0.0, 1.0, 0.0])
3-element Array{Float64,1}:
0.0
1.0
0.0
julia> left_motor = @lift sensor_input[1] - sensor_input[3]
ERROR: MethodError: `getindex` has no method matching getindex(::Reactive.Input{Array{Float64,1}}, ::Int64)
in anonymous at no file
in lift at no file
PackageEvaluator.jl is a script that runs nightly. It attempts to load all Julia packages and run their tests (if available) on both the stable version of Julia (0.2) and the nightly build of the unstable version (0.3). The results of this script are used to generate a package listing enhanced with testing results.
Tests pass.
Tests fail, but package loads.
Tests pass.
means that PackageEvaluator found the tests for your package, executed them, and they all passed.
Tests fail, but package loads.
means that PackageEvaluator found the tests for your package, executed them, and they didn't pass. However, trying to load your package with using
worked.
This issue was filed because your testing status became worse. No additional issues will be filed if your package remains in this state, and no issue will be filed if it improves. If you'd like to opt-out of these status-change messages, reply to this message saying you'd like to and @IainNZ will add an exception. If you'd like to discuss PackageEvaluator.jl please file an issue at the repository. For example, your package may be untestable on the test machine due to a dependency - an exception can be added.
Test log:
INFO: Cloning cache of React from git://github.com/shashi/React.jl.git
INFO: Installing React v0.1.2
INFO: REQUIRE updated.
Warning: could not import Base.foldl into React
Warning: could not import Base.foldr into React
Warning: could not import Base.foldl into React
Warning: could not import Base.foldr into React
ERROR: wrong number of arguments
in include at boot.jl:238
at /home/idunning/pkgtest/.julia/v0.2/React/tests/basics.jl:13
at /home/idunning/pkgtest/.julia/v0.2/React/tests/test.jl:1
INFO: REQUIRE updated.
Seems to be missing?
I was having issues with Reactive, where a map/lift command was not running consistently, and eventually error messages about a queue being filled appeared. Adding yield
to the code generating the data appears to have resolved the data. (I suppose map/lift runs as an @async
process and so yield
is needed for it to run.)
I'd suggest this is added to the tutorial as it took me a bit of guessing to determine the issue.
I find the lift(x -> foo(x), y)
syntax a little awkward. What you really want to do is to be able to just write foo(y)
and have it automatically create a Lift
.
Doing that directly seems too hard, because it would involve overriding every conceivable function to have Signal
variants. But something like this could be accomplished by a macro:
x = Input(3)
y = Input(7)
@lift x + y - 5*sin(x)
What the @lift
macro would do would be to walk the expression tree, and any symbol that it finds corresponding to a defined value of type <: Signal
would get converted into a function parameter in a call to lift
.
It's a little tricky to get the metaprogramming right here, but I think it should be do-able and will make this a lot easier to use.
Hi, this lib (and Interact etc.) rock - thank you so much!
Small bug it seems, try this:
using Reactive
input1 = Input("yah")
input2 = Input("nah")
merge(input1, input2)
`convert` has no method matching convert(::Type{Char}, ::ASCIIString)
while loading In[1], in expression starting on line 4
in Merge at .../.julia/v0.3/Reactive/src/Reactive.jl:171
in merge at .../.julia/v0.3/Reactive/src/Reactive.jl:372
Reactive:372 is
merge(signals::Signal...) = Merge{join_eltype(map(eltype, signals)...)}(signals)
As it turns out Base.join_eltype calls eltype itself, so eltype
is being called twice (per signal), first on the signal in the map, returning String
, then again on String
, returning Char
(eltype(String)
returns Char
), resulting in Merge{Char}
being called with ASCIIString
signals. This wouldn't have come up for Numbers etc. because eltype seems to just return the argument provided to it for Int, Real, Float64, etc., e.g. eltype(Int64)
returns Int64
Accordingly, changing Reactive:372 to
merge(signals::Signal...) = Merge{join_eltype(signals...)}(signals)
fixes it.
Keep up the good work!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.