scala中函数式编程的一个例子

Rat*_*man 7 functional-programming scala

我正在学习斯卡拉.感谢Odersky和所有其他作者的出色工作,这是非常有前途的.

我把一个欧拉问题(http://projecteuler.net/)带到了一个更加极小的例子.而我正试图以功能的方式.所以这不是"请立即回答我,否则我的老板会杀了我",但是"如果你有时间,请你帮助一位势在必行的语言程序员去实现功能世界吗?"

问题:我想要一个扑克牌课.一个扑克之手是由一些卡片组成的,从0到5.我想建立一个卡片列表,这就是:我的Hand类将是不可变的,如果我想添加一张卡片,那么我创建了一个新的Hand对象.所以我需要一个可以创建为"val"的Card集合,而不是var.第一步:构造函数,每个卡数一个.但是Card的集合在每个构造函数中处理,所以我必须将它作为var!

这是代码,Card类只是一个Suit和一个Value,作为一个字符串传递给构造函数("5S"是黑桃的5个):

class Hand(mycards : List[Card]) {
  // this should be val, I guess
  private var cards : List[Card] = {
    if (mycards.length>5)
      throw new IllegalArgumentException(
        "Illegal number of cards: " + mycards.length);
    sortCards(mycards)
  }

  // full hand constructor
  def this(a : String, b : String, c : String, d : String, e : String) = {
      this(Nil)

      // assign cards
      val cardBuffer = new ListBuffer[Card]()
      if ( a!=null ) cardBuffer += new Card(a)
      if ( b!=null ) cardBuffer += new Card(b)
      if ( c!=null ) cardBuffer += new Card(c)
      if ( d!=null ) cardBuffer += new Card(d)
      if ( e!=null ) cardBuffer += new Card(e)
      cards = sortCards(cardBuffer.toList)
  }
  // hand with less then 5 cards
  def this(a : String, b : String, c : String, d : String) = this(a,b,c,d,null)
  def this(a : String, b : String, c : String) = this(a, b, c, null)
  def this(a : String, b : String) = this(a, b, null)
  def this(a : String) = this(a, null)
  def this() = this(Nil)

/* removed */
}
Run Code Online (Sandbox Code Playgroud)

你知道如何使它成为真正的功能方式吗?谢谢.

PS:如果你真的想知道,那就是问题54.

om-*_*nom 6

我的答案不是关于scala的功能方面,但是你的代码很快就可以用scala sugar编写:

class Hand(val mycards: List[Card]) {
  require (mycards.size <= 5,"can't be more than five cards")
  def this(input: String*) = { 
    this(input.map(c => new Card(c)).toList)
  }
}
Run Code Online (Sandbox Code Playgroud)

input: String*在辅助构造函数中说你可以有可变数量的参数(甚至数千个字符串).我正在获取输入并为每个具有map函数的新卡调用创建,然后将结果传递给具有它自己的要求的父构造函数.(顺便说一句,映射从字符串到卡可以匿名进行,以这种方式:this(input.map(new Card(_)).toList))

class Hand(val mycards: List[Card]) {...

是平等的

class Hand(cards: List[Card]) {
val mycards = cards 
...
Run Code Online (Sandbox Code Playgroud)

从现在开始,如果您将尝试创建五张以上的卡片,您将获得java.lang.IllegalArgumentException:

scala> class Card(s: String) {println("Im a :"+s)}
defined class Card

scala> new Hand("one","two","three","four","five","six")
Im a :one
Im a :two
Im a :three
Im a :four
Im a :five
Im a :six
java.lang.IllegalArgumentException: requirement failed: can't be more than five card
    at scala.Predef$.require(Predef.scala:157)
    at Hand.<init>(<console>:9)
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 5

好吧,var下面代码中的 来自您没有cards从主构造函数初始化:

// this should be val, I guess
private var cards : List[Card] = {
  if (mycards.length>5)
    throw new IllegalArgumentException(
      "Illegal number of cards: " + mycards.length);
  sortCards(mycards)
}
Run Code Online (Sandbox Code Playgroud)

所以你需要做的是修复二级构造函数:

// full hand constructor
def this(a : String, b : String, c : String, d : String, e : String) = {
    this(Nil)

    // assign cards
    val cardBuffer = new ListBuffer[Card]()
    if ( a!=null ) cardBuffer += new Card(a)
    if ( b!=null ) cardBuffer += new Card(b)
    if ( c!=null ) cardBuffer += new Card(c)
    if ( d!=null ) cardBuffer += new Card(d)
    if ( e!=null ) cardBuffer += new Card(e)
    cards = sortCards(cardBuffer.toList)
}
Run Code Online (Sandbox Code Playgroud)

问题很简单:你想要一个由非空字符串组成的卡片列表。如果我是你,我会避免传递空值,但是......无论如何,最好的处理方法是将其转换为选项。转换很简单:Option(a)将返回Some(a)a不是空的,None如果它是。如果您编写了一个列表,则可以将flatten其删除None并转换Some(a)a. 换句话说:

def this(a : String, b : String, c : String, d : String, e : String) = 
    this(List(a, b, c, d, e).map(Option(_)).flatten.map(Card(_)))
Run Code Online (Sandbox Code Playgroud)