Skip to content

Commit

Permalink
Added support for partial function application
Browse files Browse the repository at this point in the history
  • Loading branch information
NoelKennedy committed May 2, 2012
1 parent a0889e3 commit b9e8973
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 3 deletions.
@@ -0,0 +1,24 @@
using System;
using FluentAssertions;
using NUnit.Framework;

namespace Scalesque.FunctionApplication {

public class When_creating_partially_applied_functions : UnitTestBase {
private Func<int, int, int, int, int, int, int, int> func;
private Func<int, int> apply6Params;

public override void Given() {
func = (v1, v2, v3, v4, v5, v6, v7) => v1 + v2 + v3 + v4 + v5 + v6 + v7;
}

public override void Because() {
apply6Params = func.Partial(1, 1, 1, 1, 1, 1);
}

[Test]
public void It_should_have_applied_the_first_six_parameters_creating_a_function_of_arity_1() {
apply6Params(1).Should().Be(7);
}
}
}
1 change: 1 addition & 0 deletions Scalesque.Tests/Scalesque.Tests.csproj
Expand Up @@ -49,6 +49,7 @@
<Compile Include="EitherOr\When_extracting_either.cs" />
<Compile Include="EitherOr\When_composing_with_either.cs" />
<Compile Include="EitherOr\When_joining_either.cs" />
<Compile Include="FunctionApplication\When_creating_partially_applied_functions.cs" />
<Compile Include="Patterns\SomeExampleExtractors.cs" />
<Compile Include="Patterns\When_doing_more_complicated_extractions.cs" />
<Compile Include="Patterns\When_doing_simple_pattern_matching.cs" />
Expand Down
8 changes: 8 additions & 0 deletions Scalesque.net35/Funcs.cs
@@ -0,0 +1,8 @@
namespace Scalesque {
//.net 3.5 only has Funcs defined in the core libary of up to arity 4. Defined the rest here:

public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
}
4 changes: 4 additions & 0 deletions Scalesque.net35/Scalesque.net35.csproj
Expand Up @@ -75,6 +75,9 @@
<Compile Include="..\Scalesque.net40\Option.implicits.cs">
<Link>Option.implicits.cs</Link>
</Compile>
<Compile Include="..\Scalesque.net40\PartialFunctionsGen.generated.cs">
<Link>PartialFunctionsGen.generated.cs</Link>
</Compile>
<Compile Include="..\Scalesque.net40\PatternMatcher.cs">
<Link>PatternMatcher.cs</Link>
</Compile>
Expand All @@ -99,6 +102,7 @@
<Compile Include="..\Scalesque.net40\Validation.implicits.cs">
<Link>Validation.implicits.cs</Link>
</Compile>
<Compile Include="Funcs.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
267 changes: 267 additions & 0 deletions Scalesque.net40/PartialFunctionsGen.generated.cs
@@ -0,0 +1,267 @@

using System;

