Giter Site home page Giter Site logo

extcore's People

Contributors

7sharp9 avatar enricosada avatar goswinr avatar jack-pappas avatar jindraivanek avatar mavnn avatar sachinshahredmane avatar vasily-kirichenko avatar wallymathieu 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

extcore's Issues

Add AsyncStatefulChoiceBuilder

Analogy as there's non-async pair

type ProtectedStateFunc<'State, 'T, 'Error> =  'State -> Choice<'T * 'State, 'Error>
type StatefulChoiceFunc<'State, 'T, 'Error> =  'State -> Choice<'T, 'Error> * 'State

it would be great to have async one

type AsyncProtectedStateFunc<'State, 'T, 'Error> =  'State -> Async<Choice<'T * 'State, 'Error>>
type AsyncStatefulChoiceFunc<'State, 'T, 'Error> =  'State -> Async<Choice<'T, 'Error> * 'State>> //missing

Option.fromBoolAndOut ?

This is a very useful function. I can do something like str |> int.TryParse |> Option.fromBoolAndOut .

Optimize LazyList implementation

Via the fsharp-opensource mailing list, Greg Chapman suggested a possible optimization for LazyList:

https://groups.google.com/forum/#!searchin/fsharp-opensource/lazy/fsharp-opensource/Zd221uJ0BGM/A1h8bJtv_c0J

I've noticed that both the PowerPack and ExtCore implementations of LazyList wrap a delay around the LazyLists produced by cons and consDelayed. It seems to me that this is unnecessary, since both functions are given the value which will be the head of the new LazyList (so there's no need to delay calculating it). To be specific, here's some code from the PowerPack:

let lzy f = { status = Delayed f }

let notlazy v = { status = Value v }

let consc x l = CellCons(x,l)
let cons x l = lzy(fun () -> (consc x l))

It seems to me that you could change cons to:

let cons x l = notlazy (consc x l)

without breaking anything or decreasing the laziness. Am I missing something?

Make sure enumerators are always disposed

A number of ExtCore functions, e.g., those in the Seq module, call GetEnumerator() on a seq<'T> but don't dispose the resulting enumerator. This is a problem, because the enumerator can (for example) hold handles to unmanaged resources, which are leaked when the enumerator isn't disposed properly.

The first step to fixing these issues will be to implement a custom IEnumerable<T> type in ExtCore.Tests; when GetEnumerator() is called on this type, it should return an instance of IEnumerator<T> that captures a ref cell stored inside the parent and is incremented when GetEnumerator() is called and decremented when the enumerator is disposed. This way, unit tests can assert that allocated enumerators have been disposed.

NuGet package installation adds binding redirect for FSharp.Core to version 4.3.0.0

What's worse, it replaces previous redirect with it's own:

before:

<dependentAssembly>
    <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
</dependentAssembly>

after:

<dependentAssembly>
    <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0" />
</dependentAssembly>

Supporting Result and/or Choice

For ExtCore v1.0 -- should we support both the Result<_,_> and Choice<_,_> type for error-handling, or should we drop Choice<_,_> and use only Result<_,_>?

Pros/cons of supporting Result<_,_> only:

  • ๐Ÿ‘ Smaller code size, less maintenance work (long-term)
  • ๐Ÿ‘ Just one way of doing things -- maybe simpler for less-experienced F# devs
  • ๐Ÿ‘Ž Result<_,_> is a struct, so doing a blanket replacement throughout code may hurt performance in cases where a Result is created wrapping a large struct and thereby induces expensive struct copies.
  • ๐Ÿ‘Ž Eliminating support for Choice<_,_> breaks backwards-compatibility with code written against current/past versions of ExtCore. Users of the library will have to to make non-trivial changes to their code in order to upgrade to ExtCore v1.0.

