Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are static methods more composable?

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:

  1. Ability to call functions like instance methods
  2. Use the functions as parameters for other functions

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.

like image 485
COOLBEANS Avatar asked Feb 05 '19 23:02

COOLBEANS


1 Answers

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.

like image 50
Brian McCutchon Avatar answered Sep 19 '22 01:09

Brian McCutchon