I have a case class called Cell and it has parameter-less methods for moving cells up, down, left, right...
 case class Cell(topLeft: Coordinate, botRight: Coordinate) {
  def up: Cell = {
    Cell(
      Coordinate(topLeft.x + 0, topLeft.y - 1)
      , Coordinate(botRight.x + 0, botRight.y - 1))
  }
}
It feels right that this up operation should be an instance method and be called like so:
val cell = Cell(x,y)
cell.up
However, if I make these operations static functions belonging to a companion object, like so,
object Cell{
  def up(cell: Cell): Cell = {
    Cell(
      Coordinate(cell.topLeft.x + 0, cell.topLeft.y - 1)
      , Coordinate(cell.botRight.x + 0, cell.botRight.y - 1))
  }
...
}
then they seem more composable. Now I can pass around up, down, left,or right as a parameter of type Cell => Cell. As a parameter-less instance method it is equivalent to a value and so can't be passed as a function.
See both commented lines below.
    private def move(move: Cell => Cell, team: Team, nucleus: Coordinate): Team = {
    val (mover, others) = team.cells.partition(_.nucleus == Some(nucleus))
    val newCell = move(mover.head)  // Works using STATIC move
    val newCell = mover.head.move  // Doesn't Work (needs .up, .down etc...)
    if(mover.nonEmpty){
      if(isValidCellState(newCell)) {
        Team(newCell :: others)
      }else{
        throw new BadMoveException("Invalid move from this position")
      }
    }else{
      throw new BadMoveException("You didn't select a cell to move")
    }
  }
If I want both features:
It seems that I would need to define the methods statically in the companion object, but then define them in the class by referencing the static implementation
def up = Cell.up(this)
Is this bad practice, it seems a bit stinky.
Scala makes it really easy to create lambdas for cases like this:
move(_.up, team, nucleus)
You'll notice that this is even shorter than Cell.up. For this reason, it seems unnecessary to also define them in the companion. 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With