This page is no longer maintained — Please continue to the home page at www.scala-lang.org

A post on Scala pattern matching

7 replies
Iwan Memruk
Joined: 2009-09-21,
User offline. Last seen 42 years 45 weeks ago.
Hi guys.
I've posted something about Scala pattern matching that has been bothering me for some time.Please read and feel free to comment ;)
http://zxczxc.wordpress.com/2009/09/20/a-basic-scala-feature-but-is-it-good-oop/
Thanks,
Ivan
ray.mcdermott
Joined: 2009-09-16,
User offline. Last seen 42 years 45 weeks ago.
List / Sequence mess

I am looking for some advice from the older kids again ;-)

Last time I was playing with a grid and the game continues.  I want to add words to the grid but find that this is full of type mismatches, which I have commented in the code below.

This experience dims the Scala lustre a little for me since I don't want to have all of this 'casting' and type manipulation in the code.  And I imagine that it is not needed .... or should I say that I hope it is not needed and so I am looking to you experts for some more tips and tricks.

Here is the code along with my queries / complaints....

// Add words to a grid in the horizontal plane
class Horizontal (grid: Array[Array[String]]) extends Direction {

    override def addWord(word: String) = {

        val possibleStartingPoints = for(row <- 0 until grid.length; column <- 0 until (grid(0).length - word.length)) yield new Coordinate(row, column)

        val allowableStartingPoints = possibleStartingPoints.filter(checkWordAllowable(word, _))

        addWordHorizontal(word, allowableStartingPoints(new Random().nextInt(allowableStartingPoints.length)))
    }

    // Can safely assume that the word will fit ... but will the letters of this word clash with another?
    private def checkWordAllowable(word: String, coordinate: Coordinate) : Boolean = {

        val gridLetters = for (letter <- coordinate.y until (coordinate.y + word.length)) yield grid(coordinate.x)(letter)

        val wordAsLetterList = getWordAsList(word)

//        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters // Would be nice but...
//              found   : RandomAccessSeq.Projection[String]
//              required: List[?]

        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters.toList // toList casting :(

        val allowableSpaceList = for (pair <- wordLettersGridLettersPairs) yield (pair._2 == null || pair._1 == pair._2)

        wordAsLetterList.length == allowableSpaceList.length
    }

    private def getWordAsList(word: String) : List[String] = {
//        for (letter <- 0 until word.length) yield word.substring(letter, letter+1)    // Would be nicer methinks but...
// Compiler complains:          found   : RandomAccessSeq.Projection[java.lang.String]
//                              required: List[String]
        val wordAsList = for (letter <- 0 until word.length) yield word.substring(letter, letter+1)
        wordAsList.toList
    }

    // A little clunky, but this works
    private def addWordHorizontal(word: String, coordinate: Coordinate) = {
        var gridCoordinate = coordinate
        for (letter <- getWordAsList(word)) {
            grid(gridCoordinate.x)(gridCoordinate.y) = letter
            gridCoordinate = new Coordinate(coordinate.x, gridCoordinate.y + 1)
        }
    }
}

// Abstract class ... no complaints here - I will use this as a base for horizontal, diagonal and vertical
abstract class Direction {

    def addWord(word: String)
 
}

Any help or advice would be greatly appreciated

Ray
Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: List / Sequence mess

(for (foo <- foos) yield new Bar(foo.name)).toList

The toList should fix your two issues. I'm surprised zip needs a List
and not a Seq.

