Giter VIP home page Giter VIP logo

gjallarhorn's People

Contributors

bcachet avatar dsyme avatar foggyfinder avatar forki avatar jeroldhaas avatar johanlarsson avatar majocha avatar mattstermiller avatar mtnrbq avatar pblasucci avatar reedcopsey avatar s952163 avatar teadrivendev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gjallarhorn's Issues

Possible crash issue in BoundCollection

Removing many items in one pass appears to have the potential to cause BoundCollection to throw.

Loading the collection sample, and turn off processing. Select multiple items to process, then turn back on after waiting at least 10 sec. This seems to reproduce.

I'm not sure if the internal collection should actually remove the items on RNCC instead of immediately, or if there's a better solution here. I'd prefer not to have to do a reset anytime >1 remove message is being processed.

Sample application loses validation tracking

After a period of time, the validation stops working -

I suspect there's an issue with something in how the validation tracking occurs. Something is losing the signal along the way.

Exception handling

What would be the preferred method for managing exceptions?

One option would be to go the route of observables, and have Subscription methods accept an error handling function. This would also make it easy to make functions that split a signal into two in the case of an exception - with an IObservable being passed out in the case of an exception for easy handling.

Elm module

Hello,

I have written a module based on Gjallarhorn to write WPF application in a Unidirectional Flow approach (like Elm)

namespace Elm

open Gjallarhorn
open Gjallarhorn.Bindable
open Gjallarhorn.Wpf

open System

type ViewBinding<'model, 'msg> = BindingSource -> ISignal<'model> -> IObservable<'msg> option
type ViewBindings<'model, 'msg> = ViewBinding<'model, 'msg> list


module ViewBindings =
    let toComponent (viewBindings : ViewBindings<'model, 'msg>) : Component<'model, 'msg> =
        (fun source model ->
        viewBindings
        |> List.map (fun vb -> (vb source model))
        |> List.where Option.isSome
        |> List.map Option.get)



