Objektif-c'de EVET / HAYIR, DOĞRU / YANLIŞ ve doğru / yanlış arasında bir fark var mı?


154

Gerçekten basit bir soru; Bu değerler arasında bir fark var mı (ve BOOL ile bool arasında bir fark var mı?) Bir iş arkadaşı, Objective-C'de farklı şeyleri değerlendirdiklerini, ancak ilgili .h dosyalarındaki typedef'lere baktığımda, YES / TRUE / true olarak 1ve NO / FALSE / false olarak tanımlandığını belirtti 0. Gerçekten bir fark var mı?


5
Pratik açıdan hiçbir fark yoktur. Bir farkı göstermek için muhtemelen çeşitli hileler yapabilirsiniz, ancak genellikle "tanımlanmamış davranış" bölgesine saparsınız.
Hot Licks

Yanıtlar:


84

Boolean olarak değişken kullanmanız koşuluyla pratikte bir fark yoktur BOOL. C, boole ifadelerini 0 olarak değerlendirip değerlendirmemelerine göre işler.

if(someVar ) { ... }
if(!someVar) { ... }

ile aynı anlama gelir

if(someVar!=0) { ... }
if(someVar==0) { ... }

bu nedenle herhangi bir ilkel türü veya ifadeyi bir boole testi olarak değerlendirebilirsiniz (örn. işaretçiler dahil). Birincisini değil ikincisini yapmanız gerektiğini unutmayın.

Not oradaki olduğunu bir sözde geniş değerleri atarsanız fark BOOLbu nedenle her zaman boolelerde olarak kullanabilir ve sadece kendi onları atamak, belirli değerleri için değişken ve test #definedeğerlerinin.

Önemli olarak, booleları asla bir karakter karşılaştırması kullanarak test etmeyin - sadece riskli someVardeğildir, çünkü EVET olmayan sıfır olmayan bir değer atanabilir, ancak bence daha da önemlisi, amacı doğru bir şekilde ifade edemez:

if(someVar==YES) { ... } // don't do this!
if(someVar==NO ) { ... } // don't do this either!

Başka bir deyişle, yapıları kullanılması amaçlandığı ve belgelendiği şekilde kullanın ve kendinizi C'deki incinme dünyasından kurtarın.


100

Orada inanmak olduğunu arasında bir fark boolve BOOL: neden bir açıklama için bu web sayfasını kontrol,
http://iosdevelopertips.com/objective-c/of-bool-and-yes.html

Çünkü BOOLbir bir unsigned charyerine basit bir tür, tip değişkenler BOOLdışındaki değerler içerebilir YESve NO.

Bu kodu düşünün:

BOOL b = 42;

if (b) {
    printf("b is not NO!\n");
}

if (b != YES) {
    printf("b is not YES!\n");
}

Çıktı:

b HAYIR değil!
b EVET değil!

Çoğu insan için bu gereksiz bir endişe kaynağıdır, ancak gerçekten bir boolean istiyorsanız a kullanmak daha iyidir bool. Eklemeliyim: iOS SDK genellikle BOOLarayüz tanımlarında kullanır , bu nedenle bu bir argüman BOOL.


5
Ancak, orijinal C uygulamasının hiç olmadığını boolve bu nedenle , bazen farkı gizlemek için bazen # tanım ile bazen de değil, bir Boolean olarak intveya charBoolean olarak kullanma geleneği olduğuna dikkat edin. Aslında, mevcut standartların bile boolkendi iç yapısını incelemeyi engelleyecek şekilde uygulanması gerekip gerekmediğinden emin değilim .
Hot Licks

1
Rağmen, ilk printfsöyler yalan. Değeri bdeğil YES, "sıfır değil", koşulun test ettiği şey budur. Yani sahip olmalısınız printf("b is not zero"), ki bu mutlaka aynı değildir YES. Bu durumda, bhem "sıfır değil" hem de "EVET değil" dir.
Lawrence Dol

Teşekkürler Lawrence, bu hatlar boyunca bir güncelleme yaptım.
Dan J

Gerçekten de, Xcode 8.2'deki ikinci çıktıyı alamadım. Nerede başarısız olurum?
Igor Kislyuk

1
@HotLicks, 0 ile sıfır ve yanlış ve doğru arasında doğal bir fark yoktur. Değerin mantıksal bir boole olması amaçlandığı sürece, ikili uyumluluğu korumak için her zaman bu arayüze sahip olacaktır. Sorunlar, booleans gibi görünen boolean'lar, örneğin c standart kütüphane uygulaması giriş işlevi, ana başarı 0'da döner, çoğu kişi bu 0'ı bir boole olarak düşünürseniz, aslında bir uygulama tanımlı numaralandırma veya kullanıcı tanımlı olduğunda başlar. callees genellikle anormal sonlandırmada sıfırdan farklı olmasını beklediği değer.
Dmitry

52

Bu konuda kapsamlı bir test yaptım. Sonuçlarım kendileri için konuşmalıdır:

