İsimle Çağrı: => Tür
=> Type
Notasyonu çağrısı-by-name biridir açılımı birçok yönden parametreleri geçirilebilir. Onlara aşina değilseniz, bu wikipedia makalesini okumak için biraz zaman ayırmanızı öneririm, günümüzde çoğunlukla değer çağrı ve referans çağrıdır.
Bunun anlamı, iletilen şeyin işlev içindeki değer adı ile değiştirilmesidir . Örneğin, bu işlevi kullanın:
def f(x: => Int) = x * x
Eğer böyle çağırırsam
var y = 0
f { y += 1; y }
Sonra kod bu şekilde yürütülecek
{ y += 1; y } * { y += 1; y }
Ancak bu, bir tanımlayıcı adı çakışması olduğunda ne olacağı noktasını arttırır. Geleneksel isimle çağrıda, isim çatışmalarından kaçınmak için yakalamadan kaçınma ikamesi adı verilen bir mekanizma gerçekleşir. Bununla birlikte, Scala'da bu, aynı sonuçla başka bir şekilde uygulanır - parametrenin içindeki tanımlayıcı adları, çağrılan işlevdeki gölge tanımlayıcılara başvuramaz veya gölge tanımlayıcılara başvuramaz.
Diğer ikisini açıkladıktan sonra konuşacağım isim ile ilgili başka noktalar da var.
0-arity İşlevleri: () => Tür
Sözdizimi () => Type
a türünü ifade eder Function0
. Yani, parametre almayan ve bir şey döndüren bir işlev. Bu, örneğin, yöntemi çağırmakla eşdeğerdir size()
- hiçbir parametre almaz ve bir sayı döndürür.
Bununla birlikte, bu sözdiziminin, bazı karışıklıkların nedeni olan anonim bir işlev değişmezinin sözdizimine çok benzemesi ilginçtir . Örneğin,
() => println("I'm an anonymous function")
olan Arity 0 anonim fonksiyonu hazır olduğu türü olan
() => Unit
Böylece şunu yazabiliriz:
val f: () => Unit = () => println("I'm an anonymous function")
Bununla birlikte, tipin değerle karıştırılmaması önemlidir.
Birim => Tür
Bu aslında Function1
ilk parametresi türünde olan sadece bir Unit
. Yazmanın diğer yolları (Unit) => Type
da olabilir Function1[Unit, Type]
. Mesele şu ki, bu kişinin istediği şey olması pek olası değildir. Türün Unit
ana amacı kişinin ilgilenmediği bir değeri göstermektir, bu nedenle bu değeri almak mantıklı değildir .
Örneğin,
def f(x: Unit) = ...
Biri muhtemelen ne yapabilirdi x
? Sadece tek bir değere sahip olabilir, bu yüzden onu almanıza gerek yoktur. Olası bir kullanım, geri dönen zincirleme işlevleri olacaktır Unit
:
val f = (x: Unit) => println("I'm f")
val g = (x: Unit) => println("I'm g")
val h = f andThen g
Çünkü andThen
sadece tanımlanır Function1
, ve zincirleme işlevler dönen Unit
biz türü olarak bunları tanımlamak zorunda Function1[Unit, Unit]
zincir bunları mümkün.
Karışıklık Kaynakları
İlk karışıklık kaynağı, 0-arity işlevleri için var olan tür ile değişmez adlar arasındaki benzerliğin, adıyla çağrı için de var olduğunu düşünmektir. Başka bir deyişle, düşünerek, çünkü
() => { println("Hi!") }
bir hazır içindir () => Unit
, sonra,
{ println("Hi!") }
bir değişmez olur => Unit
. O değil. Bu bir kod bloğu, gerçek bir bilgi değil.
Bir diğer karışıklık kaynağı olmasıdır Unit
türünün değeri yazılır ()
(ama değil) bir 0-Arity parametre listesi gibi hangi görünüyor.
case class Scheduled(time: Int)(callback: => Unit)
. Bu, ikincil parametre listesinin herkese açık olarak gösterilmemesi veya oluşturulanequals
/hashCode
yöntemlere dahil edilmemesi nedeniyle çalışır .