我最近开始阅读“Exercises in programming style”一书,其中一项任务是用您选择的语言实现每种编程风格。我决定和Scala一起去(我对它很新)我已经坚持了第一个“好老派”的风格。约束是:
非常少量的主存储器,通常比需要处理/生成的数据小几个数量级。 (该示例将限制设置为1024个单元格)
没有标签 - 即没有变量名称或标记的内存地址。我们所拥有的只是可通过数字寻址的记忆。
原始示例(逐行读取文件并对单词进行计数)在Python中,如下所示:
data = []
data.append([]) # data[1] is line (max 80 characters)
data.append(None) # data[2] is index of the start_char of word
data.append(0) # data[3] is index on characters, i = 0
data.append(False) # data[4] is flag indicating if word was found
data.append('') # data[5] is the word
data.append('') # data[6] is word,NNNN
data.append(0) # data[7] is frequency
...
f = open(sys.argv[1])
# Loop over input file's lines
while True:
data[1] = [f.readline()]
...
所以我们看到有一些变量(f和数据),但主要思想是将其保持在最低限度并将python数组用作一堆“内存地址”。
甚至可以在Scala中实现老派编程风格(没有变量名称或标记的内存地址)?具体来说,有一种方法可以在读取文件内容时避免“行”变量吗?
for (line <- Source.fromFile("example.txt").getLines) {
println(line.toUpperCase)
}
将文件内容读入类似于原始示例的数组不起作用,因为它没有提取器(值数据不是案例类,也没有unapply / unapplySeq成员)。
P.S。我非常清楚整个任务可能是Scala中的5个班轮,但这不是重点。
答案 0 :(得分:0)
要获取给定文件中的总字数,可以使用以下标量代码:
Source.fromFile("example.txt")
.getLines.map { line => line.trim.split(" ").length}
.reduceLeft { _ + _ }
答案 1 :(得分:0)
当然,你可以避免引入除data
- 数组之外的变量(并解决问题命令式)。只需将所有内容放入数组中,而不是将其分配给局部变量。
显然,代码将是一场噩梦,因为数组不会被输入,你的任何数据都没有任何有意义的名称,但我认为你的目标就是这个练习。
import scala.io.Source
/**
* data 0 : file as line iterator
* data 1 : index of first unused data cell
* data 2 : current line
* data 3 : index of the first letter of the current word
* data 4 : index of the last letter of the current word
* data 5 : current word
* data 6 : temp index to find already initialized words
* data 7 : flag: Word found
* data 8, 10, 12, ... words
* data 9, 11, 13, ... frequencies
*/
object GoodOldSchool {
def main(args: Array[String]): Unit = {
val data: Array[Any] = new Array[Any](1024)
data(0) = Source.fromFile(args(0)).getLines()
data(1) = 8 // first free cell
while (data(0).asInstanceOf[Iterator[String]].hasNext) {
data(2) = data(0).asInstanceOf[Iterator[String]].next()
data(3) = 0 // index first letter of current word
data(4) = 0 // index last letter of current word
// find index last letter of current word
while (data(4).asInstanceOf[Int] < data(2).asInstanceOf[String].length) {
// find the next space (we ignore punctuation)
while (data(4).asInstanceOf[Int] < data(2).asInstanceOf[String].length && data(2).asInstanceOf[String].charAt(data(4).asInstanceOf[Int]) != ' ') {
data(4) = data(4).asInstanceOf[Int] + 1
}
data(5) = data(2).asInstanceOf[String].substring(data(3).asInstanceOf[Int], data(4).asInstanceOf[Int]) // current word
data(6) = 8 // cell index
data(7) = false // word already found
8 until data(1).asInstanceOf[Int] by 2 foreach { _ =>
// Here, we do a case-sensitive word comparison
if (data(5) == data(data(6).asInstanceOf[Int])) {
data(data(6).asInstanceOf[Int] + 1) = data(data(6).asInstanceOf[Int] + 1).asInstanceOf[Int] + 1 // increment frequency
data(7) = true
}
data(6) = data(6).asInstanceOf[Int] + 2
}
if (data(7) == false) {
// create new frequency, because word was not discovered before
data(data(1).asInstanceOf[Int]) = data(5) // set word
data(data(1).asInstanceOf[Int] + 1) = 1 // set frequency
data(1) = data(1).asInstanceOf[Int] + 2 // used up two cells, update index of next free cell
}
// move to next word
data(3) = data(4).asInstanceOf[Int] + 1
data(4) = data(3)
}
}
data foreach println // let's have a look at our result
}
}