//These will all print "1"
NSLog(@"%d", true == true);
NSLog(@"%d", TRUE == true);
NSLog(@"%d", YES  == true);
NSLog(@"%d", true == TRUE);
NSLog(@"%d", TRUE == TRUE);
NSLog(@"%d", YES  == TRUE);
NSLog(@"%d", true == YES);
NSLog(@"%d", TRUE == YES);
NSLog(@"%d", YES  == YES);

NSLog(@"%d", false == false);
NSLog(@"%d", FALSE == false);
NSLog(@"%d", NO    == false);
NSLog(@"%d", false == FALSE);
NSLog(@"%d", FALSE == FALSE);
NSLog(@"%d", NO    == FALSE);
NSLog(@"%d", false == NO);
NSLog(@"%d", FALSE == NO);
NSLog(@"%d", NO    == NO);


//These will all print "0"
NSLog(@"%d", false == true);
NSLog(@"%d", FALSE == true);
NSLog(@"%d", NO    == true);
NSLog(@"%d", false == TRUE);
NSLog(@"%d", FALSE == TRUE);
NSLog(@"%d", NO    == TRUE);
NSLog(@"%d", false == YES);
NSLog(@"%d", FALSE == YES);
NSLog(@"%d", NO    == YES);

NSLog(@"%d", true == false);
NSLog(@"%d", TRUE == false);
NSLog(@"%d", YES  == false);
NSLog(@"%d", true == FALSE);
NSLog(@"%d", TRUE == FALSE);
NSLog(@"%d", YES  == FALSE);
NSLog(@"%d", true == NO);
NSLog(@"%d", TRUE == NO);
NSLog(@"%d", YES  == NO);

Çıktı:

2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.072 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.076 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.082 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.091 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.092 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.097 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.098 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.101 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0

3
[[NSObject] separa] init], TRUE veya YES değerine eşit değildir. Bu nedenle, if ([[NSObject] separa] init] == ​​TRUE) ile nesne başlatma testi başarısız olur. Aslında sıfırdan farklı bir değer yapacağında tek bir "doğru" değeri tanımlayan bir Dil ile hiç rahat olmadım.
DrFloyd5

3
Bir dil bir olmayan bir Boole değeri alarak rahat olmamıştım @SamuelRenkert ifveya while. Gibi ... while("guitar gently weeps")çalışmamalı ...
Supuhstar

@SamuelRenkert ayrıca 2003 yılında bulunan Linux arka kapı:if (user_id = ROOT_UID)
Supuhstar

14

Bu sorunun cevaplarını okumak isteyebilirsiniz . Özetle, Objective-C (objc.h içindeki tanımdan):

typedef signed char        BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#define OBJC_BOOL_DEFINED


#define YES             (BOOL)1
#define NO              (BOOL)0

11

Ana (tehlikeli!) Arasındaki fark trueve YESJSON serileştirme içindedir.

Örneğin, JSON tipi sunucu isteğimiz var ve json sence doğru / yanlış göndermemiz gerekiyor:

NSDictionary *r1 = @{@"bool" : @(true)};
NSDictionary *r2 = @{@"bool" : @(YES)};
NSDictionary *r3 = @{@"bool" : @((BOOL)true)};

Daha sonra göndermeden önce JSON dizesine dönüştürüyoruz.

