简体   繁体   English

Scala编译时递归?

[英]Scala compile-time recursion?

As a result of some helpful answers to a question I posted yesterday about tuples in Scala, I've been looking at Scala HLists. 作为对我昨天发布的有关Scala中元组的问题的一些有用答案的结果,我一直在查看Scala HLists。 I'd like to re-hash a C++ example from that question to ask another: 我想从该问题重新哈希一个C ++示例,以询问另一个问题:

In C++ one can implement compile-time recursion terminated using template specialization. 在C ++中,可以使用模板专门化来实现终止于编译时的递归。 I've often done this operating on boost tuples which, like Scala/Haskell HLists are constructed by composing the generic 'cons' type multiple times, once for each relevant type and terminating with null_type. 我经常在boost元组上执行此操作,就像Scala / Haskell HLists一样,它是通过多次构造通用的“ cons”类型构造而成的,每个相关类型一次,然后以null_type终止。 So this: 所以这:

boost::tuple<int, std::string, float>

is implemented under the hood as: 在幕后实现为:

cons<int, cons<std::string, cons<float, null_type> > >

We can then write a pair of functions that recurse at compile-time over this structure, terminating when the second, more-specialized function matches the final cons type. 然后,我们可以编写一对在编译时在此结构上递归的函数,并在第二个更专业的函数与最终的cons类型匹配时终止。 A simple example, counting the number of elements is shown below: 一个简单的示例,计算元素的数量如下所示:

template<typename T1, typename T2>
void countTupleElements( boost::tuples::cons<T1, T2>& tupleRec, int index, const std::vector<std::string>& vals )
{
    return 1 + countTupleElements( tupleRec.tail );
}

template<typename T>
void countTupleElements( boost::tuples::cons<T, boost::tuples::null_type>& tupleRec, int index, const std::vector<std::string>& vals )
{
    return 1;
}

Crucially this pattern is often used in circumstances where you want to do something different for each of the various tuple element types (not illustrated in my example): in C++ compile-time recursion is essential as once code is running, the type information is lost for all useful purposes. 至关重要的是,这种模式通常用于您要为各种元组元素类型中的每一个做不同的事情的情况下(在我的示例中未说明):在C ++中,编译时递归是必不可少的,因为一旦代码运行,类型信息就会丢失用于所有有用的目的。

My question is, is something similar possible with a Scala HList, eg 我的问题是,Scala HList是否有可能类似的事情,例如

val example = 1 :: 2.0 :: "Hello" :: "World" :: HNil

I'm aware that Scala, running on the JVM, has reflection - and so presumably this could be implemented using run-time recursion with a function using manifests and pattern matching. 我知道在JVM上运行的Scala具有反射功能-因此大概可以使用带有清单和模式匹配功能的运行时递归来实现。 But I'm interested in knowing if it's possible to do something similar to the C++ example, using compile-time recursion? 但是我有兴趣知道是否可以使用编译时递归来进行类似于C ++示例的操作?

There is an excellent example of this in the new book Scala in Depth by Joshua Suereth. 约书亚·苏瑞斯(Joshua Suereth)的新书《深度的斯卡拉》(Scala in Depth)中有一个很好的例子。 Section 7.4 is "Conditional execution using the type system" and it introduces the HList construct and how you can use compile time recursion to implement an IndexedView type that can access a specific element of the HList. 第7.4节是“使用类型系统进行有条件的执行”,它介绍了HList构造以及如何使用编译时递归来实现可以访问HList特定元素的IndexedView类型。 This is used to implement an AtIndex type which is used to retrieve individual values at compile time. 这用于实现AtIndex类型,该类型用于在编译时检索单个值。

Yes you can. 是的你可以。 See my blog post about how to implement the SKI calculus in Scala's type system for the most general case. 在最普通的情况下,请参阅我的博客文章有关如何在Scala的类型系统中实现SKI演算 I have also written about the more specific case of loop unrolling and conditional compilation . 我还写了关于循环展开和条件编译的更具体情况。 Finally the solution to this little puzzle shows the essence of one way how compile time recursion can be implemented. 最后,这个小难题解决方案显示了一种实现编译时间递归的方法的本质。

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

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