2016-04-29 47 views
6

Anladığım kadarıyla, hem Haskell hem de lambda matematiğinin bir parçası olarak, her lambda ifadesinin kendi kapsamı vardır, yani \x -> (\x -> x) gibi iç içe geçmiş lambda ifadeleri varsa, ilk \x parametresi ikinci \x.Neden java lambda ifadeleri yeni bir kapsam düzeyi sunmuyor?

Java'da bunu yaparsanız, bir derleme hatası alırsınız, tıpkı x parametresini, lambda içinde çevreleyen kapsam içinde kullanılmışsa, parametre adı veya yerel değişken adı olarak tekrar kullanırsanız, örn. bir yöntem parametresi olarak. neden olmasın onları anonim sınıfın yaptığımız gibi kapsam yeni bir seviyeye tanıtmak ve davranırlar var - Java lambda ifadeler bu şekilde hayata neden

bilen var mı? Bunun bir sınırlama ya da optimizasyondan dolayı mı yoksa muhtemelen lambdas'ın mevcut dile hapsolması gerektiğinden mi varsayıyorum?

+0

Böyle dilde iç içe lambda içinde dış x atıfta nasıl? –

+1

@SotiriosDelimanolis Yapabilmek zorunda değilsiniz, bu bir tasarım kararıdır. Yapabilirsin. g. Ayrıca, tamamen geçerli olan başka bir x tanımladığınız anonim bir sınıftan x yerel değişkenine erişemezsiniz. – Vampire

+2

[Değişken zaten metot lambda'da tanımlanmıştır] 'ın olası kopyası (https://stackoverflow.com/questions/22773003/variable-is-already-defined-in-method-lambda) – ZhekaKozlov

cevap

10

Bu Java diğer kod blokları için aynı davranıştır. Bu arada bazı akıl ile,

{ 
    int a; 
} 
{ 
    int a; 
} 

Sen section 6.4 of the JLS bu konu hakkında okuyabilir değil iken

Bu derleme hatayı

int a; 
{ 
    int a; 
} 

verir.

3

Bir lambda bloğu kapsam aka yeni blok, ancak anonim bir sınıf uygulaması yaptığı gibi, yeni bir bağlam/seviyesini belirlemek etmez.

Java Dil Şartnamede 15.27.2 Lambda Body itibaren

: anonim sınıf bildirimleri görünen kodunun aksine

, isimlerin anlamı ve başvurulan beyanname erişilebilirlik ile birlikte bir lambda vücutta görülen this ve super anahtar kelimeler vardır , çevreleyen bağlamda ile aynıdır (lambda parametrelerinin yeni adlar getirmesi dışında).

Ve

JLS 6.4 Shadowing and Obscuring dan: Bu kurallar izin

iç içe sınıf bildirimleri (yerel sınıflar (§14.3) ve anonim sınıflar bir değişken veya yerel sınıfın ait yeniden bildirilmiş (§15.9)) değişken veya yerel sınıf kapsamında gerçekleşir. Böylece, bir resmi parametre, yerel değişken veya yerel sınıfın bildirimi, bir yöntem, yapıcı veya lambda ifadesi içine yerleştirilmiş bir sınıf bildiriminde gölgelenebilir; ve bir özel durum parametresinin bildirimi, yakalama maddesinin Bloğu içinde yer alan bir sınıf bildiriminde gölgelenebilir.

lambda parametreleri ve lambda ifadeleri bildirilen diğer değişkenler tarafından oluşturulan ad çatışmaları işlemek için iki tasarım alternatifi vardır. Birincisi, sınıf bildirimlerini taklit etmektir: yerel sınıflar gibi, lambda ifadeleri isimler için yeni bir "seviye" sunar ve ifadenin dışındaki tüm değişken isimleri tekrar bildirilebilir.Bir diğeri ise "yerel" stratejidir: yakalama cümleleri, döngüler ve bloklar gibi, lambda ifadeleri de kapsayıcı içerikle aynı "düzeyde" çalışır ve ifadenin dışındaki yerel değişkenler gölgelenemez. Yukarıdaki kurallar yerel stratejiyi kullanır; Bir lambda ifadesinde bildirilen bir değişkenin, bir kapatma yönteminde bildirilen bir değişkeni gölgelemesi için özel bir ayrışma yoktur.

Örnek:

class Test { 
    private int f; 
    public void test() { 
     int a; 
     a = this.f;  // VALID 
     { 
      int a;  // ERROR: Duplicate local variable a 
      a = this.f; // VALID 
     } 
     Runnable r1 = new Runnable() { 
      @Override 
      public void run() { 
       int a;   // VALID (new context) 
       a = this.f;  // ERROR: f cannot be resolved or is not a field 
           // (this refers to the instance of Runnable) 
       a = Test.this.f; // VALID 
      } 
     }; 
     Runnable r2 =() -> { 
      int a;  // ERROR: Lambda expression's local variable a cannot redeclare another local variable defined in an enclosing scope. 
      a = this.f; // VALID 
     }; 
    } 
} 
+0

neden bu kararı verdiler? Onların yapamayacakları bir sınırlama ya da bunu yapmamalarının bir yararı, yani her lambda için yeni bir kapsam seviyesine sahip olmamak? – Tranquility

İlgili konular