如何使这段代码发挥作用?
我编写了一个简单的脚本,用于将 c 样式标识符名称(例如,invoice_number
)转换为 java 样式标识符名称(例如,invoiceNumber
)。
val files = Vector("file1", "file2")
for (file <- files) {
val in = io.Source.fromFile(file).mkString
var out = ""
var i = 0
while (i < in.length) {
val c = in(i)
if (c == '_') {
out += in(i + 1).toUpper
i += 2
} else {
out += c
i += 1
}
}
val writer = new PrintWriter(file + "1")
writer.write(out)
writer.flush()
writer.close()
}
我想知道如何使该代码发挥作用。我想不出任何高阶函数来替换“如果<某些条件>则将 i 增加 2,否则增加 1”逻辑。谢谢。
i have written a simple script for transforming the c-style identifier names (for example, invoice_number
) to java-style ones (like, invoiceNumber
).
val files = Vector("file1", "file2")
for (file <- files) {
val in = io.Source.fromFile(file).mkString
var out = ""
var i = 0
while (i < in.length) {
val c = in(i)
if (c == '_') {
out += in(i + 1).toUpper
i += 2
} else {
out += c
i += 1
}
}
val writer = new PrintWriter(file + "1")
writer.write(out)
writer.flush()
writer.close()
}
i would like to know how i can make this code functional. i can't think of any higher order function to replace the "increment i by 2 if <some-condition> else increment by 1" logic. thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
好的,这是我的方法。
认为它具有合理的功能风格。有趣的是 scala 专家将如何解决这个问题:)
Ok, here is my way to do it.
Think it's in reasonable functional style. Interesting how scala gurus will solve this problem :)
我很抱歉没有使用 Scala,但基本思想应该翻译,所以这是我在 Haskell 中编写基本逻辑的方式:
我们有两个部分:一个函数,当给定下划线时,或者如果给定时,将字符串的第一个字符大写其他任何内容都会将其添加到字符串前面。然后我们只需在输入字符序列的右折叠中使用它,以空字符串作为基本情况。
请注意,Haskell 中的默认字符串是惰性字符序列,而 Scala 中可能不是这种情况,但我希望类似的事情是可能的,因为 Scala 的功能方面来自与 Haskell 相同的受 ML 启发的传统。
编辑:顺便说一句,请注意,与许多函数式程序员可能期望的相反,我的实现不是尾递归,这是有意且正确的。相反,它在列表的尾部进行递归调用,并且由于 Haskell 中的数据构造函数让事情变得懒惰,因此每个输出字符都是根据需要生成的,而折叠的其余部分则延迟延迟,并且整个过程在恒定的堆栈空间中运行。最终结果本质上是一个消耗输入流中的元素的迭代循环,但编写得看起来像一个简单的递归函数。
尽管在一般情况下你不会这样做,除了 Haskell、惰性列表/生成器/等。如今在许多语言中都很常见,并且用于转换此类流的“消耗有限数量,处理它,产生输出”的习惯用法与语言无关。
另外,我很感谢 Antoras 和 Luigi Plinge 使用类似的算法编写了 Scala 实现,这帮助我对 Scala 有更好的感觉,而我目前对 Scala 只是暂时熟悉。
I apologize for not using Scala, but the basic idea should translate, so here's how I'd write the essential logic in Haskell:
We have two pieces: A function that uppercases the first character of a string when given an underscore, or if given anything else prepends it to the string. Then we just use this in a right fold over the sequence of input characters, with the empty string as the base case.
Note that default strings in Haskell are lazy sequences of characters, which may not be the case in Scala, but I would expect something similar to be possible, since the functional side of Scala comes from the same general ML-inspired tradition that Haskell does.
EDIT: Incidentally, notice that contrary to what many functional programmers might expect, my implementation is not tail recursive, and this is both intentional and correct. Instead it does the recursive call in the tail of the list, and since data constructors in Haskell let things be lazy, each output character is generated on demand with the rest of the fold lazily deferred, and the whole thing runs in constant stack space. The end result is essentially an iterative loop consuming elements from an input stream, but written to look like a simple recursive function.
Even though you wouldn't do things this way in the general case except in Haskell, lazy lists/generators/etc. are common in many languages these days, and the idiom of "consume a finite amount, process it, produce output" for transforming such streams is language-agnostic.
Also, my appreciation to Antoras and Luigi Plinge for writing Scala implementations with similar algorithms--helps me get a better feel for Scala, which I'm only passingly familiar with currently.
另一种解决方案;使用滑动迭代器窗口:
Another solution; using sliding iterator window:
我将 CA McCann 的 Haskell 代码翻译为 Scala:
因为String 是 Scala 中的 IndexedSeq,向其追加内容实际上需要恒定的时间。 Luigi 的代码可以更新为类似的内容:
I translated the Haskell code of C. A. McCann to Scala:
Because String is a IndexedSeq in Scala, appending to it takes effectively constant time. The code of Luigi can be updated to something like that:
我的尾递归刺:
出于某种原因
"string".toSeq
不匹配,但.toList
匹配;也许有人可以解释为什么。编辑:或者这也有效:
My tail recursive stab:
For some reason
"string".toSeq
doesn't match, but.toList
does; maybe someone can explain why.Edit: or this works too:
当然,你可以只使用正则表达式:
编辑:
或者,如果您使用匿名函数,它会更短一些,并且不需要导入(无点):
Of course, you could just use regex:
edit:
or if you use an anonymous function it's a bit shorter and you don't need the import (point-free for kicks):