RSharp 0.1.2
dotnet add package RSharp --version 0.1.2
NuGet\Install-Package RSharp -Version 0.1.2
<PackageReference Include="RSharp" Version="0.1.2" />
paket add RSharp --version 0.1.2
#r "nuget: RSharp, 0.1.2"
// Install RSharp as a Cake Addin #addin nuget:?package=RSharp&version=0.1.2 // Install RSharp as a Cake Tool #tool nuget:?package=RSharp&version=0.1.2
rsharp
Provides functional programming utilities, which should be recognizable for rust developers also using csharp.
Table of contents
Getting started
Installation via Package Manager Console in Visual Studio:
PM> Install-Package RSharp
Installation via .NET CLI:
> dotnet add <TARGET PROJECT> package RSharp
Usage
Option
The Option
type is a discriminated union, which can be either Some
or None
. It is used to represent the
possibility of a value not being present.
// implicit conversion from int to Some
private static Option<int> Foo() => 2;
// implicit conversion from null to None
private static Option<int> Bar() => null;
var foo = Foo();
var result = foo.Match(
some: x => x + 1, // <= should trigger this line
none: () => 0
);
var bar = Bar();
var result2 = bar.Match(
some: x => x + 1,
none: () => 0 // <= should trigger this line
);
Result
The Result
type is a discriminated union, which can be either Ok
or Err
. It is used to represent the possibility
of a value not being present.
private static Result<int, Exception> Divide(int a, int b) =>
b == 0
? new DivideByZeroException("Cannot divide by zero")
: a / b;
var result = Divide(4, 2);
result.Match(
ok: x => x + 1, // <= should trigger this line
err: e => 0
);
var result2 = Divide(4, 0);
result2.Match(
ok: x => x + 1,
err: e => 0 // <= should trigger this line
);
Like in Rust, the Result
type can also be unwrapped by calling the unwrap method. These methods will throw an
exception if the Result
is an Err
.
var result = Divide(4, 2);
var value = result.Unwrap(); // <= should be 2
var result2 = Divide(4, 0);
var value2 = result2.Unwrap(); // <= should throw an exception
There are also methods to unwrap the Result
type, but provide a default value if the Result
is an Err
.
var result = Divide(4, 2);
var value = result.UnwrapOr(0); // <= should be 2
var result2 = Divide(4, 0);
var value2 = result2.UnwrapOr(0); // <= should be 0
Map
The 'Map' function is used to map a single or multiple values to a new value. It is similar to the Select
method in
LINQ.
To map
SourceObject
toTargetObject
, we use the following function for the examples below.// Define a factory method to create a new instance of the target object. private static readonly Func<SourceObject, TargetObject> Factory = source => new TargetObject(new Guid(source.Id.ToString().PadLeft(32, '0')), source.Name, source.Description, source.Value);
Note that the Map
function returns a Result type, which can be either Ok
or Err
. If the mapping fails, the Err
type will contain the exception that was thrown while mapping.'
To get the result, you can either call the Unwrap
method, or the UnwrapOr
method, or any other of the Unwrap
methods.
var a = new SourceObject(1, "Object 1", "This is the first element in the list", 1.0);
var mapResult = a.Map(Factory);
// Use the Match method to get the result, or the Unwrap method to get the result directly.
mapResult.Match(
ok: b => b, // will be triggered if the mapping succeeds
err: e => null // will be triggered if the mapping fails
);
You can also map a collection of values to a new value. Since the map function can either fail or succeed, the result
will be a collection of Result
types.
You can use the Unwrap
method to get the results that succeeded, or the UnwrapOr
method to get the results that
succeeded, or a default value if the mapping failed.
Or just use the Where
method to filter out the results that failed.
// Define the source and target objects.
internal record SourceObject(int Id, string Name, string Description, double Value);
internal record TargetObject(Guid Id, string Name, string Description, double Value);
var a = new List<SourceObject>
{
new(-1, "Object 1", "This is the first element in the list", 1.0),
new(2, "Object 2", "This is the second element in the list", 2.0),
new(3, "Object 3", "This is the third element in the list", 3.0)
};
var b = a.Map(Factory).ToList();
// Filter out the errors, should be one item in this case as the first item has an invalid id.
var errors = b.Where(x => x.IsErr()).ToList();
// Get the results that succeeded, should be two items in this case.
var results = b.Where(x => x.IsOk()).Select(x => x.Unwrap()).ToList();
ForEach
The ForEach
function is used to iterate over a collection of values. It is similar to the ForEach
method in LINQ but
adds the index of the current item to the callback function.
var a = new List<SourceObject>
{
new(1, "Object 1", "This is the first element in the list", 1.0),
new(2, "Object 2", "This is the second element in the list", 2.0),
new(3, "Object 3", "This is the third element in the list", 3.0)
};
// Use the ForEach function to iterate over the collection and print the values
// to the console along with the index.
a.ForEach((item, index) => Console.WriteLine($"Item {index}: {item}"));
You can also use the ForEach function to generate a new collection of values.
var a = new List<SourceObject>
{
new(1, "Object 1", "This is the first element in the list", 1.0),
new(2, "Object 2", "This is the second element in the list", 2.0),
new(3, "Object 3", "This is the third element in the list", 3.0)
};
var b = a.ForEach((item, index) => Factory(item)).ToList();
Assert.Equal(3, b.Count);
// Use the Assert.All method to check if all items in the collection are of the correct type.
Assert.All(b, x => Assert.IsType<TargetObject>(x));
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net7.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Map can now return both option and result types, based on the result of the function passed to it