Pros/cons of supporting Result<_,_> and Choice<_,_>:

  • ๐Ÿ‘ Provides backwards-compatibility for code already written against current/past versions of ExtCore. Users should be able to (with the exception of the breaking changes defined in #47) simply upgrade to ExtCore v1.0 when it's released.
  • ๐Ÿ‘ Users can still choose between Result<_,_> and Choice<_,_> and use whatever best fits their needs.
  • ๐Ÿ‘Ž Adds additional complexity to ExtCore -- wherever we support error-handling within functions, we now need to implement those functions twice (once for Result, once for Choice). This is transitive as well -- any functions that call these functions also need to be implemented twice, etc.

cc @vasily-kirichenko @7sharp9 @wallymathieu @dsyme @TIHan

Deprecate substring in favor of ReadOnlySpan<char>?

For ExtCore 1.0, consider replacing the substring type in favor of the new ReadOnlySpan<char> type. substring is useful for avoiding allocations in text-processing code, but unfortunately there are some inconsistencies in it's implementation (and functions in the Substring module) w.r.t. whether indices used in functions represent an index into the original string or within the substring. Moving to ReadOnlySpan<char> gives us a chance to fix this, and also provides an API that'll be more compatible with the rest of F# and the broader .NET ecosystem.

Supporting multiple versions of FSharp.Core

Issues like #39 and @wallymathieu's work in #31, #32 raise an important question: should ExtCore support/target multiple versions of FSharp.Core?

If not, what should be the policy for determining which version of FSharp.Core we'll target? How would we decide if/when to upgrade the version of FSharp.Core we're referencing?

Another way of looking at this problem: if functionality (types and/or functions) from ExtCore is determined to be useful enough to be merged into FSharp.Core, how do we deal with that in a way which causes the least amount of breakage / code changes for users of ExtCore?

Thoughts? @7sharp9 @vasily-kirichenko @dsyme @TIHan

Unexpected TaskBuilder behaviour

Here is a simple program using TaskBuilder:

open System.Threading
open System.Threading.Tasks
open ExtCore.Control.Tasks

[<EntryPoint>]
let main _ =
  let completed = ref false
  let t = tasks {
    printfn "Started"
    let n = ref 10
    let s = ref 0
    printfn "Next while"
    while 0 < !n do
      printfn "Iteration"
      s := !n + !s
      n := !n - 1
    printfn "Sum %A" !s
    lock completed <| fun () ->
      completed := true
      Monitor.PulseAll completed
  }
  t.Start ()
  lock completed <| fun () ->
    while not !completed do
      Monitor.Wait completed |> ignore
  0

Running this program (Mono, but I don't expect different behavior under .Net) I get the following output:

Started
Next while

After which nothing happens. I would expect the computation to run to completion. Like when happens if you replace tasks with async and t.Start () with Async.Start t.

Update tests to use NUnit 3.x

It'd be good to update the ExtCore.Tests project to use NUnit 3.x (it's currently using the last stable 2.x version). However, this isn't as simple as changing the reference because of the use of the [<ExpectedException>] attribute which was removed from NUnit 3.x.

There is a way to bring this attribute back for NUnit 3.x:
https://github.com/nunit/nunit-csharp-samples/blob/master/ExpectedExceptionExample/ExpectedExceptionAttribute.cs

Let's either implement that attribute in ExtCore.Tests, or modify the tests to use e.g., Assert.Throws<T>(...) instead.

online documentation

It would be useful if ExtCore had online documentation available somewhere (on github pages?). If it is already available, it would be nice if it was linked in the readme; I couldn't find such a link there, and google-fu also failed me. As of now, I unfortunately can't easily learn what exactly is available in ExtCore.

Result type in ExtCore collides with the Result type in FSharp.Core 4.2

So if you open System then you get both the one from FSharp.Core and ExtCore so you have to prefix pattern matching on the Error case to avoid collision:

                 let result =
                   try Ok (analyse exp basicEnv)
                   with ex -> Result.Error (ex.Message)
                 if printResult then
                      printfn "%s" name
                      printfn "Expression: %s" (HMBasic.exp.toString exp)
                      match result with
                      | Ok result ->
                          printfn "inferred: %s\n" (HMBasic.ty.toString result)
                      | Result.Error error -> printfn "inferred: %s\n" error )

I mean its easy enough to prefix, but its unnecessary noise, maybe depreciate the result type or not open is by default.

dprintfn not working when compiled (i.e., calling the function in the ExtCore package)

Greg Chapman submitted this bug report to me a while back via the NuGet gallery. I'm opening an issue here to keep track of it:

Using VSExpress Web 2012, I manually created a WinForms app and used Nuget to add ExtCore to it. I then used the dprintfn function in several places. Although I compiled and ran my app in Debug mode, none of the dprintfn messages appeared in the Debug Output. When I just copied the dprintfn code into my app and used that (rather than the ExtCore version), the debug messages did appear.

I'm guessing that the NuGet ExtCore is a release build. so the Debug.WriteLines get stripped out.

Move tagged collections/modules to separate assembly

ExtCore has some features requiring the library to be built using the F# proto-compiler (fsc-proto), most notably the 'tagged' collections types (such as TagMap) and their supporting modules. I've found these collections to be extremely useful in practice, so I don't want to get rid of them entirely; the requirement of using fsc-proto to build ExtCore is painful though, and makes maintenance much more difficult.

I was thinking of ways to more-easily use fsc-proto in CI builds (e.g. with a docker image), but upon reflection I think the most straightforward way forward will be to move the tagged collections into a separate project/assembly (e.g. ExtCore.TaggedCollections) which references ExtCore proper. That won't eliminate the fsc-proto requirement, but it does allow ExtCore to be updated separately -- we can work out a better solution (maybe) for building the ExtCore.TaggedCollections project later.

