Scala 编程风格练习
Exercises in programming style with Scala
我最近开始阅读“Exercises in programming style”这本书,其中一项任务是用您选择的语言实现每种编程风格。我决定使用 Scala(我对它还很陌生)并且我已经坚持使用第一种 "good old school" 风格。约束是:
Very small amount of primary memory, typically orders of magnitude smaller than the data that needs to be processed/generated. (The example sets the limit to 1024 cells)
No labels -- i.e. no variable names or tagged memory addresses. All we have is memory that is addressable with numbers.
原始示例(逐行读取文件并计算字数)在 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 数组作为一堆 "memory addresses".
甚至可以在 Scala 中实现老式编程风格(没有变量名或标记内存地址)吗?具体有没有办法在读取文件内容时避免"line"变量?
for (line <- Source.fromFile("example.txt").getLines) {
println(line.toUpperCase)
}
将文件内容读入类似于原始示例的数组不起作用,因为它没有提取器(值数据不是大小写class,也不是有一个 unapply/unapplySeq 成员).
P.S。我非常清楚整个任务在 Scala 中可能是 5 行,但这不是重点。
要获取给定文件中的总字数,可以使用以下 Scala 代码:
Source.fromFile("example.txt")
.getLines.map { line => line.trim.split(" ").length}
.reduceLeft { _ + _ }
当然你可以避免在 data
-array 之外引入变量(并以命令式的方式解决问题)。只需将所有内容放入数组中,而不是将其分配给局部变量。
显然,代码将是一场噩梦,因为数组不会被键入并且您不会为任何数据命名任何有意义的名称,但我假设这就是您的目标这个练习。
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
}
}
我最近开始阅读“Exercises in programming style”这本书,其中一项任务是用您选择的语言实现每种编程风格。我决定使用 Scala(我对它还很陌生)并且我已经坚持使用第一种 "good old school" 风格。约束是:
Very small amount of primary memory, typically orders of magnitude smaller than the data that needs to be processed/generated. (The example sets the limit to 1024 cells)
No labels -- i.e. no variable names or tagged memory addresses. All we have is memory that is addressable with numbers.
原始示例(逐行读取文件并计算字数)在 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 数组作为一堆 "memory addresses".
甚至可以在 Scala 中实现老式编程风格(没有变量名或标记内存地址)吗?具体有没有办法在读取文件内容时避免"line"变量?
for (line <- Source.fromFile("example.txt").getLines) {
println(line.toUpperCase)
}
将文件内容读入类似于原始示例的数组不起作用,因为它没有提取器(值数据不是大小写class,也不是有一个 unapply/unapplySeq 成员).
P.S。我非常清楚整个任务在 Scala 中可能是 5 行,但这不是重点。
要获取给定文件中的总字数,可以使用以下 Scala 代码:
Source.fromFile("example.txt")
.getLines.map { line => line.trim.split(" ").length}
.reduceLeft { _ + _ }
当然你可以避免在 data
-array 之外引入变量(并以命令式的方式解决问题)。只需将所有内容放入数组中,而不是将其分配给局部变量。
显然,代码将是一场噩梦,因为数组不会被键入并且您不会为任何数据命名任何有意义的名称,但我假设这就是您的目标这个练习。
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
}
}