namespace Scalesque {

//Warning: This file was generated by a T4 template. Any manual changes you make maybe overwritten when the templating code activates.

/// <summary>
/// An implementation of partially applied functions
/// </summary>
public static class PartialFunctions {

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 1
/// </summary>
public static Func<TResult> Partial<T1,TResult>(this Func<T1,TResult> f, T1 value1) {
return ()=>f(value1);
}

/// <summary>
/// Creates a partially applied function of arity 1 from a function of arity 2
/// </summary>
public static Func<T2,TResult> Partial<T1,T2,TResult>(this Func<T1,T2,TResult> f, T1 value1) {
return (value2)=>f(value1,value2);
}

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 2
/// </summary>
public static Func<TResult> Partial<T1,T2,TResult>(this Func<T1,T2,TResult> f, T1 value1, T2 value2) {
return ()=>f(value1,value2);
}

/// <summary>
/// Creates a partially applied function of arity 2 from a function of arity 3
/// </summary>
public static Func<T2,T3,TResult> Partial<T1,T2,T3,TResult>(this Func<T1,T2,T3,TResult> f, T1 value1) {
return (value2,value3)=>f(value1,value2,value3);
}

/// <summary>
/// Creates a partially applied function of arity 1 from a function of arity 3
/// </summary>
public static Func<T3,TResult> Partial<T1,T2,T3,TResult>(this Func<T1,T2,T3,TResult> f, T1 value1, T2 value2) {
return (value3)=>f(value1,value2,value3);
}

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 3
/// </summary>
public static Func<TResult> Partial<T1,T2,T3,TResult>(this Func<T1,T2,T3,TResult> f, T1 value1, T2 value2, T3 value3) {
return ()=>f(value1,value2,value3);
}

/// <summary>
/// Creates a partially applied function of arity 3 from a function of arity 4
/// </summary>
public static Func<T2,T3,T4,TResult> Partial<T1,T2,T3,T4,TResult>(this Func<T1,T2,T3,T4,TResult> f, T1 value1) {
return (value2,value3,value4)=>f(value1,value2,value3,value4);
}

/// <summary>
/// Creates a partially applied function of arity 2 from a function of arity 4
/// </summary>
public static Func<T3,T4,TResult> Partial<T1,T2,T3,T4,TResult>(this Func<T1,T2,T3,T4,TResult> f, T1 value1, T2 value2) {
return (value3,value4)=>f(value1,value2,value3,value4);
}

/// <summary>
/// Creates a partially applied function of arity 1 from a function of arity 4
/// </summary>
public static Func<T4,TResult> Partial<T1,T2,T3,T4,TResult>(this Func<T1,T2,T3,T4,TResult> f, T1 value1, T2 value2, T3 value3) {
return (value4)=>f(value1,value2,value3,value4);
}

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 4
/// </summary>
public static Func<TResult> Partial<T1,T2,T3,T4,TResult>(this Func<T1,T2,T3,T4,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4) {
return ()=>f(value1,value2,value3,value4);
}

/// <summary>
/// Creates a partially applied function of arity 4 from a function of arity 5
/// </summary>
public static Func<T2,T3,T4,T5,TResult> Partial<T1,T2,T3,T4,T5,TResult>(this Func<T1,T2,T3,T4,T5,TResult> f, T1 value1) {
return (value2,value3,value4,value5)=>f(value1,value2,value3,value4,value5);
}

/// <summary>
/// Creates a partially applied function of arity 3 from a function of arity 5
/// </summary>
public static Func<T3,T4,T5,TResult> Partial<T1,T2,T3,T4,T5,TResult>(this Func<T1,T2,T3,T4,T5,TResult> f, T1 value1, T2 value2) {
return (value3,value4,value5)=>f(value1,value2,value3,value4,value5);
}

/// <summary>
/// Creates a partially applied function of arity 2 from a function of arity 5
/// </summary>
public static Func<T4,T5,TResult> Partial<T1,T2,T3,T4,T5,TResult>(this Func<T1,T2,T3,T4,T5,TResult> f, T1 value1, T2 value2, T3 value3) {
return (value4,value5)=>f(value1,value2,value3,value4,value5);
}

/// <summary>
/// Creates a partially applied function of arity 1 from a function of arity 5
/// </summary>
public static Func<T5,TResult> Partial<T1,T2,T3,T4,T5,TResult>(this Func<T1,T2,T3,T4,T5,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4) {
return (value5)=>f(value1,value2,value3,value4,value5);
}

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 5
/// </summary>
public static Func<TResult> Partial<T1,T2,T3,T4,T5,TResult>(this Func<T1,T2,T3,T4,T5,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) {
return ()=>f(value1,value2,value3,value4,value5);
}

/// <summary>
/// Creates a partially applied function of arity 5 from a function of arity 6
/// </summary>
public static Func<T2,T3,T4,T5,T6,TResult> Partial<T1,T2,T3,T4,T5,T6,TResult>(this Func<T1,T2,T3,T4,T5,T6,TResult> f, T1 value1) {
return (value2,value3,value4,value5,value6)=>f(value1,value2,value3,value4,value5,value6);
}

/// <summary>
/// Creates a partially applied function of arity 4 from a function of arity 6
/// </summary>
public static Func<T3,T4,T5,T6,TResult> Partial<T1,T2,T3,T4,T5,T6,TResult>(this Func<T1,T2,T3,T4,T5,T6,TResult> f, T1 value1, T2 value2) {
return (value3,value4,value5,value6)=>f(value1,value2,value3,value4,value5,value6);
}

/// <summary>
/// Creates a partially applied function of arity 3 from a function of arity 6
/// </summary>
public static Func<T4,T5,T6,TResult> Partial<T1,T2,T3,T4,T5,T6,TResult>(this Func<T1,T2,T3,T4,T5,T6,TResult> f, T1 value1, T2 value2, T3 value3) {
return (value4,value5,value6)=>f(value1,value2,value3,value4,value5,value6);
}

/// <summary>
/// Creates a partially applied function of arity 2 from a function of arity 6
/// </summary>
public static Func<T5,T6,TResult> Partial<T1,T2,T3,T4,T5,T6,TResult>(this Func<T1,T2,T3,T4,T5,T6,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4) {
return (value5,value6)=>f(value1,value2,value3,value4,value5,value6);
}

/// <summary>
/// Creates a partially applied function of arity 1 from a function of arity 6
/// </summary>
public static Func<T6,TResult> Partial<T1,T2,T3,T4,T5,T6,TResult>(this Func<T1,T2,T3,T4,T5,T6,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) {
return (value6)=>f(value1,value2,value3,value4,value5,value6);
}

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 6
/// </summary>
public static Func<TResult> Partial<T1,T2,T3,T4,T5,T6,TResult>(this Func<T1,T2,T3,T4,T5,T6,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) {
return ()=>f(value1,value2,value3,value4,value5,value6);
}

/// <summary>
/// Creates a partially applied function of arity 6 from a function of arity 7
/// </summary>
public static Func<T2,T3,T4,T5,T6,T7,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,TResult> f, T1 value1) {
return (value2,value3,value4,value5,value6,value7)=>f(value1,value2,value3,value4,value5,value6,value7);
}

/// <summary>
/// Creates a partially applied function of arity 5 from a function of arity 7
/// </summary>
public static Func<T3,T4,T5,T6,T7,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,TResult> f, T1 value1, T2 value2) {
return (value3,value4,value5,value6,value7)=>f(value1,value2,value3,value4,value5,value6,value7);
}

