[JAVA] Ich habe Scala ~ [Steuerungssyntax] ~ berührt

Introduction

image.png

Es ist eine direkte Migration des Dwango-Tutorials, in dem Sie es studieren, bearbeiten und durch Ihre eigenen Begriffe ersetzen.

Da es in diesem Text darum geht, die Grundlagen von Scala zu erlernen, wird es in Scala von nun an häufig Erklärungen zu einigen Syntaxen geben. Hier finden Sie eine kurze Beschreibung der Notation zur Darstellung der Syntax. In diesem Abschnitt erfahren Sie mehr über die Steuerungssyntax von Scala. Keine Sorge, es ist nicht so ausgefallen im Vergleich zu normalen Programmiersprachen.

Über die Notation

Da es in diesem Text darum geht, die Grundlagen von Scala zu erlernen, wird es in Scala von nun an häufig Erklärungen zu einigen Syntaxen geben. Hier finden Sie eine kurze Beschreibung der Notation zur Darstellung der Syntax.

Anordnung von Alphabeten usw.

Erstens, wie unten gezeigt, repräsentiert eine Folge von Alphabeten und Symbolen, wie sie ist, die Zeichenfolge selbst. Hier repräsentiert es die Zeichenfolge, wenn selbst.

if

Eine Folge von Alphabeten usw. in Anführungszeichen

Behandeln Sie als Nächstes die in Anführungszeichen eingeschlossene Reihenfolge von Alphabeten und Symbolen auf die gleiche Weise. Dies wird verwendet, um Verwechslungen mit einigen Zeichen zu vermeiden, da diese eine besondere Bedeutung haben, wie unten beschrieben. Das Folgende hat die gleiche Bedeutung wie zuvor.

'if'

Elemente in (und)

