2009-08-31 11 views
12

'u boş değilse (aksi halde boolean anlamda true) @c alma niyetiyle @a = @b || @c atamasının bazı kıvrımlı varyasyonlarını gerçekleştirmek istiyorum. Belgeler açıkçası bana yapamayacağımı söylüyor. (Ve çok doğru aslında ilgili!)Neden b'yi atayamıyorum || Perl'de @ c to?

"||", "//" ve "& &" operatörleri ( değerlendirdi son değeri döndürmek C'ler "||" ve "& & aksine ", 0 veya 1 döndüren).

[...] Özellikle

, bu atama için ikisi arasında agrega seçimi için bu kullanmaması gerektiğini anlamı : Maalesef

@a = @b || @c;    # this is wrong 
@a = scalar(@b) || @c;  # really meant this 
@a = @b ? @b : @c;   # this works fine, though 

, gerçekten değil nedenini söyle.

  • @a = sağ taraftaki liste bağlamı uyaran, bir dizi atama: Ben ne olacağını tahmin Ne

    bu oldu. Liste bağlamında değerlendirilmek üzere, sağ taraftaki

  • @b || @c. C-stili kısa devre mantıksal veya
  • ||. Soldan sağa doğru değerlendirir (gerekirse) ve içeriği yayar. Liste bağlamında
  • @b değerlendirilir. Eğer doğru değilse (i.e., boş olmayan), geri döndürülür.
  • değilse, @c liste bağlamında değerlendirilir ve döndürülür.

Açıkçası, sondan bir önceki satırım yanlıştır. Niye ya? Ve daha önemlisi, bu davranış için belgelerin veya kaynakların hangi kısmı var?

Not: Sorunun kapsamı dışında, ben üçlü operatörü kullanarak dokümantasyonu önerisi kaçınmaları nedeni benim @b aslında bir geçici (bir işlev çağrısı sonuç) olmasıdır.

+2

"Bunu gerçekten kastediyor" yazan satır nedenini anlatıyor. –

+0

Bu benim için neden daha çok bir şey. Ama ben önyargılıyım. –

+1

"Gerçekten bunu kastediyorum" yorumunun "gerçekten anlamında" olması gerektiğini düşünüyorum. Olduğu gibi, scalar() 'ın değişmesi için, @a' a eşittir - yani yazarın gerçekten KULLANMASI için ne demek istediğini - yani açıkça böyle değil. Bunun yerine, ilk satır gerçekten ikinci satırı ETTİ; ikisi de aynı sonucu alır, bu da istenen cevap değildir. – Rini

cevap

7

Mantıksal veya işleç ("||"), soldaki bağımsız değişkeni skaler bağlamda değerlendirir.

Bunun nedeni, bağımsız değişken doğru olup olmadığını anlamaktır. Özel bir skaler bağlam olan Boole bağlamı, onu skala bağlamına zorlar.


perldoc perlop"C-style-Logical-Or"

ikili "||" mantıksal VEYA işlemi, bir kısa devre yapar. Yani, sol işlenen true ise, sağ işlenen bile değerlendirilmez. ...


"Scalar values"perldoc perldata Gönderen:

.... Boole bağlam bir dize veya bir sayıya hiçbir dönüşüm şimdiye gerçekleştirilir sayıl bağlamda sadece özel bir türüdür.

 
Binary "||" performs a short-circuit logical OR operation. That is, 
if the left operand is true, the right operand is not even evaluated. 
Scalar or list context propagates down to the right operand if it is 
evaluated. 

Bu açıkça bu liste bağlam sol işlenen yaymak değil devlet değil, ama perlop devletlerin üst: perlop olarak

+0

Aradığım yanıtı aldınız. Bunu perldata'da buldum: "Boole bağlamı, yalnızca bir dizeye veya sayıya dönüştürme yapılmayan özel bir skaler içerik türüdür." Nedeni ("doğru olup olmadığını anlamaya gerek") rağmen bana biraz şüpheli görünüyor. –

+0

Değerler doğru veya yanlış olabilir, ancak toplamlar toplanamaz. Agregalar için "doğru" genellikle "boş olmayan" anlamına gelir. Bir topluluğu skaler bağlamda değerlendirdiğinizde, toplayıcı boşsa ve aksi takdirde yanlış olan bir değer alırsınız. –

+0

@Michael: Söylediklerinizin etrafındaki açıklamalarla uyuşmasına rağmen, bana hem biraz büyülü (yani, açıklanamayan) hem de perlsyn'in çoğunlukla doğruyu söyleyen hakikat/yalanla ilgili paragrafı ile çelişiyor gibi görünmektedir: "boş liste yanlıştır, her şey başka doğrudur ". Gerçeği kabul etmek için ihtiyacım olan bilgiler Brad tarafından getirildi: "skaler'e" boolean değerlendirme zekâsı "getirildi. Perlsyn, IMO'dan önemsiz olmayan kesinti. –

7

, sadece birkaç paragraf bölümünde önce alıntı:

 
With very few exceptions, these all operate on scalar values 
only, not array values. 

yüzden sağ işlenen için kuralın istisna olduğunu çoğaltım bu liste bağlamını ve sol bağlamında hakkında herhangi açıklamada eksikliği varsayabiliriz işlenen genel kuralın geçerli olduğunu ima eder.

2

Çünkü || skaler bağlamda sol tarafı,?:. doğrudan koşullu operatörü kullanamıyorsanız

sub or_array (\@\@) { 
    return @{$_[0]} if (scalar @{$_[0]}); 
    return @{$_[1]}; 
} 

@a = or_array(@b, @c); 
+0

Şüphesiz, perl6'da bununla ilgilenmek için bir şifreli operatör var. :) – Ether

0

, kolayca performansı biraz daha düşük veciz kullanabilirsiniz:

my $ref_b = [ @b ]; # Ideally, just return an arrayref from your function 
my @a = @$ref_b ? @$ref_b : @c; 

sen ve üçlü kullanamazsınız Eğer bir fonksiyonu kullanmak Yukarıdaki cevaba göre, kodunuz, ||'un sol tarafının değerlendirildiği mantıksal bağlamı skalar bir bağlamdır ve bu nedenle @b, aslında scalar(@b) olur ve bu, @a'a atanan şeydir.