2009/9/21 :
>
> I am looking for some advice from the older kids again ;-)
>
> Last time I was playing with a grid and the game continues.  I want to add
> words to the grid but find that this is full of type mismatches, which I
> have commented in the code below.
>
> This experience dims the Scala lustre a little for me since I don't want to
> have all of this 'casting' and type manipulation in the code.  And I imagine
> that it is not needed .... or should I say that I hope it is not needed and
> so I am looking to you experts for some more tips and tricks.
>
> Here is the code along with my queries / complaints....
>
> // Add words to a grid in the horizontal plane
> class Horizontal (grid: Array[Array[String]]) extends Direction {
>
>     override def addWord(word: String) = {
>
>         val possibleStartingPoints = for(row <- 0 until grid.length; column
> <- 0 until (grid(0).length - word.length)) yield new Coordinate(row, column)
>
>         val allowableStartingPoints =
> possibleStartingPoints.filter(checkWordAllowable(word, _))
>
>         addWordHorizontal(word, allowableStartingPoints(new
> Random().nextInt(allowableStartingPoints.length)))
>     }
>
>     // Can safely assume that the word will fit ... but will the letters of
> this word clash with another?
>     private def checkWordAllowable(word: String, coordinate: Coordinate) :
> Boolean = {
>
>         val gridLetters = for (letter <- coordinate.y until (coordinate.y +
> word.length)) yield grid(coordinate.x)(letter)
>
>         val wordAsLetterList = getWordAsList(word)
>
> //        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters
> // Would be nice but...
> //              found   : RandomAccessSeq.Projection[String]
> //              required: List[?]
>
>         val wordLettersGridLettersPairs = wordAsLetterList zip
> gridLetters.toList // toList casting :(
>
>         val allowableSpaceList = for (pair <- wordLettersGridLettersPairs)
> yield (pair._2 == null || pair._1 == pair._2)
>
>         wordAsLetterList.length == allowableSpaceList.length
>     }
>
>     private def getWordAsList(word: String) : List[String] = {
> //        for (letter <- 0 until word.length) yield word.substring(letter,
> letter+1)    // Would be nicer methinks but...
> // Compiler complains:          found   :
> RandomAccessSeq.Projection[java.lang.String]
> //                              required: List[String]
>         val wordAsList = for (letter <- 0 until word.length) yield
> word.substring(letter, letter+1)
>         wordAsList.toList
>     }
>
>     // A little clunky, but this works
>     private def addWordHorizontal(word: String, coordinate: Coordinate) = {
>         var gridCoordinate = coordinate
>         for (letter <- getWordAsList(word)) {
>             grid(gridCoordinate.x)(gridCoordinate.y) = letter
>             gridCoordinate = new Coordinate(coordinate.x, gridCoordinate.y +
> 1)
>         }
>     }
> }
>
> // Abstract class ... no complaints here - I will use this as a base for
> horizontal, diagonal and vertical
> abstract class Direction {
>
>     def addWord(word: String)
>
> }
>
> Any help or advice would be greatly appreciated
>
> Ray

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: List / Sequence mess


On Mon, Sep 21, 2009 at 2:27 PM, Ricky Clarkson <ricky [dot] clarkson [at] gmail [dot] com> wrote:
(for (foo <- foos) yield new Bar(foo.name)).toList

The toList should fix your two issues.  I'm surprised zip needs a List
and not a Seq.

I was also surprised.
 