Ein in () eingeschlossenes Element repräsentiert eine Gruppierung. Das Folgende ist keine Zeichenfolge, die mit (beginnt, sondern eine Gruppe von Zeichen mit dem Namen if (). Dies wird verwendet, um die später beschriebenen wiederholten Ausdrücke zu gruppieren.

('if' '(' ')')

Die Gruppierung hat Vorrang, sofern nicht ausdrücklich als "(" oder ")" angegeben.

In eingeschlossene Elemente

In eingeschlossene Namen, wie z. B. , repräsentieren ein Syntaxelement. Das Schreiben von zeigt an, dass es sich um ein syntaktisches Element handelt, das das Konzept des Ausdrucks ausdrückt. Das Folgende stellt einen Teil der Syntax der Java-if-Anweisung dar. Ich habe nicht erwähnt, was der ist, aber ich gehe von einem Ausdruck aus, der in der Java-Sprache boolesch zurückgibt.

if '(' <Bedingter Ausdruck> ')'

Ein Element gefolgt von *

Jedes Element, gefolgt von *, wird hinzugefügt, um zu bedeuten, dass das Element null oder mehrmals vorkommt. Das Folgende bedeutet, dass ein Element wie; nach 0 oder mehrmals vorkommt.

(<Formel> ;)*

Hier ist es nicht eindeutig, ob a * das Zeichen * nach a ist oder ob a 0 oder mehrmals wiederholt wird. Um die Mehrdeutigkeit zu beheben, ist die Iteration maßgebend, sofern sie nicht ausdrücklich mit einem '*' gekennzeichnet ist.

Ein Element gefolgt von einem +

Jedes Element gefolgt von einem + bedeutet, dass das Element mehr als einmal angezeigt wird. Das Folgende bedeutet, dass ein Element wie; nach mehrmals vorkommt.

(<Formel> ;)+

Hier ist es nicht eindeutig, ob auf a + der Buchstabe + folgt oder a ein- oder mehrmals wiederholt wird. Um die Mehrdeutigkeit zu beheben, hat die Iteration Vorrang, sofern nicht ausdrücklich als "+" angegeben.

Ein Element gefolgt von?

Jedes Element gefolgt von einem? Bedeutet, dass das Element 0 oder 1 Mal erscheint. Mit anderen Worten, dieses Element ist optional. Das Folgende ist

Dies bedeutet, dass ein Element, das mit else beginnt und auf folgt, 0 oder 1 Mal angezeigt wird.

(else <Formel>)?

Hier ist es nicht eindeutig, ob a? Auf das Zeichen folgt? Oder ob es sich um ein 0- oder 1-Vorkommen von a handelt. Um die Unklarheit zu beseitigen, hat die Option Vorrang, sofern nicht ausdrücklich als "?" Angegeben.

| Zwischen zwei Elementen angehängt

Zwei beliebige Elemente A und B mit einem hinzugefügten | bedeuten, dass entweder A oder B akzeptabel sind. Das Folgende bedeutet, dass entweder val oder var verwendet werden kann.

('val'|'var')

Wo ein|b ist a|Es ist nicht eindeutig, ob es sich um die drei Buchstaben b oder a oder b handelt. Explizite Mehrdeutigkeit auflösen'|'Es sei denn, die Interpretation a oder b hat Vorrang.

Ein Element gefolgt von ...

Es wird verwendet, um die ersten paar Elemente zu veranschaulichen, wenn eine beliebige Anzahl von Elementen kommt, und um klar anzuzeigen, dass der Rest im gleichen Muster erscheint. Das Folgende stellt ein Muster dar, das in [und] eingeschlossen ist und eine beliebige Anzahl von Ausdrücken enthält.

'[' <Gleichung 1>, <Gleichung 2>, ... ']'

wenn Ausdruckssyntax

Basierend auf dem oben Gesagten lautet die Syntax des if-Ausdrucks von Scala wie folgt.

if '(' <Bedingter Ausdruck> ')' <Formel> ( else <Formel> )?

Wir werden später mehr über Scalas if-Ausdrücke sprechen.

Steuerungssyntax

In diesem Abschnitt erfahren Sie mehr über die Steuerungssyntax von Scala. Keine Sorge, es ist nicht so ausgefallen im Vergleich zu normalen Programmiersprachen.

Über die Begriffe "Syntax", "Ausdruck" und "Anweisung" In diesem Abschnitt werden die Begriffe "Syntax", "Ausdruck" und "Satz" gemischt verwendet und sind möglicherweise etwas schwer zu verstehen. Daher möchte ich diese drei Begriffe zunächst erläutern.

Erstens ist "Syntax" eine Regel für ein Programm, um eine Struktur innerhalb seiner Programmiersprache zu haben. Oft enthält es Schlüsselwörter, die in der Programmiersprache speziell behandelt werden, wie z. B. class, val, if, und es gibt Regeln für die Erstellung des richtigen Programms. Im Fall einer Klasse folgt auf die Klasse der Klassenname, der Inhalt der Klasse ist in {und} eingeschlossen und so weiter. Da in diesem Abschnitt die Steuerungssyntax von Scala erläutert wird, werden die Regeln zum Erstellen von Programmen erläutert, die den Verarbeitungsfluss steuern.

Als nächstes ist der "Ausdruck" der Teil, aus dem das Programm besteht, und wird zu einem Wert, wenn die Auswertung erfolgreich ist. Zum Beispiel 1 oder 1 + 2, "hoge". Durch Auswertung werden sie zu numerischen Werten oder Zeichenfolgenwerten. Ich habe den Ausdruck verwendet, dass die Bewertung erfolgreich war, aber wenn eine Ausnahme als Ergebnis der Bewertung ausgelöst wird, entspricht dies dem Fall, in dem die Bewertung fehlschlägt.

Schließlich gibt es die "Anweisung", die im Gegensatz zum Ausdruck der Teil ist, aus dem das Programm besteht und der bei der Bewertung nicht bewertet wird. Wenn beispielsweise die Definition einer Variablen, Wert i = 1, ausgewertet wird, wird die Variable i definiert und der Wert von i wird 1, aber diese Definition als Ganzes hat keinen Wert. Das ist also ein Satz.

Scala enthält mehr Ausdrücke als Anweisungen in prozeduralen Sprachen wie C und Java. Scala verwendet eine Syntax, die mehr Ausdrücke als Anweisungen verwendet. Dies macht es einfacher, leicht verständlichen Code zu schreiben, der Zustände wie Variablen so weit wie möglich eliminiert.

Bitte achten Sie auf die Verwendung solcher Wörter und lesen Sie die nachstehende Erklärung.

Blocktyp

Wenn Sie in Scala eine Folge mehrerer Ausdrücke mit {} einschließen, wird der gesamte Ausdruck zu einem Ausdruck. Der Einfachheit halber wird er jedoch als Blockausdruck bezeichnet.

Die allgemeine Form des Blocktyps ist

{ <Gleichung 1>(;|<Neue Zeile>) <Gleichung 2>(;|<Neue Zeile>) ... }

Es wird sein. Die Reihenfolge der Ausdrücke stellt die einzelnen Ausdrücke dar, die der Reihe nach ausgewertet werden. Semikolons können weggelassen werden, wenn die Ausdrücke durch Zeilenumbrüche getrennt sind. Der Ausdruck {} wertet Ausdruck 1, Ausdruck 2 ... und die Reihenfolge der Ausdrücke der Reihe nach aus und gibt den Wert zurück, der den letzten Ausdruck ausgewertet hat.

In der folgenden Formel


scala> { println("A"); println("B"); 1 + 2; }
A
B
res0: Int = 3

A und B werden ausgegeben, und Sie können sehen, dass 3, das Ergebnis des letzten Ausdrucks 1 + 2, der Wert des Ausdrucks {} ist.

Dies wird in der später beschriebenen Methodendefinition wichtig. In der Scala


def foo(): String = {
  "foo" + "foo"
}

Es ist üblich, eine Methode in Form von (später beschrieben) zu definieren, aber hier ist {} nur ein {} Ausdruck, und {} ist nicht in der Syntax der Methodendefinition enthalten. {} In der Klassendefinitionssyntax usw. ist jedoch Teil der Anweisung.

wenn Ausdruck

Der if-Ausdruck wird ähnlich wie die Java-if-Anweisung verwendet. Die Syntax des if-Ausdrucks lautet wie folgt:

if '('<Bedingter Ausdruck>')' <dann Ausdruck> (else <sonst Ausdruck>)?

Der bedingte Ausdruck muss vom Typ Boolean sein. else kann weggelassen werden. Der then-Ausdruck ist der Ausdruck, der ausgewertet wird, wenn der bedingte Ausdruck wahr ist, und der else-Ausdruck ist der Ausdruck, der ausgewertet wird, wenn der bedingte Ausdruck falsch ist.

Verwenden wir sofort die if-Formel.

scala> var age = 17
age: Int = 17


scala> if(age < 18) {
     |   "Unter 18 Jahre alt"
     | } else {
     |   "18 Jahre und älter"
     | }
res1: String =Unter 18 Jahre alt

Außerdem ist es wie folgt, wenn es durch einen anderen Satz bewertet wird. Diese Operation ist möglich, da age eine variable Zeichenfolge ist.


scala> age = 18
age: Int = 18

scala> if(age < 18) {
     |   "Unter 18 Jahre alt"
     | } else {
     |   "18 Jahre und älter"
     | }
res2: String =18 Jahre und älter

Ich versuche, eine andere Zeichenfolge zurückzugeben, je nachdem, ob das Alter der veränderlichen Variablen weniger als 18 Jahre beträgt.

Die gesamte Scala-Steuerungssyntax besteht aus Ausdrücken, nicht nur aus Ausdrücken. Das heißt, es wird immer ein Wert zurückgegeben. Möglicherweise haben Sie den ternären Operator gesehen ?: In Sprachen wie Java, aber Scala verwendet den if-Ausdruck, wenn Sie ebenfalls einen Wert benötigen.

Obwohl ich geschrieben habe, dass sonst weggelassen werden kann, wird in diesem Fall derselbe Wert wie der Einheitentyp value () wie unten gezeigt zurückgegeben.

if '(' <Bedingter Ausdruck> ')' <dann Ausdruck> else ()

Der Unit-Typ entspricht void in Java und wird verwendet, wenn kein Wert zurückgegeben werden muss und nur ein Wert () vorhanden ist.

während Ausdruck

Die Syntax des while-Ausdrucks ähnelt der von Java.

while '(' <Bedingter Ausdruck> ')'Körpertyp

Der bedingte Ausdruck muss vom Typ Boolean sein. Der while-Ausdruck wertet weiterhin den Körperausdruck aus, während der bedingte Ausdruck wahr ist. Da der while-Ausdruck auch ein Ausdruck ist, gibt er einen Wert zurück. Da jedoch im while-Ausdruck kein geeigneter Wert zurückgegeben werden kann, wird ein Unit-Typ value () zurückgegeben.

Lassen Sie uns nun mit dem while-Ausdruck einen Wert von 1 bis 10 ausgeben.

scala> var i = 1
i: Int = 1

scala> while(i <= 10) {
     |   println("i = " + i)
     |   i = i + 1
     | }
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10

Ähnlich wie bei der while-Anweisung in Java. Es gibt auch einen do while-Ausdruck, aber da er Java ähnelt, wird die Erklärung weggelassen. Es gibt keine Sprachfunktion, die den Java-Anweisungen break und continue entspricht. Bei ordnungsgemäßer Verwendung der nachfolgend beschriebenen Funktionen höherer Ordnung ist ein Unterbrechen und Fortfahren in den meisten Fällen jedoch nicht erforderlich.

zum Ausdruck bringen

Scala hat eine Steuerungssyntax, die für Ausdrücke aufgerufen wird. Dies ist eine Steuerungssyntax, die auf ähnliche Weise wie die Java-Erweiterung für Anweisung verwendet werden kann, jedoch verschiedene andere Anwendungen als Schleifen hat. Um die wahre Kraft von for-Ausdrücken zu verstehen, müssen Sie die Methoden flatMap, map, withFilter, foreach kennen. Hier wird jedoch nur die grundlegende Verwendung von for-Ausdrücken erläutert.

Die grundlegende Syntax des for-Ausdrucks lautet wie folgt:


for '(' (<Generator>;)+ ')' '<Körper>' 
# <Generator> = x <- <Formel>

Sie können eine Schleifenvariable mit einem beliebigen Namen für den Teil verwenden, der der Variablen x jedes Generators entspricht. Sie können verschiedene Ausdrücke in den Ausdruck schreiben. Beachten Sie jedoch, dass Sie einen Ausdruck verwenden können, der einen Bereich von Zahlen darstellt, da wir im Moment nicht alles erklären können. Zum Beispiel liegt 1 bis 10 im Bereich von 1 bis 10 (einschließlich 10) und 1 bis 10 im Bereich von 1 bis 10 (ohne 10).

Verwenden wir nun den for-Ausdruck.


scala> for(x <- 1 to 5; y <- 1 until 5){
     |   println("x = " + x + " y = " + y)
     | }
x = 1 y = 1
x = 1 y = 2
x = 1 y = 3
x = 1 y = 4
x = 2 y = 1
x = 2 y = 2
x = 2 y = 3
x = 2 y = 4
x = 3 y = 1
x = 3 y = 2
x = 3 y = 3
x = 3 y = 4
x = 4 y = 1
x = 4 y = 2
x = 4 y = 3
x = 4 y = 4
x = 5 y = 1
x = 5 y = 2
x = 5 y = 3
x = 5 y = 4

Es durchläuft eine Schleife von x von 1 bis 5, eine Schleife von y von 1 bis 4 und gibt die Werte von x und y aus. Hier haben wir nur zwei Generatoren, aber wenn Sie die Anzahl erhöhen, können Sie mehrere Schleifen ausführen.

Dies ist nicht die einzige Kraft des Ausdrucks. Sie können auch nur diejenigen eingrenzen, die die Bedingungen aus den Schleifenvariablen erfüllen. Nach bis, wenn x! = Y geschrieben ist, wird dies jedoch nur extrahiert, wenn x und y unterschiedliche Werte haben.


scala> for(x <- 1 to 5; y <- 1 until 5 if x != y){
     |   println("x = " + x + " y = " + y)
     | }
x = 1 y = 2
x = 1 y = 3
x = 1 y = 4
x = 2 y = 1
x = 2 y = 3
x = 2 y = 4
x = 3 y = 1
x = 3 y = 2
x = 3 y = 4
x = 4 y = 1
x = 4 y = 2
x = 4 y = 3
x = 5 y = 1
x = 5 y = 2
x = 5 y = 3
x = 5 y = 4

Der for-Ausdruck kann auch verwendet werden, um etwas zu tun, indem die Elemente der Sammlung einzeln verfolgt werden. Schreiben wir einen Prozess, um alle auszugeben, indem wir einer Liste folgen, die aus 5 Elementen "A", "B", "C", "D", "E" besteht.


scala> for(e <- List("A", "B", "C", "D", "E")) println(e)
A
B
C
D
E

Darüber hinaus kann der for-Ausdruck verarbeitet werden, um eine neue Sammlung zu erstellen. Fügen wir allen Elementen in der obigen Liste die Zeichenfolge Pre hinzu.


scala> for(e <- List("A", "B", "C", "D", "E")) yield {
     |   "Pre" + e
     | }

res9: List[String] = List(PreA, PreB, PreC, PreD, PreE)

Der Punkt hier ist die Keyword-Ausbeute. Tatsächlich kann die for-Syntax für einen völlig anderen Zweck verwendet werden, indem die Elemente einer Sammlung mithilfe des Schlüsselworts yield verarbeitet und zurückgegeben werden. Insbesondere für Ausdrücke, die das Schlüsselwort yield verwenden, wird dies manchmal als Verständnis bezeichnet.

Ausdruck ausgleichen

Ein Übereinstimmungsausdruck ist eine Kontrollstruktur, die wie ein Java-Switch mehrere Zweige ausdrücken kann, aber mehr als nur einen Switch kann. Die grundlegende Syntax des Übereinstimmungsausdrucks lautet


<Symmetrisch> match {
  (case <Muster> (if <bewachen>)? '=>'
    (<Formel> (;|<Neue Zeile>))*
  )+
}

Dies liegt jedoch daran, dass die Inhalte, die in diesem "Muster" geschrieben werden können, sehr unterschiedlich sind. Verwenden wir es zunächst wie einen Java-Switch-Case. Zum Beispiel


scala> val taro = "Taro"
taro: String = Taro

scala> taro match {
     |   case "Taro" => "Male"
     |   case "Jiro" => "Male"
     |   case "Hanako" => "Female"
     | }
res10: String = Male

Sie können es so verwenden. Hier enthält Taro die Zeichenfolge "Taro", die dem Fall "Taro" entspricht, sodass "Male" zurückgegeben wird. Wie einige von Ihnen hier vielleicht bemerkt haben, gibt der Übereinstimmungsausdruck auch einen Wert zurück. Der Wert des Übereinstimmungsausdrucks ist die Auswertung des Ausdrucks auf der rechten Seite von => des übereinstimmenden Musters.

Das Muster kann verschiedene Werte wie numerische Werte sowie Zeichenketten verarbeiten.


scala> val one = 1
one: Int = 1

scala> one match {
     |   case 1 => "one"
     |   case 2 => "two"
     |   case _ => "other"
     | }
res11: String = one

Hier erscheint _ an der Stelle des Musters, was der Standardeinstellung von Switch-Case entspricht und ein Muster ist, das zu allem passt. Dieses Muster wird als Platzhaltermuster bezeichnet. Bei der Verwendung von Übereinstimmungsausdrücken verwenden wir häufig Platzhaltermuster, um Auslassungen zu vermeiden.

Stellen Sie ein Muster zusammen

Diejenigen, die Switch-Case-Anweisungen in Sprachen wie Java und C gelernt haben, finden es möglicherweise seltsam, dass Scalas Mustervergleich kein sogenanntes Fall-Through-Verhalten bewirkt.


"abc" match {
  case "abc" => println("first")   //Die Verarbeitung endet hier
  case "def" => println("second") //Dies wird nicht angezeigt
}

Das Fall-Through-Verhalten von C-Language-Switch-Case-Anweisungen war bekannt dafür, dass es eher Fehler als Vorteile verursachte. Es wird oft kritisiert, dass Java das Fallthrough-Verhalten der C-Sprache übernommen hat. Aus diesem Grund hat Scalas Mustervergleich kein Durchfallverhalten, aber es gibt ein |, falls Sie mehrere Muster kombinieren möchten.


"abc" match {
  case "abc" | "def" =>
    println("first")
    println("second")
}

Extrahieren von Werten durch Mustervergleich

Abgesehen von Switch-Case gibt es eine Möglichkeit, einige Elemente der Sammlung abzugleichen. Schauen wir uns das folgende Programm an.


scala> val lst = List("A", "B", "C")
lst: List[String] = List(A, B, C)

scala> lst match {
     |   case List("A", b, c) =>
     |     println("b = " + b)
     |     println("c = " + c)
     |   case _ =>
     |     println("nothing")
     | }
b = B
c = C

Wenn hier das erste Element von List "A" ist und mit dem Muster von drei Elementen übereinstimmt, werden das zweite und die nachfolgenden Elemente von List an die verbleibenden b und c gebunden, und der Ausdruck auf der rechten Seite von => wird ausgewertet. Werden. Übereinstimmungsausdrücke werden häufig verwendet, um Elemente in einer Sammlung abzugleichen.

Beim Mustervergleich können Sie einen Schutzausdruck verwenden, sodass der Ausdruck auf der rechten Seite nur ausgewertet wird, wenn er mit dem Muster und auch dem Schutzausdruck übereinstimmt (muss vom Booleschen Typ sein).


scala> val lst = List("A", "B", "C")
lst: List[String] = List(A, B, C)

scala> lst match {
     |   case List("A", b, c) if b != "B" =>
     |     println("b = " + b)
     |     println("c = " + c)
     |   case _ =>
     |     println("nothing")
     | }
nothing

Hier haben wir die Bedingung angegeben, dass das zweite Element von List in der Schutzbedingung der Musterübereinstimmung nicht "B" ist, sodass es nicht mit der ersten Bedingung übereinstimmt und mit _ übereinstimmt.

Darüber hinaus können Mustervergleichsmuster verschachtelt werden. Lassen Sie uns das vorherige Programm ein wenig ändern, um es an eine Liste anzupassen, die mit List ("A") beginnt.


scala> val lst = List(List("A"), List("B", "C"))
lst: List[List[String]] = List(List(A), List(B, C))

scala> lst match {
     |   case List(a@List("A"), x) =>
     |   println(a)
     |   println(x)
     |   case _ => println("nothing")
     | }
List(A)
List(B, C)

lst ist List("A")Und Liste("B", "C")Es ist eine Liste, die aus zwei Elementen besteht. Hier ist unter Verwendung des Übereinstimmungsausdrucks der Anfang Liste("A")Sie können sehen, dass wir das verschachtelte Muster von beschreiben können. Auch vor dem Muster@Der mit heißt als Muster,@Ein Ausdruck, der dem folgenden Muster entspricht@Binden Sie vorher an die Variable (in diesem Fall a). Das as-Muster ist nützlich, wenn Sie nur einen Teil des Musters ausschneiden möchten, wenn das Muster kompliziert ist. jedoch|Beachten Sie, dass der Wert für den Mustervergleich mit nicht abgerufen werden kann. Wie unten beschrieben|Wenn Sie eine Variable in der Musterübereinstimmung von verwenden, tritt ein Kompilierungsfehler auf.


scala> (List("a"): Any) match {
     |   case List(a) | Some(a) =>
     |     println(a)
     | }
<console>:14: error: illegal variable in pattern alternative
         case List(a) | Some(a) =>
                   ^
<console>:14: error: illegal variable in pattern alternative
         case List(a) | Some(a) =>
                             ^

Ein Mustervergleich, bei dem der Wert nicht abgerufen wird, ist möglich.


(List("a"): Any) match {
  case List(_) | Some(_) =>
    println("ok")
}

Extrahieren von Werten mithilfe eines Einschubmusters

Sie können eine Musterübereinstimmung wie im vorherigen Abschnitt in einer anderen Notation schreiben. Zum Beispiel


scala> val lst = List("A", "B", "C")
lst: List[String] = List(A, B, C)

scala> lst match {
     |   case List("A", b, c) =>
     |     println("b = " + b)
     |     println("c = " + c)
     |   case _ =>
     |     println("nothing")
     | }
b = B
c = C

Der Code kann wie folgt umgeschrieben werden.


scala> val lst = List("A", "B", "C")
lst: List[String] = List(A, B, C)

scala> lst match {
     |   case "A" :: b :: c :: _ =>
     |     println("b = " + b)
     |     println("c = " + c)
     |   case _ =>
     |     println("nothing")
     | }
b = B
c = C

Hier wird ein Mustername (: :), der zwischen den Elementen der Liste angezeigt wird, z. B. "A" :: b :: c :: _, als Einschubmuster bezeichnet. Wenn der Musterabgleich durch das eingefügte Muster (: :) durchgeführt wird, zeigt das Element vor :: auf das erste Element der Liste und das Element nach :: auf den Rest der Liste. Wenn Sie das Ende der Liste ignorieren möchten, müssen Sie _ am Ende des Musters einfügen, wie oben gezeigt. Beachten Sie, dass es eine solche Funktion gibt, da Listenplatzierungsmuster in der Scala-Programmierung häufig vorkommen.

Musterübereinstimmung nach Typ

Sie können auch ein Muster verwenden, das nur übereinstimmt, wenn der Wert zu einem bestimmten Typ gehört. Muster, die nur übereinstimmen, wenn der Wert zu einem bestimmten Typ gehört, werden in Form von name: match type verwendet. Sie können es beispielsweise folgendermaßen verwenden: Der AnyRef-Typ ist ein Typ, der dem Java-Objekttyp entspricht, und jeder Referenztypwert kann in der AnyRef-Typvariablen gespeichert werden.


scala> import java.util.Locale
import java.util.Locale

scala> val obj: AnyRef = "String Literal"
obj: AnyRef = String Literal

scala> obj match {
     |   case v:java.lang.Integer =>
     |     println("Integer!")
     |   case v:String =>
     |     println(v.toUpperCase(Locale.ENGLISH))
     | }
STRING LITERAL

Sie können sehen, dass es nicht mit java.lang.Integer übereinstimmt, sondern mit einem String. Dieses Muster wird manchmal für die Ausnahmebehandlung verwendet und entspricht der Definition. Werte, die einem Typ entsprechen, können so behandelt werden, als wären sie in diesen Typ umgewandelt worden.

Beispielsweise kann v, das dem String-Typ im obigen Ausdruck entspricht, die String-Typ-Methode toUpperCase aufrufen. Es ist eine gute Idee zu bedenken, dass Scala häufig Pattern Matching anstelle von Casting verwendet.

Fallstricke beim Typmusterabgleich aufgrund von JVM-Einschränkungen

Es gibt eine Sache zu beachten, wenn Mustervergleichstypen. Aufgrund der Einschränkungen der JVM, in der Scala ausgeführt wird, wird der Mustervergleich bei Verwendung von Typvariablen nicht korrekt durchgeführt.

Wenn Sie beispielsweise versuchen, die folgende Musterübereinstimmung mit REPL durchzuführen, wird eine Warnung angezeigt.


scala> val obj: Any = List("a")
obj: Any = List(a)

scala> obj match {
     |   case v: List[Int]    => println("List[Int]")
     |   case v: List[String] => println("List[String]")
     | }
<console>:16: warning: non-variable type argument Int in type pattern List[Int](the underlying of List[Int]) is unchecked since it is eliminated by erasure
         case v: List[Int]    => println("List[Int]")
                 ^
<console>:17: warning: non-variable type argument String in type pattern List[String](the underlying of List[String]) is unchecked since it is eliminated by erasure
         case v: List[String] => println("List[String]")
                 ^
<console>:17: warning: unreachable code
         case v: List[String] => println("List[String]")
                                        ^
List[Int]

List [Int] und List [String] sind verschiedene Typen, aber der Mustervergleich kann sie nicht unterscheiden.

Die ersten beiden Warnungen haben die Bedeutung, dass die Aktion "Typ löschen" des Scala-Compilers den Int-Teil von List [Int] löscht und nicht überprüft wird.

Infolgedessen werden die beiden Muster nicht mehr unterscheidbar, und der Musterabgleich wird in der Reihenfolge von oben durchgeführt, sodass das zweite Muster nicht erreichbarer Code ist. Die dritte Warnung bedeutet dies.

Für den Mustervergleich von Typen, die Typvariablen enthalten, empfiehlt es sich, Platzhaltermuster wie unten gezeigt zu verwenden.


obj match {
  case v: List[_] => println("List[_]")
}


Ende

Nächstes Mal werde ich über Klassen lernen.

Referenz

Dieses Dokument ist CC BY-NC-SA 3.0

image.png Es wird unter verteilt.

https://dwango.github.io/scala_text/

Auch in Bezug auf die Ertragsformel usw. scheint es gut, den folgenden Artikel fortzusetzen.

https://qiita.com/harry0000/items/e37ca3bfb68df839bf55

Recommended Posts

Ich habe Scala ~ [Steuerungssyntax] ~ berührt
Ich habe Scala berührt
Ich habe Scala ~ [Klasse] ~ berührt
Ich habe Scala ~ [Objekt] ~ berührt
Ich habe Scala ~ [Trate] ~ berührt
Java-Steuerungssyntax
Java-Steuerungssyntax
Steuerungssyntaxoperator
Ich habe Scala ~ [Typparameter und Verschiebungsspezifikation] ~ berührt
Ich habe zuerst Java touched berührt
Ich habe zuerst Java touched berührt
[Java] Hinweis zur Steuerungssyntax
Ich habe zuerst Java touched berührt
Ich habe zuerst Java berührt
Ich ging zur Scala Fukuoka 2019!
[Java] Zusammenfassung der Steuerungssyntax