Saya telah melihat daftar survei yang diambil di scala-lang.org dan melihat pertanyaan yang aneh: " Bisakah Anda menyebutkan semua penggunaan" _ "? ". Bisakah kamu? Jika ya, silakan lakukan di sini. Contoh-contoh penjelasan dihargai.
Saya telah melihat daftar survei yang diambil di scala-lang.org dan melihat pertanyaan yang aneh: " Bisakah Anda menyebutkan semua penggunaan" _ "? ". Bisakah kamu? Jika ya, silakan lakukan di sini. Contoh-contoh penjelasan dihargai.
Jawaban:
Yang bisa saya pikirkan adalah
def foo(l: List[Option[_]]) = ...
case class A[K[_],T](a: K[T])
val _ = 5
List(1, 2, 3) foreach { _ => println("Hi") }
trait MySeq { _: Seq[_] => }
Some(5) match { case Some(_) => println("Yes") }
"abc" match { case s"a$_c" => }
C(1, 2, 3) match { case C(vs @ _*) => vs.foreach(f(_)) }
import java.util._
import java.util.{ArrayList => _, _}
def bang_!(x: Int) = 5
def foo_=(x: Int) { ... }
List(1, 2, 3) map (_ + 2)
List(1, 2, 3) foreach println _
def toFunction(callByName: => Int): () => Int = callByName _
var x: String = _ // unloved syntax may be eliminated
Mungkin ada orang lain yang saya lupa!
Contoh menunjukkan mengapa foo(_)
dan foo _
berbeda:
Contoh ini berasal dari 0__ :
trait PlaceholderExample {
def process[A](f: A => Unit)
val set: Set[_ => Unit]
set.foreach(process _) // Error
set.foreach(process(_)) // No Error
}
Dalam kasus pertama, process _
merupakan metode; Scala mengambil metode polimorfik dan berupaya membuatnya monomorfik dengan mengisi parameter tipe, tetapi menyadari bahwa tidak ada tipe yang dapat diisi untuk A
yang akan memberikan tipe (_ => Unit) => ?
(Eksistensial _
bukan tipe).
Dalam kasus kedua, process(_)
adalah lambda; saat menulis lambda tanpa tipe argumen eksplisit, Scala menyimpulkan tipe dari argumen yang foreach
diharapkan, dan _ => Unit
merupakan tipe (padahal _
sebenarnya tidak), sehingga dapat diganti dan disimpulkan.
Ini mungkin merupakan gotcha paling sulit di Scala yang pernah saya temui.
Perhatikan bahwa contoh ini dikompilasi dalam 2.13. Abaikan saja seolah-olah ditugaskan ke garis bawah.
val x: Any = _
println _
dan println(_)
berbeda. Anda dapat melihat ini sebagai contoh karena mereka menangani tipe eksistensial dan polimorfik sedikit berbeda. Akan muncul dengan sedikit contoh.
Dari (entri saya) di FAQ , yang tentu saja saya tidak menjamin akan lengkap (saya menambahkan dua entri hanya dua hari yang lalu):
import scala._ // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]] // Higher kinded type parameter
def f(m: M[_]) // Existential type
_ + _ // Anonymous function placeholder parameter
m _ // Eta expansion of method into method value
m(_) // Partial function application
_ => 5 // Discarded parameter
case _ => // Wild card pattern -- matches anything
val (a, _) = (1, 2) // same thing
for (_ <- 1 to 10) // same thing
f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence
var i: Int = _ // Initialization to the default value
def abc_<>! // An underscore must separate alphanumerics from symbols on identifiers
t._2 // Part of a method name, such as tuple getters
1_000_000 // Numeric literal separator (Scala 2.13+)
Ini juga bagian dari pertanyaan ini .
var i: Int = _
atau kasus khusus pencocokan pola val (a, _) = (1, 2)
atau kasus khusus dari val dibuangfor (_ <- 1 to 10) doIt()
def f: T; def f_=(t: T)
kombo untuk membuat f member yang bisa berubah.
_
pada nama metode curang. Tapi baiklah. Saya hanya berharap orang lain memperbarui FAQ ... :-)
Penjelasan yang bagus tentang penggunaan garis bawah adalah sihir Scala _ [garis bawah] .
Contoh:
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "anything other than one and two"
}
expr match {
case List(1,_,_) => " a list with three element and the first element is 1"
case List(_*) => " a list with zero or more elements "
case Map[_,_] => " matches a map with any key type and any value type "
case _ =>
}
List(1,2,3,4,5).foreach(print(_))
// Doing the same without underscore:
List(1,2,3,4,5).foreach( a => print(a))
Di Scala, _
tindakan serupa dengan *
di Jawa saat mengimpor paket.
// Imports all the classes in the package matching
import scala.util.matching._
// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._
// Imports all the members of the object Fun but renames Foo to Bar
import com.test.Fun.{ Foo => Bar , _ }
// Imports all the members except Foo. To exclude a member rename it to _
import com.test.Fun.{ Foo => _ , _ }
Dalam Scala, pengambil dan penyetel akan secara implisit didefinisikan untuk semua vars non-pribadi dalam suatu objek. Nama pengambil sama dengan nama variabel dan _=
ditambahkan untuk nama penyetel.
class Test {
private var a = 0
def age = a
def age_=(n:Int) = {
require(n>0)
a = n
}
}
Pemakaian:
val t = new Test
t.age = 5
println(t.age)
Jika Anda mencoba untuk menetapkan fungsi ke variabel baru, fungsi akan dipanggil dan hasilnya akan ditugaskan ke variabel. Kebingungan ini terjadi karena kawat gigi opsional untuk pemanggilan metode. Kita harus menggunakan _ setelah nama fungsi untuk menetapkannya ke variabel lain.
class Test {
def fun = {
// Some code
}
val funLike = fun _
}
List(1,2,3,4,5).foreach(print(_))
itu jauh lebih mudah untuk dilakukan List(1,2,3,4,5).foreach(print)
, Anda bahkan tidak benar-benar membutuhkan garis bawah sama sekali, tapi saya rasa itu hanya masalah gaya
Ada satu penggunaan yang bisa saya lihat semua orang di sini sepertinya lupa daftar ...
Daripada melakukan ini:
List("foo", "bar", "baz").map(n => n.toUpperCase())
Anda bisa melakukannya:
List("foo", "bar", "baz").map(_.toUpperCase())
n => n
Berikut adalah beberapa contoh di mana _
digunakan:
val nums = List(1,2,3,4,5,6,7,8,9,10)
nums filter (_ % 2 == 0)
nums reduce (_ + _)
nums.exists(_ > 5)
nums.takeWhile(_ < 8)
Dalam semua contoh di atas satu garis bawah mewakili elemen dalam daftar (untuk mengurangi garis bawah pertama mewakili akumulator)
Selain penggunaan yang disebutkan JAiro, saya suka yang ini:
def getConnectionProps = {
( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo )
}
Jika seseorang membutuhkan semua properti koneksi, ia dapat melakukan:
val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps
Jika Anda hanya membutuhkan host dan port, Anda dapat melakukan:
val ( host, port, _, _ ) = getConnectionProps
Ada contoh spesifik yang digunakan "_":
type StringMatcher = String => (String => Boolean)
def starts: StringMatcher = (prefix:String) => _ startsWith prefix
mungkin sama dengan:
def starts: StringMatcher = (prefix:String) => (s)=>s startsWith prefix
Menerapkan “_” dalam beberapa skenario akan secara otomatis dikonversi menjadi “(x $ n) => x $ n”