Scala中的基本元编程技术

时间:2013-11-14 10:45:58

标签: scala template-meta-programming generic-programming

在scala中指定以下概念的最佳方法是什么?该概念表示通用提取器函数的接口,该函数指定了在编译时提取的类。

Contruct的定义

import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import scala.collection.JavaConversions._

trait ExtractorBase {
  type ExtractedType
  type RetType = Tuple2[Option[Seq[ExtractedType]],Option[Seq[String]]]
  type ExtractorFunction = (Document) => RetType
  def extractor : ExtractorFunction
}
class Extractor[T] (extractor_in: Any) extends ExtractorBase {
  type ExtractedType = T
  val extractor : ExtractorFunction = extractor_in
}

构造实例

//type TFunc = (Document) => Tuple2[Option[Seq[Int]],Option[Seq[String]]]
val ex = new Extractor[Int]( (x: Document)=> {
    (Some(Seq(1)),Some(Seq("hassan")))
})

此时,提取器功能也没有正确别名:

[error] /Users/hassan/code/scala/extractor/hon.scala:14: type mismatch;
[error]  found   : Any
[error]  required: org.jsoup.nodes.Document => (Option[Seq[Extractor.this.ExtractedType]], Option[Seq[String]])
[error]     (which expands to)  org.jsoup.nodes.Document => (Option[Seq[T]], Option[Seq[String]])
[error]   val extractor : ExtractorFunction = extractor_in
  • 如何在扩展特征的类的定义之外引用通用特征数据?在编译时和运行时。例如编译时,我宁愿:

    trait ExtractorBase [T] {   类型ExtractedType = T.   类型RetType = Tuple2 [Option [Seq [ExtractedType]],Option [Seq [String]]]   type ExtractorFunction =(Document)=> RetType   def提取器:ExtractorFunction }

然后

class Extractor[T] (extractor_in: ExtractorBase[T].ExtractorFunction) extends ExtractorBase

类似于C ++特征。

  • 在运行时我不介意获取特征中的类型信息。

  • 可能有一种更惯用的创建特征实例的方法,我不想要通过Extractor[T]类。有没有办法用特质的伴侣对象做到这一点?

修改

Ankur的回答让我走上了正确的道路。我从我的保留曲目中错过了#操作符。是时候装扮一下了。

trait ExtractorBase[T] {
  type ExtractedType = T
  type RetType = Tuple2[Option[Seq[ExtractedType]],Option[Seq[String]]]
  type ExtractorFunction = (Document) => RetType
  def extractor : ExtractorFunction
}
class Extractor[T] (extractor_in: ExtractorBase[T]#ExtractorFunction) extends ExtractorBase[T] {
  def extractor : ExtractorBase[T]#ExtractorFunction = extractor_in
}

导致:

val ex = new Extractor[Int]( (x: Document)=> {
      (Some(Seq(1)),Some(Seq("hassan")))
})

1 个答案:

答案 0 :(得分:0)

使用jsoup可以检索通用url和项目(或两者,或者任何一个,或者没有)的提取函数的可能通用规范可以定义如下。它是功能性的,惯用的afaik。如果可以改进,请提供意见。

import org.jsoup.nodes.Document

object ExtractorTraits {
  case class UrlPair[T](data: String, payload: Option[T])
  case class ResultPair[T,U](items: Option[Seq[T]],urls:  Option[Seq[UrlPair[U]]] = None)

  trait ItemExtractorTrait[I,C] {
    type ExtractedType = I
    type RetType = Option[Seq[ExtractedType]]
    type ExtractorFunction = (Document,Option[C]) => RetType
    def apply : ExtractorFunction
  }
  class ItemExtractor[I,C](extract_item : ItemExtractorTrait[I,C]#ExtractorFunction = (doc : Document,c: Option[C]) => None)
    extends ItemExtractorTrait[I,C] { val apply = (doc: Document, ctxt: Option[C]) => extract_item(doc,ctxt) }

  trait UrlExtractorTrait[U,C] {
    type UrlPayload = U
    type RetType = Option[Seq[UrlPair[U]]]
    type ExtractorFunction = (Document,Option[C]) => RetType
    def apply : ExtractorFunction
  }
  class UrlExtractor[U,C](extract_url : UrlExtractor[U,C]#ExtractorFunction = (doc:Document,c : Option[C]) => None)
    extends UrlExtractorTrait[U,C] { val apply = (doc: Document, ctxt:  Option[C]) => extract_url(doc,ctxt)}

  trait ExtractorTrait[I,U,C] {
    type RetType = ResultPair[I,U]
    type ExtractorFunction = (Document, Option[C]) => RetType
    def apply : ExtractorFunction
  }
  class Extractor[I,U,C] (item_extractor: ItemExtractorTrait[I,C]#ExtractorFunction = new ItemExtractor[I,C]().apply,
                        url_extractor: UrlExtractorTrait[U,C]#ExtractorFunction = new UrlExtractor[U,C]().apply) extends ExtractorTrait[I,U,C] {
    val apply = (doc: Document, ctxt: Option[C]) => ResultPair[I,U](item_extractor(doc,ctxt),url_extractor(doc,ctxt))
  }
}

修改

将功能特性分开,以便可以单独使用它们。

<强> EDIT2

提取器现在有上下文