2015-05-27 2 views
0

У меня есть следующая программа, которая содержит рекурсивный fucntion с сопоставлением с образцом. Этот код работаетscala pattern matching dilemma

def randomSelect(num:Int, lst:List[Symbol]):List[Symbol] = (num, lst) match{ 

    /** traveerse list recursively extracting randomelemnents 

    * 

    */ 

    case (n, l) => { 

     if (n>0) { 
     println("At " + n + " we got:" + l) 
     val rnd = getRandom(l.length) 
     val item = l(rnd) 
     lst(rnd) :: randomSelect(n - 1, l.filter(it => it != item)) 
     } else List[Symbol]() 

    } 

} 

а в следующем не. И я не могу понять, почему

def randomSelect(num:Int, lst:List[Symbol]):List[Symbol] = (num, lst) match{ 

    /** traveerse list recursively extracting randomelements 

    * 

    */ 

    case (n, mylist) => { 
     val rnd = getRandom(mylist.length) 
     val item = mylist(rnd) 
     lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item)) 

    } 
    case (0, mylist) => List[Symbol]() 

}

во втором Conde сниппета, случай (0, MyList) никогда не вызывается.

что мне не хватает?

вид касается марко

+0

Первый случай всегда будет соответствовать, переместите второй случай перед ним. – Lee

ответ

1

прямо сейчас у вас есть что-то вроде:

if (the input is a Tuple2) { 
    do something 
} else if (the input is a Tuple2 with a 0 as the first item) { 
    do other thing 
} 

case (n, mylist) => матчей (0, List(...)) вам нужно добавить охранника первого выражения или изменить порядок дела, так что 0 случай достигается первый.

так как:

case (0, mylist) => List[Symbol]() 
case (n, mylist) => { 
    val rnd = getRandom(mylist.length) 
    val item = mylist(rnd) 
    lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item)) 
} 

или

case (n, mylist) if n > 0 => { 
    val rnd = getRandom(mylist.length) 
    val item = mylist(rnd) 
    lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item)) 
} 
case (0, mylist) => List[Symbol]() 
0

В следующем заявлении: case (n, mylist), n является переменной, которая связывается с любым значением в таком положении, что в вашем случае является num: Int. Таким образом, n привязан ко всем целочисленным значениям. Когда это бывает 0, ваш первый случай соответствует ему и, таким образом, никогда не сможет достичь второго оператора case.

Существует два способа решить эту проблему. Во-первых:

case (n, mylist) if n > 0 => { 
     val rnd = getRandom(mylist.length) 
     val item = mylist(rnd) 
     lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item)) 

    } 
case _ => List.empty[Symbol] 

Я использовал подстановочные, так как вы не использовать либо список или n.

Второй способ:

case (0, _) => List.empty[Symbol] 
case (n, mylist) => { 
     val rnd = getRandom(mylist.length) 
     val item = mylist(rnd) 
     lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item)) 

    } 
0

Как было упомянуто выше, реорганизовать случаи так, что наиболее специфичный оцениваются в первую очередь.

Однако сопоставление с образцом для двух случаев может быть сведен к if-else выражению (не того, чтобы реплицировать if-else через охранник), отметив, что в этом рекурсивном методе основание (тривиальный) случай может быть объявлен первым, главным образом, для повышения читаемости ,

def randomSelect(n:Int, l:List[Symbol]):List[Symbol] = { 
    if (n <= 0) List[Symbol]() 
    else { 
     println("At " + n + " we got:" + l) 
     val rnd = getRandom(l.length) 
     val item = l(rnd) 
     lst(rnd) :: randomSelect(n - 1, l.filter(it => it != item)) 
    } 
}