NSData *data = [NSJSONSerialization  dataWithJSONObject:requestParams options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

Sonuç

jsonString1 // {"bool":1}
jsonString2 // {"bool":true}
jsonString3 // {"bool":true}

API mantığı nedeniyle jsonString1bir hataya neden olabilir.

Bu yüzden Objective-C'deki boolean'lara dikkat edin.

Yalnızca tam, Özetle @YESve döküm değeri olarak @((BOOL)expression)vardır __NSCFBooleantürü ve dönüştürülmüş trueJSON seri ile. @(expression1 && expression2)(Çift @(YES && YES)) gibi diğer tüm ifadeler türdedir ve JSON __NSCFNumber (int)biçimine dönüştürülür 1.

PS: Dize değerli boolean kullanabilirsiniz

@{@"bool" : @"true"}; // in JSON {"bool":true}

1

Burada hiç kimsenin bahsetmediği ince bir hata var, sanırım ... her şeyden daha mantıklı bir hata daha var:

int i = 2;
if(i);        //true
if(i==YES);   // false
if((!!i)==YES); //true

bu yüzden buradaki sorun sadece (YES==1)ve C'de karşılaştırma boole değil, değere dayalı.

çünkü YESsadece #define(dile özgü bir şeyden ziyade), bir değer olması gerekir ve 1en mantıklıdır.


Bu aslında 2 yıldan daha uzun bir süre önce daha az ayrıntıyla DanJ'lerle aynı cevaptır.
Lawrence Dol

@LawrenceDol Bilmiyorum, YES'in sadece 1 olarak tanımlandığından ve dile özgü olmadığından bahsediyor, daha üst düzey bir dilde olabilir gibi ... birisi muhtemelen bundan değer alabilir ... ama iyi trolling, seninle.
Grady Oyuncu

0

Sanırım birçok durumda daha açıklayıcı olmak için EVET / HAYIR eklediler. Örneğin:

[button setHidden:YES];

daha iyi geliyor

[button setHidden:TRUE];

2
Katılmıyorum; ikisi de aynısını okudular. Ancak, sıradan bir kişi için bir kullanıcı arayüzünde Evet / Hayır güzel görünüyor düşünüyorum.
Lawrence Dol

16
Ben de aynı fikirde değilim. Herhangi bir şey varsa, diğer dillerde yıllardır kullanılan yazılı olmayan standartlara bağlı kalmama nedeniyle kötü okuyor. IE, çok sayıda standarda uymadığınızda ne olduğuna dair en iyi örnektir.
FreeAsInBeer

1
2 kesin olmayan cevap için yarım downvote ve cevaplarınızı imzalamak için
fpg1503

-2

İlk önce doğru ve yanlışın ne olduğunu ve ilk başta onlara ne anlam verdiğini inceleyelim.

lambda hesabında eğer bir then b else c olarak adlandırılan bir yapı oluşturabiliriz:

(\ifThenElse. <use if then else>)(\a. \b. \c. a b c)

JavaScript'te, Bu şöyle görünür:

(function(ifThenElse) {
    // use ifThenElse
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
});

ifThenElse'ın yararlı olması için, sağ veya solu seçen ve "true" seçeneğini seçerken bunu yapan "true" işlevine veya "true" seçeneğini seçmeyen "false" işlevine ihtiyacımız vardır.

Bu işlevleri şu şekilde tanımlayabiliriz:

(\true. <use true>)(\a. \b. a) and (\false. <use false>)(\a. \b. b)

JavaScript'te şöyle görünür:

(function(True) {
    // use True
})(function(a) {
     return function(b) {
         return a;
     }
});

(function(False) {
    // use True
})(function(a) {
     return function(b) {
         return b;
     }
});

şimdi aşağıdakileri yapabiliriz

(\true. \false. \ifThenElse. \doThis. \doThat. ifThenElse true doThis doThat)
(\a. \b. a)(\a. \b. b)(\a. \b. \c. a b c)(\a. ())(\a. ())

doThis ve doThat ile (\ a. ()) olmak, lambda hesabı yazdırma / matematik / dizeler gibi herhangi bir hizmet sunmadığından, yapabileceğimiz tek şey hiçbir şey yapmamak ve bunu yaptığımızı söylemek (ve daha sonra istediğimiz yan etkileri sağlayan sistemimiz)

yani bunu iş başında görelim.

(function(True) {
    return (function(False) {
        return (function(ifThenElse) {
            return (function(doThis) {
                return (function(doThat) {
                    return ifThenElse(True)(doThis)(doThat);
                });
            });
        });
    })
})(function(a) {
     return function(b) {
         return a;
     }
})(function(a) {
     return function(b) {
         return b;
     }
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
})(function(a) { console.log("you chose LEFT!"); })
(function(a) {console.log("you chose RIGHT");})();

Bu, birden fazla işleve ayırmak için diziler / haritalar / argümanlar / veya birden fazla ifadeyi kullanmamıza izin verildiğinde basitleştirilebilen derin bir ortam, ancak tutmak istiyorum, kendimi tam olarak bir argümanın işlevleriyle sınırlayabildiğim kadar saf sadece.

True / False adının doğal bir önemi olmadığını fark ederseniz, bunları kolayca evet / hayır, sol / sağ, sağ / sol, sıfır / bir, elma / portakal olarak yeniden adlandırabiliriz. Hangi seçim yapılırsa yapılsın bunun sadece seçicinin yaptığı türden kaynaklanması önemlidir. Eğer "SOL" basılırsa, seçicinin sadece doğru olabileceğini biliyoruz ve bu bilgiye dayanarak daha sonraki kararlarımıza rehberlik edebiliriz.

Özetlemek gerekirse

function ChooseRight(left) {
    return function _ChooseRight_inner(right) {
        return right;
    }
}
function ChooseLeft(left) {
    return function _ChooseLeft_inner(right) {
        return left;
    }
}

var env = {
    '0': ChooseLeft,
    '1': ChooseRight,
    'false': ChooseRight,
    'true': ChooseLeft,
    'no': ChooseRight
    'yes': ChooseLeft,
    'snd': ChooseRight,
    'fst': ChooseLeft
};
var _0 = env['0'];
var _1 = env['1'];
var _true = env['true'];
var _false = env['false'];
var yes = env['yes'];
var no = env['no'];

// encodes church zero or one to boolean
function lambda_encodeBoolean(self) {
    return self(false)(true);
}
// decodes a Boolean to church zero or one
function lambda_decodeBoolean(self) {
    console.log(self, self ? env['true'] : env['false']);
    return self ? env['true'] : env['false'];
}

lambda_decodeBoolean('one' === 'two')(function() {
    console.log('one is two');
})(function() {
    console.log('one is not two');
})();

lambda_decodeBoolean('one' === 'one')(function() {
    console.log('one is one');
})(function() {
    console.log('one is not one');
})();

-7

Hayır, EVET / HAYIR, DOĞRU / YANLIŞ (1/0) 'dan farklı bir yöntemdir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.