Perl'de herhangi bir işlev, çağrıldığı bağlamı belirleyebilir: skalar, liste veya void. wantarray operatörü bağlamı belirlemek için kullanılır.
Örnek:
sub foo { if (wantarray) { return (1, 2, 3); # Liste bağlamı } else { return 42; # Skalar bağlamı } } my @a = foo(); # (1, 2, 3) my $b = foo(); # 42 foo(); # Void bağlamı
Özellik: wantarray doğru kullanılmazsa, beklenmedik değerler dönebilir.
Bağlama bağlı olarak bir dizi ve bir skalar dönen bir işlev, void bağlamında çağrıldığında ne döner?
Cevap: Void bağlamında dönen değer yok sayılır, ancak wantarray üzerinden yapılan ayrıştırma kodu çalışmaya devam eder. Bu nedenle, işlev yan etkiler yaratıyorsa ayrı bir işlem sağlamak gereklidir. Örneğin:
sub noisy { if (wantarray) { print "Liste bağlamında çağrıldı"; return (1,2,3); } elsif (defined wantarray) { print "Skalar bağlamında çağrıldı"; return 42; } else { print "Void!"; return; } }
Hikaye 1
Bir projede bir mühendis bağlam farklarını unuttu. Dosya isimlerini döndüren bir işlev bazen sadece dosya sayısını (skalar bağlam) döndürüyordu; bu diğer sonuçlarla birleştirildiğinde veri kaybına yol açıyordu.
Hikaye 2
Başlıkları ayrıştırmak için API geliştirirken, işlevler yalnızca sol tarafta açıkça bir dizi olduğunda liste döndürdü (
my @headers = parse_headers()), ancakif (parse_headers())şeklinde çağrıldığında yalnızca ilk başlık dönüyordu. Hata hemen bulunamadı, çünkü işleme mantıklı görünüyordu — ancak davranış projenin farklı kısımlarında farklılık gösteriyordu.
Hikaye 3
Bir dosyada eşleşmeleri arayan işlev, bağlama bağlı olarak farklı sayıda sonuç döndürüyordu. Sonuç olarak,
mapveyagrepiçine gönderildiğinde beklenmeyen hatalar yaşanıyordu:mapbir liste bekliyordu amaundefalıyordu — skaler bağlamda ise yalnızca bulunan eşleşmelerin sayısı hesaplanıyordu. Sorun, birkaç sürümden sonra ortaya çıktı.