/// <summary>
/// Creates a partially applied function of arity 4 from a function of arity 7
/// </summary>
public static Func<T4,T5,T6,T7,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,TResult> f, T1 value1, T2 value2, T3 value3) {
return (value4,value5,value6,value7)=>f(value1,value2,value3,value4,value5,value6,value7);
}

/// <summary>
/// Creates a partially applied function of arity 3 from a function of arity 7
/// </summary>
public static Func<T5,T6,T7,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4) {
return (value5,value6,value7)=>f(value1,value2,value3,value4,value5,value6,value7);
}

/// <summary>
/// Creates a partially applied function of arity 2 from a function of arity 7
/// </summary>
public static Func<T6,T7,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) {
return (value6,value7)=>f(value1,value2,value3,value4,value5,value6,value7);
}

/// <summary>
/// Creates a partially applied function of arity 1 from a function of arity 7
/// </summary>
public static Func<T7,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) {
return (value7)=>f(value1,value2,value3,value4,value5,value6,value7);
}

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 7
/// </summary>
public static Func<TResult> Partial<T1,T2,T3,T4,T5,T6,T7,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) {
return ()=>f(value1,value2,value3,value4,value5,value6,value7);
}

/// <summary>
/// Creates a partially applied function of arity 7 from a function of arity 8
/// </summary>
public static Func<T2,T3,T4,T5,T6,T7,T8,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1) {
return (value2,value3,value4,value5,value6,value7,value8)=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}