2009/9/21  <Ray [dot] Mcdermott [at] toyota-europe [dot] com>:
>
> I am looking for some advice from the older kids again ;-)
>
> Last time I was playing with a grid and the game continues.  I want to add
> words to the grid but find that this is full of type mismatches, which I
> have commented in the code below.
>
> This experience dims the Scala lustre a little for me since I don't want to
> have all of this 'casting' and type manipulation in the code.  And I imagine
> that it is not needed .... or should I say that I hope it is not needed and
> so I am looking to you experts for some more tips and tricks.
>
> Here is the code along with my queries / complaints....
>
> // Add words to a grid in the horizontal plane
> class Horizontal (grid: Array[Array[String]]) extends Direction {
>
>     override def addWord(word: String) = {
>
>         val possibleStartingPoints = for(row <- 0 until grid.length; column
> <- 0 until (grid(0).length - word.length)) yield new Coordinate(row, column)
>
>         val allowableStartingPoints =
> possibleStartingPoints.filter(checkWordAllowable(word, _))
>
>         addWordHorizontal(word, allowableStartingPoints(new
> Random().nextInt(allowableStartingPoints.length)))
>     }
>
>     // Can safely assume that the word will fit ... but will the letters of
> this word clash with another?
>     private def checkWordAllowable(word: String, coordinate: Coordinate) :
> Boolean = {
>
>         val gridLetters = for (letter <- coordinate.y until (coordinate.y +
> word.length)) yield grid(coordinate.x)(letter)
>
>         val wordAsLetterList = getWordAsList(word)
>
> //        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters
> // Would be nice but...
> //              found   : RandomAccessSeq.Projection[String]
> //              required: List[?]
>
>         val wordLettersGridLettersPairs = wordAsLetterList zip
> gridLetters.toList // toList casting :(
>
>         val allowableSpaceList = for (pair <- wordLettersGridLettersPairs)
> yield (pair._2 == null || pair._1 == pair._2)
>
>         wordAsLetterList.length == allowableSpaceList.length
>     }
>
>     private def getWordAsList(word: String) : List[String] = {
> //        for (letter <- 0 until word.length) yield word.substring(letter,
> letter+1)    // Would be nicer methinks but...
> // Compiler complains:          found   :
> RandomAccessSeq.Projection[java.lang.String]
> //                              required: List[String]
>         val wordAsList = for (letter <- 0 until word.length) yield
> word.substring(letter, letter+1)
>         wordAsList.toList
>     }
>
>     // A little clunky, but this works
>     private def addWordHorizontal(word: String, coordinate: Coordinate) = {
>         var gridCoordinate = coordinate
>         for (letter <- getWordAsList(word)) {
>             grid(gridCoordinate.x)(gridCoordinate.y) = letter
>             gridCoordinate = new Coordinate(coordinate.x, gridCoordinate.y +
> 1)
>         }
>     }
> }
>
> // Abstract class ... no complaints here - I will use this as a base for
> horizontal, diagonal and vertical
> abstract class Direction {
>
>     def addWord(word: String)
>
> }
>
> Any help or advice would be greatly appreciated
>
> Ray



--
Ricky Clarkson
Java Programmer, AD Holdings
+44 1565 770804
Skype: ricky_clarkson
Google Talk: ricky [dot] clarkson [at] gmail [dot] com



--
Viktor Klang

Blog: klangism.blogspot.com
Twttr: viktorklang

Lift Committer - liftweb.com
AKKA Committer - akkasource.org
Cassidy - github.com/viktorklang/Cassidy.git
SoftPub founder: http://groups.google.com/group/softpub
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: List / Sequence mess
Hello Ray,

yield constructs different containers depending on the generator:

scala> for (i <- 0 until 5) yield i*i
res0: RandomAccessSeq.Projection[Int] = RangeM(0, 1, 4, 9, 16)

scala> for (i <- List(0,1,2,3,45)) yield i*i
res1: List[Int] = List(0, 1, 4, 9, 2025)

On Mon, Sep 21, 2009 at 2:21 PM, <Ray [dot] Mcdermott [at] toyota-europe [dot] com> wrote:

I am looking for some advice from the older kids again ;-)

Last time I was playing with a grid and the game continues.  I want to add words to the grid but find that this is full of type mismatches, which I have commented in the code below.

This experience dims the Scala lustre a little for me since I don't want to have all of this 'casting' and type manipulation in the code.  And I imagine that it is not needed .... or should I say that I hope it is not needed and so I am looking to you experts for some more tips and tricks.

Here is the code along with my queries / complaints....

// Add words to a grid in the horizontal plane
class Horizontal (grid: Array[Array[String]]) extends Direction {

    override def addWord(word: String) = {

        val possibleStartingPoints = for(row <- 0 until grid.length; column <- 0 until (grid(0).length - word.length)) yield new Coordinate(row, column)

        val allowableStartingPoints = possibleStartingPoints.filter(checkWordAllowable(word, _))

        addWordHorizontal(word, allowableStartingPoints(new Random().nextInt(allowableStartingPoints.length)))
    }

