繁体   English   中英

挑战:更好的方式来讨论或部分应用C#4的弦乐。加入

[英]Challenge: Neater way of currying or partially applying C#4's string.Join

背景

我最近读到.NET 4的System.String类有一个新的Join方法重载。 这个新的重载需要一个分隔符和一个IEnumerable<T> ,它允许将任意集合连接成一个字符串,而无需转换为中间字符串数组。

凉! 这意味着我现在可以这样做:

var evenNums = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0);
var list = string.Join(",",evenNums);

......而不是这个:

var evenNums = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .Select(i => i.ToString())
    .ToArray();
var list = string.Join(",", evenNums);

...因此节省了将每个项目转换为字符串,然后分配数组。

问题

但是,作为一般编程功能样式的粉丝,特别是C#中的方法链接,我宁愿能够写出这样的东西:

var list = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .string.Join(",");

这不是合法的C#。 是的,我可以使用Enumerable.Aggregate来做 ,是的,我可以使用我自己的Join扩展方法实现它 ,但是这些方法很难读取/效率低,感觉像是一个警察(分别),所以我想尝试以不同的方式做到这一点。 我到目前为止最接近的是这样的:

var list = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .ApplyTo(
        Functional.Curry<string, IEnumerable<object>, string>
            (string.Join)(",")
    );

...使用以下扩展方法:

public static class Functional
{
    public static TRslt
    ApplyTo<TArg, TRslt>(this TArg arg, Func<TArg, TRslt> func)
    {
        return func(arg);
    }

    public static Func<T1, Func<T2, TResult>>
    Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        Func<Func<T1, T2, TResult>, Func<T1, Func<T2, TResult>>> curried
            = f => x => y => f(x, y);
        return curried(func);
    }
}

这非常冗长,需要显式定义参数和字符串的返回类型。我想要使用的加载过载,并依赖于C#4的方差特性,因为我们将其中一个参数定义为IEnumerable而不是IEnumerable。

挑战

你能找到一种更简洁的方法来实现这种方法链式编程吗?

这个挑战是试图在C#中找到一种简洁的方式来解决具有多重载荷的功能 - 这只是为了好玩!

有什么不对:

var list = string.Join(",",Enumerable.Range(1, 100).Where(i => i%2 == 0));

我真的不明白这不是函数式编程。 它不那么紧密,真实。 但功能程序不是关于链接,而是关于编写更多的声明性语句,这在我的书中正在做。 当然,如果你真的希望它被链接,你可以这样做:内部/加入字符串数组的LINQ方式是什么?

我不确定为什么你需要你的例子中额外的Curry方法。 简单地使用另一个Lambda会产生更简洁的选项。

var list = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .ApplyTo((x) => { return string.Join(",", x); })

五年之后它仍然没有答案,让我们试试吧!

高效,没有外部代码,完全链接和可读:

var list = Enumerable.Range(1, 100000)
    .Where(i => i % 2 == 0)
    .Aggregate(new StringBuilder(), (prev, i) => prev.AppendFormat(",{0}",i))
    .Remove(0,1)
    .ToString();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM