undisp
undisp

Reputation: 721

Scala: if inside match case

Is there any way to put a if inside a match case in scala?

Something like this:

def createSchedules(listTask: List[TaskOrder], physicalResources: List[Physical], humanResources: List[Human], previousTime: Duration): List[TaskSchedule] = listTask match {
    case TaskOrder(id, time, physicalRes, order) :: t =>
      val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources)
      if (physicalRes != null) 
        new TaskSchedule(
          order, 
          order.getProduct(), 
          Task(id, time, physicalRes), 
          physicalRes, 
          taskScheduleHumanResources, 
          order.quantity, 
          previousTime, 
          previousTime + time) :: createSchedules(t, physicalRes, humanResources, previousTime + time)
    case Nil => Nil
  }

Doing that I get an error saying:

type mismatch; found : Unit required: List[Objects.TaskSchedule]

What would be the best way to do it?

Upvotes: 2

Views: 1251

Answers (3)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

The reason the compiler is infering Unit is that you don't have an else clause, which means you don't return a value in case physicalRes is null.

You need to add an else clause to your code:

case TaskOrder(id, time, physicalRes, order) :: t => 
  val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources)
  if (physicalRes != null) // stuff
  else createSchedules(t, physicalRes, humanResources, previousTime + time)

You can use collect to only select the desire elements:

val res: List[TaskSchedule] = listTask.collect {
   case order if order.physicalRes != null => new TaskSchedule(...)
}

Or you can also fold over the collection and only accumulate when you find non-empty physicalRes:

val res: List[TaskSchedule] = listTask.foldLeft(List.empty[TaskOrder]) {
  case (acc, order) => 
    if (order.physicalRes != null) {
       new TaskSchedule(...) :: acc
    } else acc
}

Upvotes: 5

Jack Leow
Jack Leow

Reputation: 22477

As others have pointed out, the compiler tries to infer type of the if expression (it would try and find the first common super-type shared by the if and else). Given the lack of an else, it goes with Unit, hence the error you were receiving.

If I understand what you are trying to do, collecting seems the easiest way to accomplish that:

def createSchedules(listTask: List[TaskOrder], physicalResources: List[Physical], humanResources: List[Human], previousTime: Duration): List[TaskSchedule] =
  listTask.collect {
    case TaskOrder(id, time, physicalRes, order) if physicalRes != null =>
      val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources)
      new TaskSchedule(
        order, 
        order.getProduct(), 
        Task(id, time, physicalRes), 
        physicalRes, 
        taskScheduleHumanResources, 
        order.quantity, 
        previousTime, 
        previousTime + time
      )
  }

Upvotes: 0

Ramesh Maharjan
Ramesh Maharjan

Reputation: 41957

If you do

    def createSchedules(listTask: List[TaskOrder],
                        physicalResources: List[Physical],
                        humanResources: List[Human],
                        previousTime: Duration): List[TaskSchedule] = listTask match {
      case TaskOrder(id, time, physicalRes, order) :: t =>{
        val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources);
        if(physicalRes != null) 
          new TaskSchedule(order, order.getProduct(), Task(id, time, physicalRes), physicalRes, taskScheduleHumanResources, order.quantity, previousTime, previousTime + time):: createSchedules(t, physicalRes, humanResources, previousTime + time)
        else 
          Nil
      }
      case Nil => Nil
    }
  }

It should work

Upvotes: 1

Related Questions