    // Can safely assume that the word will fit ... but will the letters of this word clash with another?
    private def checkWordAllowable(word: String, coordinate: Coordinate) : Boolean = {

        val gridLetters = for (letter <- coordinate.y until (coordinate.y + word.length)) yield grid(coordinate.x)(letter)

        val wordAsLetterList = getWordAsList(word)

//        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters // Would be nice but...
//              found   : RandomAccessSeq.Projection[String]
//              required: List[?]

        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters.toList // toList casting :(

        val allowableSpaceList = for (pair <- wordLettersGridLettersPairs) yield (pair._2 == null || pair._1 == pair._2)

        wordAsLetterList.length == allowableSpaceList.length
    }

    private def getWordAsList(word: String) : List[String] = {
//        for (letter <- 0 until word.length) yield word.substring(letter, letter+1)    // Would be nicer methinks but...
// Compiler complains:          found   : RandomAccessSeq.Projection[java.lang.String]
//                              required: List[String]
        val wordAsList = for (letter <- 0 until word.length) yield word.substring(letter, letter+1)
        wordAsList.toList
    }

    // A little clunky, but this works
    private def addWordHorizontal(word: String, coordinate: Coordinate) = {
        var gridCoordinate = coordinate
        for (letter <- getWordAsList(word)) {
            grid(gridCoordinate.x)(gridCoordinate.y) = letter
            gridCoordinate = new Coordinate(coordinate.x, gridCoordinate.y + 1)
        }
    }
}

// Abstract class ... no complaints here - I will use this as a base for horizontal, diagonal and vertical
abstract class Direction {

    def addWord(word: String)
 
}

Any help or advice would be greatly appreciated

Ray



--
Viktor Klang

Blog: klangism.blogspot.com
Twttr: viktorklang

Lift Committer - liftweb.com
AKKA Committer - akkasource.org
Cassidy - github.com/viktorklang/Cassidy.git
SoftPub founder: http://groups.google.com/group/softpub
ray.mcdermott
Joined: 2009-09-16,
User offline. Last seen 42 years 45 weeks ago.
Re: List / Sequence mess

Viktor - I had intuited that, but I still find the need to code like this:

(for....).toList

a little, well ugly.

Of course sometimes one can and must live with ugliness.  I have a mirror to prove that ;-)

Thanks for the help

Ray









Viktor Klang <viktor [dot] klang [at] gmail [dot] com>
21/09/2009 14:29 To Ray [dot] Mcdermott [at] toyota-europe [dot] com cc scala-user [at] listes [dot] epfl [dot] ch Subject Re: [scala-user] List / Sequence mess




Hello Ray,

yield constructs different containers depending on the generator:

scala> for (i <- 0 until 5) yield i*i
res0: RandomAccessSeq.Projection[Int] = RangeM(0, 1, 4, 9, 16)

scala> for (i <- List(0,1,2,3,45)) yield i*i
res1: List[Int] = List(0, 1, 4, 9, 2025)

On Mon, Sep 21, 2009 at 2:21 PM, <Ray [dot] Mcdermott [at] toyota-europe [dot] com (Ray [dot] Mcdermott [at] toyota-europe [dot] com)> wrote:

I am looking for some advice from the older kids again ;-)

Last time I was playing with a grid and the game continues.  I want to add words to the grid but find that this is full of type mismatches, which I have commented in the code below.

This experience dims the Scala lustre a little for me since I don't want to have all of this 'casting' and type manipulation in the code.  And I imagine that it is not needed .... or should I say that I hope it is not needed and so I am looking to you experts for some more tips and tricks.

Here is the code along with my queries / complaints....

// Add words to a grid in the horizontal plane

class Horizontal (grid: Array[Array[String]]) extends Direction {