/// <summary>
/// Creates a partially applied function of arity 6 from a function of arity 8
/// </summary>
public static Func<T3,T4,T5,T6,T7,T8,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1, T2 value2) {
return (value3,value4,value5,value6,value7,value8)=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}

/// <summary>
/// Creates a partially applied function of arity 5 from a function of arity 8
/// </summary>
public static Func<T4,T5,T6,T7,T8,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1, T2 value2, T3 value3) {
return (value4,value5,value6,value7,value8)=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}

/// <summary>
/// Creates a partially applied function of arity 4 from a function of arity 8
/// </summary>
public static Func<T5,T6,T7,T8,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4) {
return (value5,value6,value7,value8)=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}

/// <summary>
/// Creates a partially applied function of arity 3 from a function of arity 8
/// </summary>
public static Func<T6,T7,T8,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) {
return (value6,value7,value8)=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}

/// <summary>
/// Creates a partially applied function of arity 2 from a function of arity 8
/// </summary>
public static Func<T7,T8,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) {
return (value7,value8)=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}

/// <summary>
/// Creates a partially applied function of arity 1 from a function of arity 8
/// </summary>
public static Func<T8,TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) {
return (value8)=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}

/// <summary>
/// Creates a partially applied function of arity 0 from a function of arity 8
/// </summary>
public static Func<TResult> Partial<T1,T2,T3,T4,T5,T6,T7,T8,TResult>(this Func<T1,T2,T3,T4,T5,T6,T7,T8,TResult> f, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8) {
return ()=>f(value1,value2,value3,value4,value5,value6,value7,value8);
}


}
}
42 changes: 42 additions & 0 deletions Scalesque.net40/PartialFunctionsGen.tt
@@ -0,0 +1,42 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>

<#@ output extension=".cs" #>
using System;

namespace Scalesque {

//Warning: This file was generated by a T4 template. Any manual changes you make maybe overwritten when the templating code activates.

/// <summary>
/// An implementation of partially applied functions
/// </summary>
public static class PartialFunctions {

<#

for(int arity=1;arity<=8;arity++){
for(int applications=1;applications<=arity;applications++) {
Func<IEnumerable<string>, string, string> seperate =(list, seperator) => list.Aggregate("", (acc, t) => acc + seperator + t).Trim(seperator.ToCharArray());
var allGenericTypes = seperate(Enumerable.Range(1, arity).Select(x => "T" + x.ToString()), ",") + ",TResult";
var signatureOfParametersToApply = seperate(Enumerable.Range(1, applications).Select(x => string.Format("T{0} value{0}", x)), ", ");
var parameterApplication = seperate(Enumerable.Range(1, arity).Select(x => string.Format("value{0}", x)), ",");
var unappliedParameters = seperate(Enumerable.Range(applications, arity).Where(x => (arity >= x) & x > applications).Select(x => string.Format("value{0}", x)), ",");
var signatureOfPartiallyAppliedFunction = "Func<" + seperate(Enumerable.Range(applications, arity).Where(x => (arity >= x) & x > applications).Select(x => "T" + x.ToString()).Concat(new string[] { "TResult" }), ",") + ">";
#>
/// <summary>
/// Creates a partially applied function of arity <#=arity-applications#> from a function of arity <#=arity#>
/// </summary>
public static <#= signatureOfPartiallyAppliedFunction #> Partial<<#= allGenericTypes #>>(this Func<<#= allGenericTypes #>> f, <#=signatureOfParametersToApply#>) {
return (<#=unappliedParameters#>)=>f(<#=parameterApplication#>);
}

<# }
}
#>

}
}
3 changes: 1 addition & 2 deletions Scalesque.net40/Properties/AssemblyInfo.cs
@@ -1,11 +1,10 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Scalaesque")]
[assembly: AssemblyTitle("Scalesque")]
[assembly: AssemblyDescription("Functional programming library for c#")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
Expand Down

0 comments on commit b9e8973

Please sign in to comment.