objective c - ¿Hay una diferencia entre SÍ/NO, VERDADERO/FALSO y verdadero/falso en objetivo-c?
objective-c boolean (9)
Pregunta simple realmente; ¿Hay alguna diferencia entre estos valores (y hay una diferencia entre BOOL y bool)? Un compañero de trabajo mencionó que evalúan diferentes cosas en Objective-C, pero cuando miré los typedefs en sus respectivos archivos .h, YES / TRUE / true se definieron todos como 1
y NO / FALSE / false se definieron todos como 0
. Hay realmente alguna diferencia?
Creo que agregan SÍ / NO para ser más fácil de entender en muchos casos. Por ejemplo:
[button setHidden:YES];
suena mejor que
[button setHidden:TRUE];
Creo que hay una diferencia entre bool
y BOOL
. Consulte esta página web para obtener una explicación de por qué:
http://iosdevelopertips.com/objective-c/of-bool-and-yes.html
Como BOOL
es un unsigned char
más que un tipo primitivo, las variables del tipo BOOL
pueden contener valores distintos de YES
y NO
.
Considera este código:
BOOL b = 42;
if (b) {
printf("b is not NO!/n");
}
if (b != YES) {
printf("b is not YES!/n");
}
El resultado es:
¡b no es NO!
¡b no es SÍ!
Para la mayoría de las personas esto es una preocupación innecesaria, pero si realmente quieres un booleano, es mejor usar un bool
. Debo añadir: el SDK de iOS generalmente usa BOOL
en sus definiciones de interfaz, por lo que es un argumento para seguir con BOOL
.
Es posible que desee leer las respuestas a esta question . En resumen, en Objective-C (de la definición en objc.h):
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
Hay un error sutil que nadie ha mencionado aquí, que pensé que incluiría ... más de un error lógico que cualquier otra cosa:
int i = 2;
if(i); //true
if(i==YES); // false
if((!!i)==YES); //true
así que el problema aquí es solo eso (YES==1)
y en C la comparación no es booleana, sino que está basada en el valor.
porque YES
es solo un #define
(en lugar de algo intrínseco al lenguaje), tiene que ser de algún valor, y 1
tiene más sentido.
Hice una prueba exhaustiva sobre esto. Mis resultados deberían hablar por sí mismos:
//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);
El resultado es:
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
La principal (¡peligrosa!) Diferencia entre true
y YES
está en la serialización JSON.
Por ejemplo, tenemos una solicitud de servidor de tipo JSON y necesitamos enviar verdadero / falso en jsonncence:
NSDictionary *r1 = @{@"bool" : @(true)};
NSDictionary *r2 = @{@"bool" : @(YES)};
NSDictionary *r3 = @{@"bool" : @((BOOL)true)};
Luego lo convertimos a cadena JSON antes de enviarlo como
NSData *data = [NSJSONSerialization dataWithJSONObject:requestParams options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
El resultado es
jsonString1 // {"bool":1}
jsonString2 // {"bool":true}
jsonString3 // {"bool":true}
Debido a la lógica API, jsonString1
podría jsonString1
un error.
Así que ten cuidado con los booleanos en Objective-C.
PD: puedes usar
@{@"bool" : @"true"}; // {"bool":true}
No hay diferencia práctica siempre que use variables de BOOL
como booleanos. C procesa expresiones booleanas en función de si se evalúan a 0 o no 0. Entonces:
if(someVar ) { ... }
if(!someVar) { ... }
significa lo mismo que
if(someVar!=0) { ... }
if(someVar==0) { ... }
por lo que puede evaluar cualquier tipo o expresión primitiva como una prueba booleana (que incluye, por ejemplo, punteros). Tenga en cuenta que debe hacer lo primero, no lo último.
Tenga en cuenta que existe una diferencia si asigna valores obtusos a la llamada variable BOOL
y prueba valores específicos, por lo tanto, siempre utilícelos como booleanos y solo asígnelos de sus valores #define
.
Es importante destacar que nunca pruebe los booleanos usando una comparación de caracteres, no solo es arriesgado porque a someVar
se les puede asignar un valor distinto de cero que no es SÍ, pero, en mi opinión, lo más importante es que no expresa la intención correctamente:
if(someVar==YES) { ... } // don''t do this!
if(someVar==NO ) { ... } // don''t do this either!
En otras palabras, use los constructos tal como están destinados y documentados para ser utilizados y se ahorrará en un mundo de dolor en C.
No, SÍ / NO es una forma diferente de referirse a VERDADERO / FALSO (1/0)
Primero, examinemos lo que es verdadero y falso y lo que les da sentido en primer lugar.
podemos construir una estructura llamada if a then b else c en lambda calculus de la siguiente manera:
(/ifThenElse. <use if then else>)(/a. /b. /c. a b c)
En JavaScript, esto se ve así:
(function(ifThenElse) {
// use ifThenElse
})(function(a) {
return function(b) {
return function(c) {
return a(b)(c);
};
};
});
Para que ifThenElse sea útil, necesitamos una función "verdadera" que elija ya sea derecha o izquierda, y lo hace ignorando la otra opción, o una función "falsa" que elige la opción "true" no toma.
Podemos definir estas funciones de la siguiente manera:
(/true. <use true>)(/a. /b. a) and (/false. <use false>)(/a. /b. b)
en JavaScript se ve así:
(function(True) {
// use True
})(function(a) {
return function(b) {
return a;
}
});
(function(False) {
// use True
})(function(a) {
return function(b) {
return b;
}
});
ahora podemos hacer lo siguiente
(/true. /false. /ifThenElse. /doThis. /doThat. ifThenElse true doThis doThat)
(/a. /b. a)(/a. /b. b)(/a. /b. /c. a b c)(/a. ())(/a. ())
con doThis y doThat siendo (/ a. ()) porque el cálculo lambda no ofrece ningún servicio como impresión / matemática / cadenas, todo lo que podemos hacer es no hacer nada y decir que lo hicimos (y luego hacer trampa reemplazándolo con servicios en nuestro sistema que proporciona los efectos secundarios que queremos)
así que vamos a ver esto en acción.
(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");})();
Ese es un entorno profundo que podría simplificarse si se nos permitiera usar arrays / maps / arguments / o más de una declaración para dividirnos en múltiples funciones, pero quiero mantenerlo de la manera más pura posible, limitándome a las funciones de exactamente un argumento solamente.
observe que el nombre verdadero / falso no tiene un significado inherente, podemos cambiarle el nombre fácilmente a sí / no, izquierda / derecha, derecha / izquierda, cero / uno, manzana / naranja. Tiene importancia en que cualquier elección que se haga, solo es causada por el tipo de selector elegido. Entonces, si se imprime "IZQUIERDA", sabemos que el seleccionador solo puede ser cierto, y de acuerdo con este conocimiento podemos guiar nuestras decisiones posteriores.
Entonces para resumir
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'');
})();