Skip to content

Language-ext 1.7 released!

Compare
Choose a tag to compare
@louthy louthy released this 08 Dec 00:55

Lots of things have been improved over the past 3 months, especially in the Process system, but in general also. Now feels like a good time to get a release out. Any problems, shout!

Core

  • Added: Units of measure: Length, Velocity, Acceleation, Area and Time
  • Added: List.span - applied to a predicate and a list, returns a tuple where first element is longest prefix of elements that satisfy the predicate and second element is the remainder of the list.
  • Added: List.tails function - returns all final segments of the list argument, longest first.
  • Added: Applicative support for Option, OptionUnsafe, Either, EitherUnsafe, Try, TryOption, List, IEnumerable (Prelude.apply function or Apply extension method)
  • Added: Support for arithmetic operators on all monadic types with provision of IAppendable, ISubtractable, IProductable, IDivisible and INumeric. Allowing for operations like this: Some(10) + Some(10) == Some(30), and List(1,2,3) + List(4,5,6) == List(1,2,3,4,5,6)
  • Added: List.foldUntil, List.foldWhile
  • Added: Functional version of using(...) { } called use
  • Added: tryuse which is a version of 'use' that returns a Try<T>; where T is an IDisposable
  • Added: Extension method: Try<T>.Use(), same as tryuse
  • Added: Try<T>.IfFail(Exception ex => ...)
  • Added: Try<T>.IfFail().Match() - allows matching of Exception types as a single expression
    Tuple<A,B> bi-functor, bi-foldable, bi-iterable
    Tuple<A,B,C> tri-functor, tri-foldable, tri-iterable
  • Added: Serializable attribute to Either, EitherUnsafe, Lst, ListItem, Map, MapItem, Option, OptionUnsafe, Que, Stck,
  • Moved Prelude.init, Prelude.initInfinite, Prelude.repeat to List

Process system

  • Strategy system - Decalarative way of dealing with Process failure
    • Match on exceptions and map to Directives (Stop, Restart, Resume, Escalate)
    • Map the Directives to MessageDirectives to decided on the fate of the failed message (Send to dead letters, Send to self (front or back of the queue), Send to supervisor, Send to specified Process)
  • Session system - Allows consuming code to set a session-ID that is propagated throughout the system with the messages. Very useful for hooking up to authentication systems.
  • Roles. Each node in a cluster must specify a role name.
  • Process.ClusterNodes property - Has a map of alive cluster nodes and their roles.
  • Routers - Processes that can auto-route messages to child processes or a provided set of processes. Default routers include:
    • Broadcast
    • Round-robin
    • Random
    • Least-busy
  • Dispatchers - Like routers but without an actual Process. Dispatchers have a sender specified list of Processes to dispatch to, i.e. Dispatch.leastBusy(pid1, pid2, pid3). There are four default dispatchers:
    • Broadcast
    • Round-robin
    • Random
    • Least-busy
      Bespoke dispacthers can be registered using Dispatch.register(...)
  • Role dispatchers - Using a combination of Process.ClusterNodes and dispatchers, the Role dispatchers allow for ProcessIds to be built that refer to locations in the cluster by role. ie. Role.Broadcast["mail-server"]["user"]["smtp"] will create a ProcessId that looks like this: /disp/role-broadcast/user/smtp. Because it's a ProcessId it can be used with any of the existing functionality that accepts ProcessIds (tell, ask, subscribe, etc.) but it has a behaviour baked in (broadcast in this case). So doing a tell will send to all smtp Processes in the cluster.
    There are several Role dispatchers:
    • Role.Broadcast
    • Role.RoundRobin
    • Role.Random
    • Role.LeastBusy
    • Role.First
    • Role.Second
    • Role.Third
    • Role.Last
  • Death-watch system: Process.watch and Process.unwatch to get one Process watching for the death of another. Separate inbox called Terminated is used so that your primary inboxes can stay strongly typed.
  • Process setup functions are invoked immediately, rather than on their first message.
  • More improvements to the F# API to bring it closer to parity with the C# API - this work is on-going.
  • Process.js now has a Process.spawnView function (if knockout.js is in use) that allows for synchronisation of Process state and view state as well as hooking up event functions.

Breaking changes.

Hopefully very few. But areas to watch out for:

  • Remove the old with functions that were deprecated a while ago because I needed them for a new match by value and exception function. If you get errors around this area, you should use Prelude.map instead.
  • Cluster.connect now expects an extra parameter. It is the role of the node in the cluster. You don't have to use roles, but you do have to give it a valid ProcessName
  • F# Process system has had its Process ID type changed from (unit -> ProcessId) to ProcessId. It was a useful experiment for a while to avoid making ProcessFs.Self and ProcessFs.Sender into functions; but has created friction between the C# and F# implementations ever since. So I have changed the F# API to use the same ProcessId that the C# does and have changed ProcessFs.Self and the like to return 'special' ProcessIds (/__special__/self for example) that are resolved on use. So you should also be careful if you ever need to send these special paths around to use resolvePID pid to extract the actual path. This does mean that tell (Sender()) msg (Self()) can be written tell Sender msg Self, which I think is much more attractive and easy to deal with. So the occassional resolvePID Self I think is less of a problem.

Documentation

  • There's more of it!

Thanks to @la-yumba and @Jagged for their help with this release.

Nu-get

As usual everything is release on NuGet: