Scala:隐式地将对象渲染为复杂的XML? [英] Scala: Implicitly render objects into complex XML?

查看:59
本文介绍了Scala:隐式地将对象渲染为复杂的XML?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,如何(或为什么不能)使用诸如

val myURL = new URL("https://example.com")
<p>Hey, come check out my cool new website at { myURL }.</p>

这样的方法自动将所有URL对象转换为相关的超链接:

implicit def urlToXML(url: URL): xml.Node =
  <a href={ url.toString }>{ url.getHost + url.getPath }</a>

然后我可能会(隐式)使用它:

val myURL = new URL("https://example.com")
<p>Hey, come check out my cool new website at { myURL }.</p>

Scala(2.11.5)似乎忽略了implicit方法,并将URL对象直接转换为字符串.

解决方案

转换必须由预期的类型或成员选择触发.在这种情况下,嵌入式Scala表达式的预期类型为Any.

它是这样编译的:

scala> <tag>{ 42 }{ new java.net.URI("http://acme.com") }</tag>
[[syntax trees at end of                     typer]] // <console>
package $line3 {
  object $read extends scala.AnyRef {
    def <init>(): $line3.$read.type = {
      $read.super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>(): type = {
        $iw.super.<init>();
        ()
      };
      object $iw extends scala.AnyRef {
        def <init>(): type = {
          $iw.super.<init>();
          ()
        };
        private[this] val res0: scala.xml.Elem = {
          {
            new scala.xml.Elem(null, "tag", scala.xml.Null, scala.this.xml.TopScope, false, ({
              val $buf: scala.xml.NodeBuffer = new scala.xml.NodeBuffer();
              $buf.&+(42);
              $buf.&+(new java.net.URI("http://acme.com"));
              $buf
            }: _*))
          }
        };
        <stable> <accessor> def res0: scala.xml.Elem = $iw.this.res0
      }
    }
  }
}

该文档为

另一种选择是提供一个自定义xml库,该库在该位置采用有用的类型,例如Embeddable,您可以为其提供所需的类型类.

另一种选择是预测Scala的未来并使用插值器.

For example, how can I (or why can't I) automatically convert all URL objects to a relevant hyper-link using an implicit method such as this:

implicit def urlToXML(url: URL): xml.Node =
  <a href={ url.toString }>{ url.getHost + url.getPath }</a>

Then I might (implicitly) use it like so:

val myURL = new URL("https://example.com")
<p>Hey, come check out my cool new website at { myURL }.</p>

Scala (2.11.5) seems to ignore the implicit method and convert the URL object straight to a string.

解决方案

Conversions have to be triggered by either an expected type or a member selection. In this case, the expected type for the embedded Scala expression is Any.

This is how it compiles:

scala> <tag>{ 42 }{ new java.net.URI("http://acme.com") }</tag>
[[syntax trees at end of                     typer]] // <console>
package $line3 {
  object $read extends scala.AnyRef {
    def <init>(): $line3.$read.type = {
      $read.super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>(): type = {
        $iw.super.<init>();
        ()
      };
      object $iw extends scala.AnyRef {
        def <init>(): type = {
          $iw.super.<init>();
          ()
        };
        private[this] val res0: scala.xml.Elem = {
          {
            new scala.xml.Elem(null, "tag", scala.xml.Null, scala.this.xml.TopScope, false, ({
              val $buf: scala.xml.NodeBuffer = new scala.xml.NodeBuffer();
              $buf.&+(42);
              $buf.&+(new java.net.URI("http://acme.com"));
              $buf
            }: _*))
          }
        };
        <stable> <accessor> def res0: scala.xml.Elem = $iw.this.res0
      }
    }
  }
}

The doc is here for NodeBuffer.&+.

So alternatively,

scala> implicit class `uri anchor`(val u: java.net.URI) { def a = <a href={ u.toString }>{ u.getHost }</a> }
defined class uri$u0020anchor

scala> <tag>{ new java.net.URI("http://acme.com").a }</tag>
res1: scala.xml.Elem = <tag><a href="http://acme.com">acme.com</a></tag>

scala> 

The other alternative is to provide a custom xml library that takes a useful type in that location, such as Embeddable, for which you could provide the type classes you want.

The other alternative is to anticipate the Scala future and use an interpolator.

这篇关于Scala:隐式地将对象渲染为复杂的XML?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