AsyncChoiceBuilder x.TryFinally / x.Using issue

in asyncChoice computation IDisposable.Dispose called after first bind instead of calling on computation finish

open System

let mutable disposed = false

[<SetUp>]
let setup() = disposed <- false

[<TearDown>]
let teardown() =
    printfn "Should be disposed. Checking..."
    Assert.IsTrue(disposed)

type Disposable() = 
    interface IDisposable with
        member x.Dispose() = 
            printfn "disposing!"
            disposed <- true

let createAsyncChoiceDisposable() = async { return Choice1Of2(new Disposable()) }

let waitAsyncChoice() = 
    asyncChoice { 
        printfn "waiting"
    }

let shouldNotBeDisposed() =
    printfn "Should not be disposed. Checking..."
    Assert.IsFalse(disposed)

// asyncChoice wrong behavior

[<Test>]
let usingAsyncChoice() : unit = 
    asyncChoice { 
        use! d = createAsyncChoiceDisposable()
        shouldNotBeDisposed()
        let! a = waitAsyncChoice()
        shouldNotBeDisposed()
    }
    |> Async.RunSynchronously
    |> Choice.get
    |> ignore

// async - expected behavior

let createAsyncDisposable() = async { return (new Disposable()) }

let waitAsync() = 
    async { 
        printfn "waiting"
    }

[<Test>]
let usingAsync() : unit = 
    async { 
        use! d = createAsyncDisposable()
        shouldNotBeDisposed()
        do! waitAsync()
        shouldNotBeDisposed()
    }
    |> Async.RunSynchronously
    |> ignore

I think this problem in TryFinally implementation because target disposed after first bind in case of using try/finally explicit

Async.Seq.Parallel.batch wrong implementation?

Hi, after reading (and rereading a few times) xml doc for ExtCore.Control.Collections.Async.Seq.Parallel.batch I expect:

[1..10]
|> Seq.map (fun x -> async { return x * x })
|> ExtCore.Control.Collections.Async.Seq.Parallel.batch 3

expect to return [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]
but it returns [1; 4; 9; 4; 9; 16; 9; 16; 25; 16; 25; 36; 25; 36; 49; 36; 49; 64; 49; 64; 81; 64; 81; 100]

Why batch use Seq.windowed?

I expect that implementation (w/out parameters checking):

let mybatch size (sequence : seq<Async<'T>>) : seq<'T> =
    sequence
    |> Seq.split size
    |> Seq.collect (Async.Parallel >> Async.RunSynchronously)

where Seq.split (maybe not best implementation):

module Seq =
    /// Split seq to chunks with size chunkSize (or lesser)
    let split chunkSize (s: #seq<_>) =
        seq {
            let r = ResizeArray<_>()
            for x in s do
                r.Add(x)
                if r.Count = chunkSize then
                    yield r.ToArray() |> Array.toList
                    r.Clear()
            if r.Count <> 0 then yield r.ToArray() |> Array.toList }

By the way, why there is not Seq.split (maybe better name it 'partition'?) in ExtCore. It is very useful function.

Publish packages from CI builds

It'd make releasing new versions of ExtCore significantly easier if we could build + release new versions of the nuget package directly from within the CI builds. Some initial thoughts:

  • We could use travis encrypt to encrypt the nuget API key needed to publish new versions of the package -- for obvious reasons the key should not be made public.
  • We (probably?) don't want the package to be released on every CI build. The git commit message(s) are available to the CI build through environment variables. Perhaps we'd implement something in the build script to check the commit message so project maintainers can trigger a new release via a git tag and/or including something like [ci package] in the commit message. Travis CI does something like this now -- including [ci skip] in the commit message prevents a commit from triggering a CI build.

ExtCore v1.0

Once the Maintainability tasks project is completed, I think we ought to release the new versions of ExtCore as v1.0.0. The reason for the version bump is that the library has been (more or less) API-stable for a long time, but we will need to make a few breaking changes at some point to be able to properly support new versions of F# without having conflicts between ExtCore and newer versions of FSharp.Core.

Current list of breaking changes that'll need to be made:

  • #23: Remove the TaskBuilder type, which was never properly implemented.
  • #38: Remove the == operator from Pervasives.fs.
  • #39: Remove the Result active pattern from Pervasives.fs -- it conflicts with the new Result<_,_> type in FSharp.Core.
  • #43: Move tagged collections to a separate assembly
  • Remove the few functions (e.g. typehandleof<'T>) in Pervasives.fs which use inline IL and therefore require fsc-proto to build ExtCore.
  • #48: Determine whether and how to support both Choice<_,_> and Result<_,_>

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.