Kısa devre değerlendirmesi - Short-circuit evaluation
Değerlendirme stratejileri |
---|
Kısa devre değerlendirmesi , minimum değerlendirme veya McCarthy değerlendirmesi ( John McCarthy'den sonra ), bazı programlama dillerinde ikinci argümanın yalnızca ilk argümanın değerini belirlemek için yeterli olmadığı durumlarda yürütüldüğü veya değerlendirildiği bazı Boole operatörlerinin semantiğidir. ifade: işlevin ilk argümanı olarak değerlendirildiğinde , genel değer şöyle olmalıdır ; ve işlevin ilk argümanı olarak değerlendirildiğinde , genel değer olmalıdır .
AND
false
false
OR
true
true
Tembel değerlendirmeli programlama dillerinde ( Lisp , Perl , Haskell ), olağan Boole operatörleri kısa devredir. Diğerlerinde ( Ada , Java , Delphi ), hem kısa devre hem de standart Boole operatörleri mevcuttur. Özel veya (XOR) gibi bazı Boolean işlemleri için kısa devre yapmak mümkün değildir, çünkü sonucu belirlemek için her iki işlenen de her zaman gereklidir.
Kısa devre operatörleri, katı olmadıkları için basit aritmetik operatörlerden ziyade kontrol yapılarıdır . Olarak zorunlu dil açısından (özellikle Cı- ve C ++ yan etkiler önemlidir), kısa devre operatörler tanıtmak dizisi noktası - tamamen herhangi biri bulunan, birinci bağımsız değişken değerlendirmek yan etkiler ikinci değişkeni işleme (isteğe bağlı olarak) daha önce. Algol 68 kullanılan proceduring elde etmek için , kullanıcı tanımlı kısa devre operatörleri ve prosedürler.
Kısa devre operatörlerinin kullanımı sorunlu olarak eleştirilmiştir:
Koşullu bağlaçlar - kısaca " cand " ve " cor " - ilk bakışta göründüklerinden daha az masumdur. Örneğin, cor cand üzerinden dağıtmaz : karşılaştırın
- (A cand B) kor Cı ile (bir kor C) cand (B kor ° C);
¬A ∧ C durumunda, ikinci ifade B'nin tanımlanmasını gerektirir, birincisi gerektirmez. Koşullu bağlaçlar böylece programlarla ilgili biçimsel akıl yürütmeyi karmaşıklaştırdığından, bunlardan kaçınılması daha iyidir.
Tanım
Uygular kısa devre değerlendirme herhangi bir programlama dilinde, ekspresyon eşdeğerdir koşullu ifade ve ifade eşdeğerdir . Her iki durumda da x yalnızca bir kez değerlendirilir.
x and y
if x then y else x
x or y
if x then x else y
Yukarıdaki genelleştirilmiş tanım , kısa devre operatörlerinin en son değerlendirilen alt ifadeyi döndürebildiği, ikiden fazla doğruluk değerine sahip True
ve False
, gevşek yazılmış dilleri barındırır . Buna aşağıdaki tabloda "son değer" denir. Kesin olarak yazılan bir dil için, ifade boole durumu için ve sırasıyla basitleştirilir .
if x then y else false
if x then true else y
Öncelik
Her ne kadar AND
sürer öncelik üzerinde OR
birçok dilde, bu kısa devre değerlendirmenin bir evrensel özellik değildir. Aynı önceliği alan ve birbiriyle sol ilişkisel olan iki operatörün bir örneği , POSIX kabuğunun komut listesi sözdizimidir.
Aşağıdaki basit soldan sağa değerlendirici bir öncelik zorlar AND
üzerinde OR
bir yan continue
:
function short-circuit-eval (operators, values) let result := True for each (op, val) in (operators, values): if op = "AND" && result = False continue else if op = "OR" && result = True return result else result := val return result
Resmileştirme
Yan etkileri olan veya olmayan kısa devre mantığı, Hoare'nin koşullu . Sonuç olarak, kısa devre yapmayan operatörler, aynı değerlendirme sırasına sahip olmak için kısa devre mantığı dışında tanımlanabilir.
Ortak programlama ve komut dosyası dillerinde destek
Dilim | hevesli operatörler | Kısa devre operatörleri | Sonuç türü |
---|---|---|---|
Gelişmiş İş Uygulama Programlama ( ABAP ) | Yok |
and , or
|
Boole 1 |
Ada |
and , or
|
and then , or else
|
Boole |
ALGOL 68 | ve, &, ∧ ; veya, ∨ | andf , orf (her ikisi de kullanıcı tanımlı) | Boole |
APL |
∧ , ∨ , ⍲ (nand), ⍱ (nor), vb.
|
:AndIf , :OrIf
|
Boole 1 |
awk | Yok |
&& , ||
|
Boole |
bash | Yok |
&& , ||
|
Boole |
C , Amaç-C | Yok |
&& , || ,?
|
int ( && , || ), opnd bağımlı ( ? )
|
C++ 2 | Yok |
&& , || ,?
|
Boole ( && , || ), opnd bağımlı ( ? )
|
C# |
& , |
|
&& , || , ? ,??
|
Boole ( && , || ), opnd bağımlı ( ? , ?? )
|
ColdFusion İşaretleme Dili (CFML) | Yok |
AND , OR , && ,||
|
Boole |
D 3. |
& , |
|
&& , || ,?
|
Boole ( && , || ), opnd bağımlı ( ? )
|
Eyfel |
and , or
|
and then , or else
|
Boole |
Erlang |
and , or
|
andalso , orelse
|
Boole |
Fortran 4 |
.and. , .or.
|
.and. , .or.
|
Boole |
Git , Haskell , OCaml | Yok |
&& , ||
|
Boole |
Java , MATLAB , R , Swift |
& , |
|
&& , ||
|
Boole |
JavaScript , Julia |
& , |
|
&& , ||
|
Son değer |
Kement | Yok |
and , or , && ,||
|
Son değer |
Kotlin |
and , or
|
&& , ||
|
Boole |
Lisp , Lua , Şema | Yok |
and , or
|
Son değer |
kabakulak (M) |
& , !
|
Yok | sayısal |
Modül-2 | Yok |
AND , OR
|
Boole |
Oberon | Yok |
& , OR
|
Boole |
OCaml | Yok |
&& , ||
|
Boole |
paskal |
and , or 5 , 9
|
and_then , or_else 6 , 9
|
Boole |
Perl |
& , |
|
&& , and , || ,or
|
Son değer |
yakut |
and , or
|
&& , ||
|
Son değer |
PHP |
& , |
|
&& , and , || ,or
|
Boole |
POSIX kabuğu (komut listesi) | Yok |
&& , ||
|
Son değer (çıkış) |
piton | Yok |
and , or
|
Son değer |
Pas |
& , |
|
&& , ||
|
Boole |
küçük konuşma |
& , |
|
and: , or: 7
|
Boole |
standart makine öğrenimi | Bilinmeyen |
andalso , orelse
|
Boole |
TTCN-3 | Yok |
and , or
|
Boole |
Beckhoff TwinCAT® ( IEC 61131-3 ) 10 |
AND , OR
|
AND_THEN , OR_ELSE
|
Boole |
Visual Basic .NET |
And , Or
|
AndAlso , OrElse
|
Boole |
Visual Basic , Uygulamalar için Visual Basic (VBA) |
And , Or
|
Select Case 8
|
sayısal |
Wolfram Dili |
And @@ {...} , Or @@ {...}
|
And , Or , && ,||
|
Boole |
ZTT |
& , |
|
Yok | Boole |
1 ABAP ve APL'nin belirgin bir boole türü yoktur.
2 olduğunda aşırı , operatörler &&
ve ||
istekli ve herhangi bir tür geri dönebilir.
3 Bu yalnızca çalışma zamanı tarafından değerlendirilen ifadeler için geçerlidir static if
ve static assert
. Statik başlatıcılardaki veya bildirim sabitlerindeki ifadeler istekli değerlendirmeyi kullanır.
4 Fortran operatörleri ne kısa devrelidir ne de isteklidir: dil belirtimi derleyicinin optimizasyon yöntemini seçmesine izin verir.
5 ISO/IEC 10206:1990 Genişletilmiş Pascal , kısa devreye izin verir, ancak gerektirmez.
6 ISO/IEC 10206:1990 Genişletilmiş Pascal destekler and_then
ve or_else
.
7 Smalltalk, argümanı and:
bir blok olduğu sürece (örneğin, false and: [Transcript show: 'Wont see me']
) kısa devre semantiğini kullanır . CASE deyimlerini destekleyen
8 BASIC dili, bunu sabit etiketlerle sınırlı atlama tabloları yerine koşullu değerlendirme sistemini kullanarak yaptı.
9 Delphi ve Free Pascal varsayılan olarak kısa devre değerlendirmesi. Bu, derleyici seçenekleriyle değiştirilebilir ancak yaygın olarak kullanılmamaktadır.
10 standart IEC 61131-3 Aslında, eğer tanımlamaz AND
ve OR
kullanımı kısa devre değerlendirme ve operatörler tanımlamaz AND_THEN
ve OR_ELSE
. Tablodaki girişler, Beckhoff TwinCAT® için nasıl çalıştığını gösterir.
Genel kullanım
İkinci argümanın istenmeyen yan etkilerinden kaçınmak
C tabanlı bir dil kullanan olağan örnek :
int denom = 0;
if (denom != 0 && num / denom)
{
... // ensures that calculating num/denom never results in divide-by-zero error
}
Aşağıdaki örneği göz önünde bulundurun:
int a = 0;
if (a != 0 && myfunc(b))
{
do_something();
}
Bu örnekte, myfunc(b)
asla çağrılmayan kısa devre değerlendirme garantileri . Bunun nedeni false olaraka != 0
değerlendirilmesidir . Bu özellik, iki kullanışlı programlama yapısına izin verir.
- İlk alt ifade pahalı bir hesaplamanın gerekip gerekmediğini kontrol ederse ve kontrol false olarak değerlendirilirse , ikinci argümanda pahalı hesaplama ortadan kaldırılabilir.
- İlk ifadenin, onsuz ikinci ifadenin bir çalışma zamanı hatasına neden olabileceği bir koşulu garanti ettiği bir yapıya izin verir .
Her ikisi de, minimum değerlendirmenin hem boş göstericinin kaldırılmasını hem de fazla bellek alımını önlediği aşağıdaki C parçacığında gösterilmektedir:
bool is_first_char_valid_alpha_unsafe(const char *p)
{
return isalpha(p[0]); // SEGFAULT highly possible with p == NULL
}
bool is_first_char_valid_alpha(const char *p)
{
return p != NULL && isalpha(p[0]); // 1) no unneeded isalpha() execution with p == NULL, 2) no SEGFAULT risk
}
Deyimsel koşullu yapı
Minimum değerlendirme bir operatörün semantik tanımının bir parçası olduğu ve (isteğe bağlı) bir optimizasyon olmadığı için , birçok kodlama modeli özlü (deyimsel ise) koşullu bir yapı olarak buna güvenmeye başlamıştır. Örnekler şunları içerir:
Perl deyimleri:
some_condition or die; # Abort execution if some_condition is false
some_condition and die; # Abort execution if some_condition is true
POSIX kabuk deyimleri:
modprobe -q some_module && echo "some_module installed" || echo "some_module not installed"
Bu deyim echo
başarısız olamayacağını varsayar .
Olası sorunlar
Test edilmemiş ikinci durum, gerçekleştirilmemiş yan etkiye yol açar
Bu faydalara rağmen, minimum değerlendirme, bunun gerçekleştiğini fark etmeyen (veya unutan) programcılar için sorunlara neden olabilir. Örneğin, kodda
if (expressionA && myfunc(b)) {
do_something();
}
eğer myfunc(b)
olursa olsun bazı gerekli işlemi gerçekleştirmek gerekiyordu do_something()
böyle tahsis sistem kaynakları ve gibi yürütülür expressionA
false ile değerlendirir, daha sonra myfunc(b)
sorunlara neden olabilecek şekilde, yürütülmez. Java gibi bazı programlama dillerinde, bu sorunu önlemek için biri minimum değerlendirme kullanan ve diğeri kullanmayan iki operatör bulunur.
Gerçekleştirilmemiş yan etki ifadeleriyle ilgili sorunlar, uygun programlama stiliyle kolayca çözülebilir, yani, değerlendirmelerde yan etkileri olan değerlerin kullanılması genellikle kodu opak ve hataya açık hale getirme eğiliminde olduğundan, boole ifadelerinde yan etkilerin kullanılmaması gibi.
Kısıtlayıcı optimizasyonlar nedeniyle azaltılmış verimlilik
Kısa devre, modern merkezi işlem birimlerinde (CPU'lar) şube tahmininde hatalara yol açabilir ve performansı önemli ölçüde azaltabilir. Kayda değer bir örnek, ışın izlemede eksen hizalı kutu kesişim koduyla yüksek düzeyde optimize edilmiş ışındır . Bazı derleyiciler bu tür durumları algılayabilir ve daha hızlı kod yayınlayabilir, ancak programlama dili semantiği bu tür optimizasyonları sınırlayabilir.
Böyle bir durum için optimize edemeyen bir derleyici örneği , 2012 itibariyle Java'nın Hotspot VM'sidir.