在ClojureClr中,不使用反射机制编写一个惰性序列并将其写入文件。

3

我有一个大的惰性序列,里面包含多行文本,我想将它们写入文件。在C#中,我会使用 System.IO.File/WriteAllLines,它有一个重载方法,可以接受 string[]IEnumerable<string> 类型的参数。

我希望能够避免在运行时使用反射来实现这个功能。

(set! *warn-on-reflection* true)

(defn spit-lines [^String filename seq]
  (System.IO.File/WriteAllLines filename seq))

但是,我收到了这个反射警告。

反射警告,... - 无法解析调用WriteAllLines。

通常情况下,我需要知道何时需要使用反射来提高性能,但我不关心此特定方法调用。 我愿意编写更多的代码以消除警告,但不愿将所有数据强制转换为数组存储在内存中。 有什么建议吗?

1个回答

2
以下有两个选项可供考虑,具体取决于您是否使用Clojure的核心数据结构。

使用LINQ中的Enumerable.Cast将seq转换为IEnumerable<string>

此选项适用于仅包含字符串的任何IEnumerable

(defn spit-lines [^String filename a-seq]
  (->> a-seq
       (System.Linq.Enumerable/Cast (type-args System.String))
       (System.IO.File/WriteAllLines filename)))

使用类型提示来强制调用者提供IEnumerable<string>

如果您想使用类型提示,请这样做。但要注意,clojure数据结构不实现IEnumerable<String>,因此可能会导致运行时异常

^|System.Collections.Generic.IEnumerable`1[System.String]|

将类型的完整CLR名称用竖线 (|) 包裹起来,可以指定在Clojure语法中通常是非法的字符。

(defn spit-lines [^String filename ^|System.Collections.Generic.IEnumerable`1[System.String]| enumerable-of-string]
  (System.IO.File/WriteAllLines filename enumerable-of-string))

这是使用类型提示版本并传递集合时,从(spit-lines "filename.txt" #{})抛出的异常:

System.InvalidCastException:无法将类型为'clojure.lang.PersistentTreeSet'的对象强制转换为类型'System.Collections.Generic.IEnumerable`1[System.String]'。

有关指定类型的更多信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接