    override def addWord(word: String) = {


        val possibleStartingPoints = for(row <- 0 until grid.length; column <- 0 until (grid(0).length - word.length)) yield new Coordinate(row, column)


        val allowableStartingPoints = possibleStartingPoints.filter(checkWordAllowable(word, _))


        addWordHorizontal(word, allowableStartingPoints(new Random().nextInt(allowableStartingPoints.length)))

    }


    // Can safely assume that the word will fit ... but will the letters of this word clash with another?

    private def checkWordAllowable(word: String, coordinate: Coordinate) : Boolean = {


        val gridLetters = for (letter <- coordinate.y until (coordinate.y + word.length)) yield grid(coordinate.x)(letter)


        val wordAsLetterList = getWordAsList(word)


//        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters // Would be nice but...

//              found   : RandomAccessSeq.Projection[String]

//              required: List[?]


        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters.toList // toList casting :(


        val allowableSpaceList = for (pair <- wordLettersGridLettersPairs) yield (pair._2 == null || pair._1 == pair._2)


        wordAsLetterList.length == allowableSpaceList.length

    }


    private def getWordAsList(word: String) : List[String] = {

//        for (letter <- 0 until word.length) yield word.substring(letter, letter+1)    // Would be nicer methinks but...

// Compiler complains:          found   : RandomAccessSeq.Projection[java.lang.String]

//                              required: List[String]

        val wordAsList = for (letter <- 0 until word.length) yield word.substring(letter, letter+1)

        wordAsList.toList

    }


    // A little clunky, but this works

    private def addWordHorizontal(word: String, coordinate: Coordinate) = {

        var gridCoordinate = coordinate

        for (letter <- getWordAsList(word)) {

            grid(gridCoordinate.x)(gridCoordinate.y) = letter

            gridCoordinate = new Coordinate(coordinate.x, gridCoordinate.y + 1)

        }

    }

}


// Abstract class ... no complaints here - I will use this as a base for horizontal, diagonal and vertical

abstract class Direction {


    def addWord(word: String)

 

}


Any help or advice would be greatly appreciated

Ray



dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: List / Sequence mess
1) Apply "toList" to the range:   val iSquared = for(i <- 1 to 5 toList) yield i * i   Note that this implies all the yields will be computed. When you map (use for-comprehension) over a Range, then nothing will be immediately computed. Instead, when you access a member of the resulting range (RandomAccessSeq.Projection, which is the result of "map" over a Range), it will compute the element. This can be quite interesting if you don't need access to all elements, and terrible if you access the same element over and over (because the result isn't cached).   2) Create a List from a range:   val iSquared = for(i <- List.range(1,6)) yield i * i
  On Mon, Sep 21, 2009 at 9:37 AM, <Ray [dot] Mcdermott [at] toyota-europe [dot] com> wrote:

Viktor - I had intuited that, but I still find the need to code like this:

(for....).toList

a little, well ugly.

Of course sometimes one can and must live with ugliness.  I have a mirror to prove that ;-)

Thanks for the help

Ray









Viktor Klang <viktor [dot] klang [at] gmail [dot] com>
21/09/2009 14:29 To Ray [dot] Mcdermott [at] toyota-europe [dot] com cc scala-user [at] listes [dot] epfl [dot] ch Subject Re: [scala-user] List / Sequence mess




Hello Ray,

yield constructs different containers depending on the generator:

scala> for (i <- 0 until 5) yield i*i
res0: RandomAccessSeq.Projection[Int] = RangeM(0, 1, 4, 9, 16)

scala> for (i <- List(0,1,2,3,45)) yield i*i
res1: List[Int] = List(0, 1, 4, 9, 2025)

On Mon, Sep 21, 2009 at 2:21 PM, <Ray [dot] Mcdermott [at] toyota-europe [dot] com (Ray [dot] Mcdermott [at] toyota-europe [dot] com)> wrote:

