2016-11-28 6 views
0

In scala def wird eine Methode definiert und val, var werden zur Definition von Variablen verwendet.Definition von Variablen in Scala mit def

Betrachten Sie den folgenden Code ein:

scala> def i = 3 
i: Int 

scala> i.getClass() 
res0: Class[Int] = int 

scala> val v = 2 
v: Int = 2 

scala> v.getClass() 
res1: Class[Int] = int 

scala> println(v) 
2 

scala> println(i) 
3 

scala> i+v 
res4: Int = 5 

scala> def o =() => 2+3 
o:() => Int 

scala> o.getClass() 
res5: Class[_ <:() => Int] = class $$Lambda$1139/1753607449 

Warum Variablendefinition Arbeit def mit? Wenn es eine Funktion definiert, die Int zurückgibt, warum zeigt getClassInt anstelle eines Funktionsobjekts?

Antwort

2

Im Gegensatz zu val oder var Erklärung, def i = 3 ist nicht Variablendeklaration. Sie definieren eine Methode/Funktion, die eine Konstante 3 zurückgibt und i keine Parameter annimmt.

Deklaration mit val und var werden sofort ausgewertet, aber im Falle von Lazy Val und Def-Bewertung passiert, wenn explizit aufgerufen.

i ist eine Nicht-Argument-Funktion. Um Verwirrung loszuwerden Sie es mit leeren Klammern erklären könnte auch

def i() = 3 

Unterschied zwischen lazy val und def ist

  1. faul val träge ausgewertet und das Ergebnis zwischengespeichert wird. Das bedeutet, dass

  2. Def Deklaration jedes Mal ausgewertet wird, wenn Sie Methodenname aufrufen.

Beispiel Scala REPL mit

scala> lazy val a = { println("a evaluated"); 1} 
a: Int = <lazy> 

scala> def i = { println("i function evaluated"); 2} 
i: Int 

scala> a 
a evaluated 
res0: Int = 1 

scala> a 
res1: Int = 1 

scala> a 
res2: Int = 1 

scala> i 
i function evaluated 
res3: Int = 2 

scala> i 
i function evaluated 
res4: Int = 2 

scala> i 
i function evaluated 
res5: Int = 2 

Beachten Sie, dass a nur einmal ausgewertet wird und weitere Anrufungen von a Rückkehr der zwischengespeicherte Ergebnis also faul val wird einmal ausgewertet, wenn es aufgerufen wird und das Ergebnis gespeichert wird für immer. So sehen Sie println Ausgabe einmal

Hinweis Funktion wird jedes Mal ausgewertet, wenn es aufgerufen wird. In diesem Fall sehen Sie println Ausgang jedes Mal, wenn Sie die Funktion

Es gibt eine Konvention der Verwendung eines leeren Parameterliste, wenn die Methode hat Nebenwirkungen und verlassen sie

Allgemeine Übereinkommen berufen ab, wenn seine rein.

bearbeitet
scala> def i = 1 
i: Int 

scala> :type i 
Int 

scala> :type i _ 
() => Int 
+0

Danke für die detaillierte Erklärung. Aber wenn 'def 'eine Funktion deklariert oder eher ein Funktionsobjekt erzeugt, warum gibt' getClass' dann den Typ 'Int' zurück? Ich würde erwarten, eine Art von Funktionsobjekt zu sehen. Zum Beispiel: lambdas in Java8 implementieren eine der Schnittstellen im 'java.util.function. *' Paket. –

+0

@KshitizSharma Scala hat das Prinzip des einheitlichen Zugriffs, so dass Clients nicht wissen müssen, ob sie auf ein Feld zugreifen oder eine Methode ohne Nebenwirkungen aufrufen. –

+0

Richtig, wenn Sie über den resultierenden Wert besorgt sind. Aber bei der Analyse einer Funktion durch Reflexion sollte sie ihre Funktion nicht als Int bezeichnen. –

-1

Es gibt wenig anderes Konzept. Ruf nach Namen an, rufe nach Wert auf und rufe nach Bedarf auf. Alles Def ist im Wesentlichen Anrufe mit Namen. Was meinst du mit variabler Definition mit def ?? Sieht aus wie Duplikat zu mir: Call by name vs call by value in Scala, clarification needed Weitere Details in wiki: https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name

+0

Call-by-Name ist eine semantische Parameterauswertung. Das zu tun, was OP mit einem "def" tut, verhält sich in einigen Szenarien gleich, sollte aber nicht damit verwechselt werden. Außerdem ist es keine faule Bewertung. Das ist noch eine andere Sache. – rethab

+0

Oh .. ich sehe, ich habe "call by name" und "call-by need" gemischt. https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name. Dies ist jedoch eine doppelte Frage :) – Pavel

2

EDIT: Meine Antwort auf die Frage der Revision # 3 adressiert.

Es ist sehr nützlich, sich den Code in der Mitte des Kompilierungsprozesses anzusehen, in dem Sie sehen können, auf was Ihr Code tatsächlich übersetzt wurde. Das folgende einfache Programm:

object TestApp { 
    def definedVal = 3 
    val valVal = 3 
    lazy val lazyValVal = 3 

    def main(args: Array[String]) { 
     println(definedVal) 
     println(valVal) 
     println(lazyValVal) 
    } 
} 

an folgende (mit -Xprint:mixin Compiler-Option) übersetzt wird:

[[syntax trees at end of      mixin]] // test.scala 
package <empty> { 
    object TestApp extends Object { 
    @volatile private[this] var bitmap$0: Boolean = false; 
    private def lazyValVal$lzycompute(): Int = { 
     { 
     TestApp.this.synchronized({ 
      if (TestApp.this.bitmap$0.unary_!()) 
      { 
       TestApp.this.lazyValVal = 3; 
       TestApp.this.bitmap$0 = true; 
      () 
      }; 
      scala.runtime.BoxedUnit.UNIT 
     }); 
     () 
     }; 
     TestApp.this.lazyValVal 
    }; 

    def definedVal(): Int = 3; 

    private[this] val valVal: Int = _; 
    <stable> <accessor> def valVal(): Int = TestApp.this.valVal; 

    lazy private[this] var lazyValVal: Int = _; 
    <stable> <accessor> lazy def lazyValVal(): Int = if (TestApp.this.bitmap$0.unary_!()) 
     TestApp.this.lazyValVal$lzycompute() 
    else 
     TestApp.this.lazyValVal; 

    def main(args: Array[String]): Unit = { 
     scala.this.Predef.println(scala.Int.box(TestApp.this.definedVal())); 
     scala.this.Predef.println(scala.Int.box(TestApp.this.valVal())); 
     scala.this.Predef.println(scala.Int.box(TestApp.this.lazyValVal())) 
    }; 
    def <init>(): TestApp.type = { 
     TestApp.super.<init>(); 
     TestApp.this.valVal = 3; 
    () 
    } 
    } 
} 

Vom Ausgang oben ist es möglich, folgendes schließen:

  1. definedVal ist eigentlich eine Methode.
  2. valVal ist ein Feld, das im Konstruktor initialisiert wird und über einen automatisch generierten Accessor verfügt.
  3. Für das Lazy-Feld lazyValVal Compiler generiert compute Methode, die nur einmal aufgerufen wird, wenn das Feld das erste Mal zugegriffen wird.
Verwandte Themen