C'è qualcosa di simile a the slice notation in Python in Scala?Notazione Slice in Scala?
Penso che questa sia davvero un'operazione utile che dovrebbe essere incorporata in tutte le lingue.
C'è qualcosa di simile a the slice notation in Python in Scala?Notazione Slice in Scala?
Penso che questa sia davvero un'operazione utile che dovrebbe essere incorporata in tutte le lingue.
scala> import collection.IterableLike
import collection.IterableLike
scala> implicit def pythonicSlice[A, Repr](coll: IterableLike[A, Repr]) = new {
| def apply(subrange: (Int, Int)): Repr = coll.slice(subrange._1, subrange._2)
| }
pythonicSlice: [A,Repr](coll: scala.collection.IterableLike[A,Repr])java.lang.Object{def apply(subrange: (Int, Int)): Repr}
scala> val list = List(3, 4, 11, 78, 3, 9)
list: List[Int] = List(3, 4, 11, 78, 3, 9)
scala> list(2 -> 5)
res4: List[Int] = List(11, 78, 3)
Questo farà?
Disclaimer: Non correttamente generalizzato.
EDIT:
scala> case class PRange(start: Int, end: Int, step: Int = 1)
defined class PRange
scala> implicit def intWithTildyArrow(i: Int) = new {
| def ~>(j: Int) = PRange(i, j)
| }
intWithTildyArrow: (i: Int)java.lang.Object{def ~>(j: Int): PRange}
scala> implicit def prangeWithTildyArrow(p: PRange) = new {
| def ~>(step: Int) = p.copy(step = step)
| }
prangeWithTildyArrow: (p: PRange)java.lang.Object{def ~>(step: Int): PRange}
scala> implicit def pSlice[A](coll: List[A]) = new {
| def apply(prange: PRange) = {
| import prange._
| coll.slice(start, end).grouped(step).toList.map(_.head)
| }
| }
pSlice: [A](coll: List[A])java.lang.Object{def apply(prange: PRange): List[A]}
scala> val xs = List.range(1, 10)
xs: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> xs(3 ~> 9)
res32: List[Int] = List(4, 5, 6, 7, 8, 9)
scala> xs(3 ~> 9 ~> 2)
res33: List[Int] = List(4, 6, 8)
Vedi l'ScalaAPI here
Quindi nonla stessa convenienza di notazione, ma l'operazione è lì
fetta def (da: Int, fino a quando: Int) : Seq [A]
Seleziona un intervallo di elementi.
Seleziona un intervallo di elementi.
Nota: c.slice (da, a) è equivalente a (ma forse più efficiente rispetto) c.drop (da) .Take (a - da)
dall'indice del primo restituito elemento in questa sequenza. fino a l'indice uno dopo l'ultimo elemento restituito in questa sequenza.
rendimenti
una sequenza contenente gli elementi da indice da e si estendono fino a (esclusi) indice finché di questa sequenza.
classi di definizione: IterableLike → TraversableLike
metodo equivalente a Scala (con una sintassi leggermente diversa) esiste per tutti i tipi di sequenze:
scala> "Hello world" slice(0,4)
res0: String = Hell
scala> (1 to 10) slice(3,5)
res1: scala.collection.immutable.Range = Range(4, 5)
La più grande differenza rispetto ai affettare in Python è che gli indici di inizio e di fine sono obbligatori in Scala.
Si noti che questo funziona non proprio utilizzando apply
, ma generalizza alle liste, stringhe, array, ecc:
implicit def it2sl[Repr <% scala.collection.IterableLike[_, Repr]](cc: Repr) = new {
def ~>(i : Int, j : Int) : Repr = cc.slice(i,j)
}
L'utilizzo è:
scala> "Hello World" ~> (3, 5)
res1: java.lang.String = lo
scala> List(1, 2, 3, 4) ~> (0, 2)
res2: List[Int] = List(1, 2)
scala> Array('a', 'b', 'c', 'd') ~> (1, 3)
res3: Array[Char] = Array(b, c)
Si potrebbe voler rinominare il metodo con qualcos'altro che ti piace.Tranneapply
(perché c'è già una conversione da String
a StringLike
che decora String con un metodo apply
- analogamente, con ArrayOps
- e v'è già un metodo applicare su altri tipi di raccolta come List
).
Grazie per Daniel per il suggerimento di utilizzare una vista vincolata.
Bene, alcune persone preferiscono un linguaggio che rimanga piccolo, semplice e pulito. Non tutti i piccoli zuccheri sintattici valgono la pena. – soc
Non sono convinto che Scala sia piccolo e semplice. Rispetto a qualcosa come lua, comunque ... –
Confronto con Python Scala non sembra così piccolo e semplice, ha molti più costrutti di Python. –