功能Scala的重构/布局

The*_*aul 12 refactoring functional-programming coding-style scala

这个班轮......

 Console.println(io.Source.fromFile("names.txt").getLines.mkString.split(",").map{x:String => x.slice(1, x.length -1)}.sortBy { x => x}.zipWithIndex.map{t =>{ (t._2 +1)*(t._1.map{_.toChar - "A"(0).toChar + 1}.sum)}}.sum);
Run Code Online (Sandbox Code Playgroud)

...是我对Project Euler问题22的解决方案.它似乎工作,它写在(我的尝试)功能风格.

这个例子有点极端,但我的问题更为笼统 - 您更喜欢编写/格式化/评论功能样式代码?功能方法似乎鼓励了一系列方法调用,我发现这些方法调用不可读,而且放置注释也无处可寻.

此外,当我编写过程代码时,我发现我编写了一些小方法,每个方法都有一个目的和有意义的名称.当我编写功能代码时,我似乎正在养成一种习惯,这种习惯产生的线条与上面的线条有点差别,其中(对我而言)意义难以破译 - 而且个别计算也难以在其他地方重复使用.我在网上看到的很多功能代码示例同样简洁(对我而言)模糊不清.

我该怎么办?为当前上下文中有意义的名称编写计算的每个部分的小函数?(即使它们只是地图的包装,说?)

对于我给出的例子,有什么更好的方法来编写它并呈现它?

(就像所有风格的问题一样,这个问题是主观的.但是没有理由它应该引起争议!)

Kev*_*ght 19

一个简单的第一次尝试来整理它就是删除引导Console.尾随;和显式:String类型 - 所有这些都是不必要的 - 添加一些缩进并导入io.Source:

import io.Source
println(
  Source.fromFile("names.txt").getLines.mkString.split(",").map{
    x => x.slice(1, x.length -1)
  }.sortBy {x => x}.zipWithIndex.map{
    t =>{ (t._2 +1)*(t._1.map{_.toChar - "A"(0).toChar + 1}.sum)}
  }.sum
)
Run Code Online (Sandbox Code Playgroud)

下一步是清理一下,在映射元组列表时使用模式匹配而identity不是x=>x.toChar字符也是不必要的,单引号可用于表示字符文字.

import io.Source
println(
  Source.fromFile("names.txt").getLines.mkString.split(",").map {
    x => x.slice(1, x.length -1)
  }.sortBy(identity).zipWithIndex.map {
    case (v, idx) =>{ (idx+1)*(v.map{_ - 'A' + 1}.sum)}
  }.sum
)
Run Code Online (Sandbox Code Playgroud)

还有一些更改也有助于使代码的意图更加清晰:

import io.Source
println(
  Source.fromFile("names.txt").getLines.mkString.split(",")
  .map { _.stripPrefix("\"").stripSuffix("\"") }
  .sortBy(identity)
  .map { _.map{_ - 'A' + 1}.sum }
  .zipWithIndex
  .map { case (v, idx) => (idx+1) * v }
  .sum
)
Run Code Online (Sandbox Code Playgroud)

下一步,使其更具"功能性",是将其分解为"功能"(偷偷摸摸,是吧?).理想情况下,每个函数都会有一个清楚地表达其目的的名称,并且它将很短(旨在使其成为单个表达式,因此不需要括号):

import io.Source

def unquote(s:String) = s.stripPrefix("\"").stripSuffix("\"")

def wordsFrom(fname:String) =
  Source.fromFile(fname).getLines.mkString.split(",").map(unquote)

def letterPos(c:Char) = c - 'A' + 1

println(
  wordsFrom("names.txt")
  .sortBy(identity)
  .map { _.map(letterPos).sum }
  .zipWithIndex
  .map { case (v, idx) => (idx+1) * v }
  .sum
)
Run Code Online (Sandbox Code Playgroud)

wordsFrom 是一个明显的1线程,但我拆分它以便在stackOverflow上更容易格式化

  • +1这非常接近我认为对这个问题的完美答案.轻微的挑剔:不会"排序"优于"sortBy(身份)"? (2认同)