module Bindings =
    let private wrapRO getter f : ViewBinding<'model, 'msg> = 
        (fun (source : BindingSource) (model : ISignal<'model>) ->
                model
                |> Signal.map getter
                |> (f source)
                None)

    let private wrapRW getter setter f : ViewBinding<'model, 'msg> = 
        (fun (source : BindingSource) (model : ISignal<'model>) ->
            model
            |> Signal.map getter
            |> (f source)
            |> Observable.filter Option.isSome
            |> Observable.map Option.get
            |> Observable.map setter
            |> Some)

    let vm (getter : 'model -> 'a) (setter : 'b -> 'msg) (comp : ViewBindings<'a, 'b>) name : ViewBinding<'model, 'msg> =
        wrapRW getter setter (fun source  model-> Gjallarhorn.Bindable.Binding.componentToView source name (ViewBindings.toComponent comp) model |> Observable.map Some)

    let vmCollection getter setter (comp : ViewBindings<'a, 'b>) name : ViewBinding<'model, 'msg> = 
        (fun source (model : ISignal<'model>) ->
            let models = model |> Signal.map (getter >> Seq.mapi (fun i m -> m, i))
            let c s m = ViewBindings.toComponent comp s (Signal.map fst m)
            BindingCollection.toView source name models c 
            |> Observable.map (fun (msg,(m, id)) -> setter msg id)
            |> Some)

    let oneWay getter name : ViewBinding<'model, 'msg> =
        wrapRO getter (fun source -> Gjallarhorn.Bindable.Binding.toView source name)
        
    let twoWayConverted getter setter conversion name : ViewBinding<'model, 'msg> =
        wrapRW getter setter (fun source -> Binding.toFromViewValidated source name conversion)
        
    let twoWayValidated getter setter name : ViewBinding<'model, 'msg> =
        twoWayConverted getter setter Gjallarhorn.Validation.Converters.fromTo name

    let twoWay getter setter name : ViewBinding<'model, 'msg> =
        wrapRW getter setter (fun source model -> Binding.toFromView source name model |> Observable.map Option.Some)

    let cmd msg name : ViewBinding<'model, 'msg> =
        (fun (source : BindingSource) (model : ISignal<'model>) ->
            Gjallarhorn.Bindable.Binding.createMessage name msg source
            |> Some)

    let cmdIf msg canExecute name : ViewBinding<'model, 'msg> =
        (fun (source : BindingSource) (model : ISignal<'model>) ->
            Gjallarhorn.Bindable.Binding.createMessageChecked name (model |> Signal.map canExecute) msg source
            |> Some)

module App =            
    let app init update bindings : Framework.ApplicationCore<'model, 'msg> =
        Framework.basicApplication init update (bindings|> ViewBindings.toComponent)

    let run window app =
        Framework.runApplication System.Windows.Application window app

Complete code of the module and example of its usage can be found on https://github.com/bcachet/ElmAppliedToWPF

What do you think of this wrapper/module ?
Do I use Gjallarhorn correctly in this scenario ?

By showing you this module, I hope to:

  • improve my Gjallarhorn usage
  • get feedback on my approach

Have a nice day

Bertrand

Use FsCheck for more thorough testing

Many of the tests could be done via FsCheck, which would allow much better test coverage and help prevent edge cases from creeping in.

Would be nice to integrate this into the current nunit tests (even if nunit has issues with fscheck integration)

Subscriptions fire when mutable is set to same value

When a mutable is set to the same value as its current value, the subscriptions on it still fire, and mutables defined as maps of it are also set again, which causes subscriptions on them to fire.

This is not on the latest version of Gjallarhorn and I will update this post to confirm whether the issue still exists when we are able to upgrade to the latest.

Validation issue in Binding.mutateToFromViewValidated

Hi,

I'm not sure that this is really the issue or I'm missing something important.

When I use Binding.mutateToFromViewValidated to bind mutable with some validation rule and the input is invalid the red border doesn't appear for the text box. The validation itself seems to be working.

I've created sample project to illustrate - https://github.com/kirill-gerasimenko/TestMutateValidation
There are two textboxes, one is bound using Binding.mutateToFromViewValidated, other by using Binding.toFromViewValidated, they share the same validation rule. Former doesn't show validation error, the latter does.

Would you be able to have a look at this?

Kirill

Build failure

After a fresh clone of the git repoistory, I ran build.cmd from Powershell. But I get several build errors:

Gjallhorn-build.txt

I have "Microsoft Visual C++ Build Tools" version 14.0.25420.1 installed, which is what it seems gets used for the build command.

> cd "C:\Program Files (x86)\MSBuild\14.0\Bin\"
> .\MSBuild.exe /version
Microsoft (R) Build Engine version 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.

14.0.25420.1

I also have VS 2017 (along with the build tools) and dotnet installed:

> Get-VSSetupInstance

InstanceId          : 1eff422b
DisplayName         : Visual Studio Community 2017
InstallationVersion : 15.0.26430.16
InstallationPath    : C:\Program Files (x86)\Microsoft Visual Studio\2017\Community
InstallDate         : 2017-06-28 6:37:15 PM

InstanceId          : d49f017f
DisplayName         : Visual Studio Build Tools 2017
InstallationVersion : 15.0.26430.16
InstallationPath    : C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools
InstallDate         : 2017-07-22 2:00:32 PM
> dotnet --version
1.0.4

.Add notifies even when underlying value has not changed

Related to #56 but simpler:

let x = Mutable.create false
x.Add(fun b -> Debug.WriteLine(sprintf "x is now %b" b))
x.Value <- false // does nothing, as expected, because x has not changed

let y = Mutable.create -1
let z = y |> Signal.map (fun y -> y < 0)
z.Add(fun b -> Debug.WriteLine(sprintf "z is now %b" b))
y.Value <- -2 // prints "z is now true", unexpectedly
y.Value <- -3 // prints "z is now true", unexpectedly

Improve workflow around packaging nuget

Right now, I'm doing the nuget packages manually.

I'd like to have templates built out for paket to package these together.

Currently, 3 packages are created - Gjallarhorn, for the core project, Gjallarhorn.Bindable for the binding projects, then Gjallarhorn.Bindable.Wpf for the Wpf wrappers. The first 2 are PCL, the last .NET 4.5+.

Each requires the previous as a dependency, with the version number being the current version number.

My ideal here would be:

  • Enable paket pack on all three projects, so packages could be setup quickly
  • Integrate into FAKE build script so README.md changes propogate into paket templates
  • Add build target in FAKE to build/test/package/[push?]

Create Navigation system for Framework

The framework needs a mechanism to support navigation. I'd like open a discussion about the best way to approach this before I try to implement something.

My goals would include:

  • Allow current framework message system to "update" navigation status
  • Allow "pages" to be pushed/popped from the navigation system via the message
  • Allow each page to be tied to a component, which would allow them to be developed in isolation
  • Allow each platform to override provided default mechanism for swapping out "page" [ie: make this usable in WPF via windows/dialogs/etc, as well as Xamarin Forms]

I'd love feedback on needs/wants/etc in order to start brainstorming on the best approach here.

Should commands be IObservable instead of ISignal?

Right now, Commands typed as ISignal<CommandState>, where CommandState is a DU containing Unexecuted or Executed of DateTime, which allows you to look directly at the value to see whether it's been executed before.

In many ways, a command is really just a channel for events to flow into the VM, which is a better fit for an observable. Would it make more sense to drop the DU, and make the command IObservable<DateTime> (for parameterless commands) or IObservable<TParam> (for parameterized commands) instead?

Function in module `Binding`

In the module Binding no functions createCommandParam and createCommandParamChecked. I think it makes sense to add them.

I understand that there is a function createMessageParam , createMessageParamChecked which in most cases it will be convenient to use.

Should we add async commanding support?

Originally, I had planned to add support for async "commands", but I'm not sure it's necessary.

Since the command is really just a channel into the VM, there's nothing preventing starting an async operation explicitly. We could even potentially create a signal mapper that worked asynchronously, which would let you directly subscribe in an async manner.

The biggest advantage of building it in would be the ability to hook into the execution tracker automatically (which is already written, but unused currently). That could always be handled via the signal mapper, though.

I'd love to get input on this. Would you rather have a set of APIs for commands that are async directly, or just leave it more explicit?

Page with Sample tutorial is out of date

This page seems to be outdated. It is linked on the other pages as "GETTING STARTED / Sample tutorial". At least I cannot find the View module referenced, and it looks like it was later renamed to Signal.

http://reedcopsey.github.io/Gjallarhorn/tutorial.html

Is the last example on that page, with the computation expression - is that still usable in some form?

The page seems to have been replaced with the very similar page intro.htm (link below), so that the only remaining todo is to remove the page named tutorial.html, and the links to it from other pages. Perhaps the link can be replaced with a link to the examples in the repo instead.

http://reedcopsey.github.io/Gjallarhorn/intro.html

Synchronization problem in signal manager

SignalManager.Signal has a synchronization issue.

Since the dep.Signal call happens within the lock, it's possible for user code to create a deadlock if it tries to modify the signal.

Need to change to:

  • Lock to get dependencies
  • SIgnal (outside lock)
  • Lock, check HasDependencies, and remove if necessary

This should keep the locking separate from the signal mechanism, and prevent the deadlocks, while still having proper removal behavior.

Build doesn't produce NuGet packages

I wanted to build NuGet packages of Gjallarhorn (or preferably just use this as a NuGet souce via Paket), but apparently that doesn't work yet. I couldn't find out easily how NuGet creation via FAKE/Paket works, so I'll just put this here as a reminder for now.

I suppose you intend to have separate packages for the projects that build on each other; is that correct?

samples\WpfSimpleMvvmApplication.exe crashes when the `Do Async Op` button is clicked

samples\WpfSimpleMvvmApplication.exe crashes when the Do Async Op button is clicked

Other samples work. WpfSimpleMvvmApplication.exe works until Do Aysnc Op is clicked, then crashes with the following exception:

.\WpfSimpleMvvmApplication.exe
Names in "model" [1]: Recent [dsadssa dasdasd]

Unhandled Exception: System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.
at Microsoft.FSharp.Control.CancellationTokenOps.Start@1224-1.Invoke(Exception e)
at <StartupCode$FSharp-Core>.$Control.loop@425-40(Trampoline this, FSharpFunc2 action) at Microsoft.FSharp.Control.Trampoline.ExecuteAction(FSharpFunc2 firstAction)
at Microsoft.FSharp.Control.TrampolineHolder.Protect(FSharpFunc`2 firstAction)
at <StartupCode$FSharp-Core>.$[email protected](Object state)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Names in "model" [2]: Recent [adsadssa dasdasd]

Both in win7 and win10, built with VS2015. Let me know if you need further information.

Observable.Add(handler) to a ISignal doesn't execute the handle function when the property value has changed

As the title suggest, when trying to Observable.Add( handler ) there is an issue where, when changing the property binded to this Observable, the handler is not called.

This issue has been reproduced in the FSI by referencing only Gjallarhorn.dll.
The steps are the following :

run the following code line by line by sending it to F# interactive.
The last 3 lines, do not trigger any of the two observables handlers.


module test =
    type V = { A : int ; B : int }

    let v = Mutable.create { A = 0 ; B = 0 } 

    let a = v |> Signal.map (fun v -> v.A) 
    let b = v |> Signal.map (fun v -> v.B) 

    a |> Observable.add (fun a -> printfn "A changed to %d" a) 
    b |> Observable.add (fun b -> printfn "B changed to %d" b) 

    v.Value <- { v.Value with A = 12 } 
    v.Value <- { v.Value with B = 2 }
    v.Value <- {A = 5 ; B = 6} ```

Signal.map evaluations

y = Signal.map f x, f is evaluated each time y's value is asked for.
When x is changed, y is not updated immediately.

open Gjallarhorn
let x = Mutable.create 0
let f i = printf "processing"; i*i
let y = Signal.map f x // "processing" (expected)
printfn "x = %A" x.Value // nothing (expected)
printfn "y = %A" y.Value // "processing" (unexpected)
printfn "y = %A" y.Value // "processing" (unexpected)
x.Value <- 1 // nothing (unexpected)
printfn "y = %A" y.Value // "processingprocessing" (unexpected)
printfn "y = %A" y.Value // "processing" (unexpected)

Errors resulting from 'as self'

We see occasional errors from App Center resulting from use of as self.

System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.

I will try to remove these usages.

Errors in CoreTypes.fs

According to these comments
dotnet/fsharp#5286 (comment)

Because |> is a generic function, the rules state you can't have a byref<_> as a type arg

dotnet/fsharp#5270 (comment)

Local functions and lambdas cannot have byref-like parameters

there are now some restrictions when using byref.

Opening Gjallarhorn project in Rider or Visual Studio I'm getting a lot of errors:
image

The message is not very helpful

image

but it seems that partial application doesn't work with byref anymore.

This form makes the error go away:
image

Validators.containedWithin<RecordType> -> System.FormatException

type SomeRecord = { A : int }

testCase "contained within" <| fun () -> 
    let validValues = [4; 8; 15; 16; 23; 42] |> List.map (fun p -> { A = p })
    let value = Mutable.create <| List.last validValues
    let validated = 
        value 
        |> Signal.validate (Validation.Validators.containedWithin validValues)
    value.Value <- { A = -1 }
[22:11:55 ERR] gjallarhorn/validators/contained within errored in 00:00:00.2770000 <Expecto>
System.FormatException: Входная строка имела неверный формат.
   в System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
   в System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
   в Gjallarhorn.ValidationModule.validateWith[a](FSharpFunc`2 validator, ValidationCollector`1 step)
   в Gjallarhorn.ValidationModule.Validators.containedWithin[a](IEnumerable`1 collection, ValidationCollector`1 step)
   в [email protected](ValidationCollector`1 step) в ...\Gjallarhorn.Tests.fs:строка 64
   в Gjallarhorn.SignalModule.ValidatorMappingSignal`2.validateCurrent(a value)
   в Gjallarhorn.SignalModule.ValidatorMappingSignal`2.Update[a](a source)
   в <StartupCode$Gjallarhorn>[email protected](IDependent dep)
   в Gjallarhorn.Internal.WeakRef.execute[a](FSharpFunc`2 f, WeakReference`1 wr)
   в <StartupCode$Gjallarhorn>[email protected](WeakReference`1 wr)
   в Microsoft.FSharp.Collections.ArrayModule.Filter.createMask[a](FSharpFunc`2 f, a[] src, UInt32[]& maskArrayOut, UInt32& leftoverMaskOut)
   в Microsoft.FSharp.Collections.ArrayModule.Filter.filter[a](FSharpFunc`2 f, a[] src)
   в Microsoft.FSharp.Collections.ArrayModule.Filter[T](FSharpFunc`2 predicate, T[] array)
   в Gjallarhorn.Internal.DependencyTracker`1.signalAndUpdateDependencies(ISignal`1 source)
   в Gjallarhorn.Internal.DependencyTracker`1.MarkDirty(ISignal`1 source)
   в Gjallarhorn.Internal.SignalManager.Signal[a](ISignal`1 source)
   в Gjallarhorn.Internal.Dependencies.createRemote@247.Gjallarhorn-Internal-IDependencyManager`1-MarkDirty(ISignal`1 source)
   в Gjallarhorn.Internal.Mutable`1.set_Value(a value)
   в [email protected](Unit unitVar0) в ...\Gjallarhorn.Tests.fs:строка 65
   в [email protected](Unit unitVar)
   в Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvoke[T,TResult](AsyncActivation`1 ctxt, TResult result1, FSharpFunc`2 part2)
   в <StartupCode$FSharp-Core>[email protected](AsyncActivation`1 ctxt)
   в Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction)

Creating an invalid format string

Using

testCase "String.Format + string record" <| fun () -> 
    """{0} and """ + string { A = 0 }
    |> fun format -> 
        System.String.Format(format, 42)
    |> ignore
[22:38:37 ERR] gjallarhorn/validators/String.Format + string record errored in 00:00:00.1010000 <Expecto>
System.FormatException: Входная строка имела неверный формат.
   в System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
   в System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
   в System.String.Format(String format, Object arg0)
   в [email protected](Unit unitVar0) в ...\Gjallarhorn.Tests.fs:строка 68
   в [email protected](Unit unitVar)
   в Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvoke[T,TResult](AsyncActivation`1 ctxt, TResult result1, FSharpFunc`2 part2)
   в <StartupCode$FSharp-Core>[email protected](AsyncActivation`1 ctxt)
   в Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction)

InvalidOperationException in SignalBase

Don't know how it correctly to write, so I'll start with an example:

open Gjallarhorn

try

let value = Mutable.create 1
let final = value |> Signal.map (fun _ -> failwith "...")
value.Value <- 5

with
| _ as exp -> printfn "%A" exp.Message

An unhandled exception of type 'System.InvalidOperationException'
Additional information: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.

-> Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.FailInit()

-> Gjallarhorn.Internal.MappingSignal`2.OnDisposing()

-> Gjallarhorn.Internal.SignalBase`1.System-IDisposable-Dispose()

it's starts here due of the member this.Value


Some time ago I tried to deal with the causes but nothing came

What is blocking creating signals from the standard mutables

Hey I saw this and it looks really awesome, but I was curious what is basically preventing you from having a signal subscribe to a normal standard mutable.

Example

let mutable x = 0
Signal.Subscription.create (fun currentValue -> printfn "Value is now %d" currentValue) m 

// After this is set, a print will occur
// Prints: "Value is now 1"
m.Value <- 1

// After this is set, a second print will occur with the new value
// Prints: "Value is now 2"
m.Value <- 2

Create IReflectableType binding target implementation

This would allow the Gjallarhorn binding system to work with Xamarin Forms, and I believe Perspex, in addition to WPF.

It should be possible to build directly into the Bindable PCL library, and have this be the default creation if WPF isn't installed.

Unexpected subscription notifications

In a console app, if one manually creates a SynchronizationContext, then uses it with Signal.observeOn, then adds a subscription handler to the resulting signal with my_signal.Subscribe (....), it can get called more than expected. This does not happen if one uses Signal.Subscription.Create instead.

Repro:

open Gjallarhorn
open System.Threading

[<EntryPoint>]
let main argv =
  let m1 = Mutable.create 1L
  let m2 = Mutable.create 2L

  let sync_ctx = System.Threading.SynchronizationContext()

  printfn "Creating signal..."
  let signal =
    (m1, m2)
    ||> Signal.map2
      (fun a b ->
        printfn "A dependency has changed. Called from thread ID %d" (Thread.CurrentThread.ManagedThreadId)
        a + b)
    |> Signal.observeOn sync_ctx

  use _sub = signal.Subscribe (fun res -> printfn "Signal value is now %d. thread ID: %d" res (Thread.CurrentThread.ManagedThreadId))
  
  printfn "Setting m1..."
  m1.Value <- 2L

  printfn "Sleeping 200 ms"
  System.Threading.Thread.Sleep(200)
  printfn "Thread awake again"

  printfn "Setting m2..."
  m2.Value <- 3L

  printfn "Finished"
  System.Console.ReadLine() |> ignore
  0

Output

Creating signal...
A dependency has changed. Called from thread ID 1
Setting m1...
Sleeping 200 ms
A dependency has changed. Called from thread ID 3
Signal value is now 4. thread ID: 3
Signal value is now 4. thread ID: 4
Thread awake again
Setting m2...
Finished
A dependency has changed. Called from thread ID 5
Signal value is now 5. thread ID: 5
Signal value is now 5. thread ID: 3

In this case, the lines Signal value is now 4. thread ID: 4 and Signal value is now 5. thread ID: 3 are unexpected, and go away with the other approach mentioned. The number of signal recomputations look correct in both cases.

Question: 'Back propogation' from values

I use a similar library internally, but I also support descendant nodes updating their parents if a bidirectional linking operation is used to create them.

Does Gjallarhorn support anything similar to this?

Request for Feedback: Update

The basic framework for applications already makes threading very simple.

Some of the sample applications use thread-safe mutables for their internal state, which allows for completely thread safe pushing of update messages into the main application state.

In addition, the framework already marshals model changes to the UI thread automatically.

Given this, I'm considering making the basic application do this automatically - so all updates happen on a threadpool thread, and the UI is automatically fed the new model on the UI thread. This would effectively keep the UI thread decoupled from the entire "application logic", so all updates would happen off the UI thread without any effort from the user.

Note that this is an extremely small change, in terms of code. I've pushed it, as it appears to work perfectly in my testing. Changes required can be seen here: bdc882b

Does anybody see any disadvantages (significant or insignificant) to doing this automatically? I could potentially make it optional, but hate the thought of adding options for no reason.

Async Signal handling

Right now, signal mapping/filtering/etc is always synchronous.

To go async, the best option (currently) is to treat it as an observable, and use Rx to do the processing, then map back into a signal if needed later.

We could add a set of async signal processing options, perhaps in their own submodule, ie: SIgnal.Async.map or similar. These would likely need to work like filtering, where you specify the initial value for the resulting signal, since there wouldn't otherwise be a value until the operation completed.

Changing license to MIT

I've had a couple of requests for this. I'm completely open to it, but would like to make sure the other contributors are okay with a license change.

@jeroldhaas , @TeaDrivenDev , @JohanLarsson , and @s952163 :

Would you all please reply here if you're okay with changing the license to an MIT style license?

Thank you,
Reed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.