I am looking for some advice from the older kids again ;-)

Last time I was playing with a grid and the game continues.  I want to add words to the grid but find that this is full of type mismatches, which I have commented in the code below.

This experience dims the Scala lustre a little for me since I don't want to have all of this 'casting' and type manipulation in the code.  And I imagine that it is not needed .... or should I say that I hope it is not needed and so I am looking to you experts for some more tips and tricks.

Here is the code along with my queries / complaints....

// Add words to a grid in the horizontal plane

class Horizontal (grid: Array[Array[String]]) extends Direction {


    override def addWord(word: String) = {


        val possibleStartingPoints = for(row <- 0 until grid.length; column <- 0 until (grid(0).length - word.length)) yield new Coordinate(row, column)


        val allowableStartingPoints = possibleStartingPoints.filter(checkWordAllowable(word, _))


        addWordHorizontal(word, allowableStartingPoints(new Random().nextInt(allowableStartingPoints.length)))

    }


    // Can safely assume that the word will fit ... but will the letters of this word clash with another?

    private def checkWordAllowable(word: String, coordinate: Coordinate) : Boolean = {


        val gridLetters = for (letter <- coordinate.y until (coordinate.y + word.length)) yield grid(coordinate.x)(letter)


        val wordAsLetterList = getWordAsList(word)


//        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters // Would be nice but...

//              found   : RandomAccessSeq.Projection[String]

//              required: List[?]


        val wordLettersGridLettersPairs = wordAsLetterList zip gridLetters.toList // toList casting :(


        val allowableSpaceList = for (pair <- wordLettersGridLettersPairs) yield (pair._2 == null || pair._1 == pair._2)


        wordAsLetterList.length == allowableSpaceList.length

    }


    private def getWordAsList(word: String) : List[String] = {

//        for (letter <- 0 until word.length) yield word.substring(letter, letter+1)    // Would be nicer methinks but...

// Compiler complains:          found   : RandomAccessSeq.Projection[java.lang.String]

//                              required: List[String]

        val wordAsList = for (letter <- 0 until word.length) yield word.substring(letter, letter+1)

        wordAsList.toList

    }


    // A little clunky, but this works

    private def addWordHorizontal(word: String, coordinate: Coordinate) = {

        var gridCoordinate = coordinate

        for (letter <- getWordAsList(word)) {

            grid(gridCoordinate.x)(gridCoordinate.y) = letter

            gridCoordinate = new Coordinate(coordinate.x, gridCoordinate.y + 1)

        }

    }

}


// Abstract class ... no complaints here - I will use this as a base for horizontal, diagonal and vertical

abstract class Direction {


    def addWord(word: String)

 

}


Any help or advice would be greatly appreciated

Ray



--
Viktor Klang

Blog: klangism.blogspot.com
Twttr: viktorklang

Lift Committer - liftweb.com
AKKA Committer - akkasource.org
Cassidy - github.com/viktorklang/Cassidy.git
SoftPub founder: http://groups.google.com/group/softpub



--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
Phil! Gold
Joined: 2009-03-30,
User offline. Last seen 42 years 45 weeks ago.
Re: A post on Scala pattern matching

* Iwan Memruk [2009-09-21 10:01 +0300]:
> I've posted something about Scala pattern matching that has been bothering
> me for some time.
>
> http://zxczxc.wordpress.com/2009/09/20/a-basic-scala-feature-but-is-it-g...

See this page where Martin Odersky discusses pattern matching:

http://www.artima.com/scalazine/articles/pattern_matching.html

He discusses the difference between pattern matching and polymorphism and
what circumstances each one might be appropriate for.

I would tend to categorize it based on your chosen programming style
(chosen as appropriate for your problem): if you're writing OO code with a
functional accent, use polymorphism; if you're writing functional code
with an OO accent, pattern metching might be more appropriate.

There's also stuff like Option or Either, where pattern matching is
without question the best way to go.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland