【问题标题】:Basic Metaprogramming techniques in ScalaScala 中的基本元编程技术
【发布时间】:2013-11-14 10:45:58
【问题描述】:

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

结构定义

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
  • 如何在扩展特征的类定义之外引用通用特征数据?在编译时和运行时。例如编译时间我宁愿有:

    特征提取器基础[T] { 类型 ExtractedType = T 类型 RetType = Tuple2[Option[Seq[ExtractedType]],Option[Seq[String]]] 类型 ExtractorFunction = (Document) => RetType def 提取器:ExtractorFunction }

然后

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

有点类似于 C++ 特征。

  • 在运行时,我也不介意获取 trait 中的类型信息。

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

编辑

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")))
})

【问题讨论】:

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


    【解决方案1】:

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

    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

    提取器现在有上下文

    【讨论】:

      猜你喜欢
      • 2014-12-25
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      • 2019-11-29
      • 2012-02-19
      相关资源
      最近更新 更多