1. Post-condicionales
Puntos Clave
- Sintaxis: COMMAND:condition arguments -- dos puntos entre el comando y la condición
- Código compacto: Ejecuta un solo comando condicionalmente sin bloques IF/ELSE
- SET:condition: SET:condition var = value -- solo establece si la condición es verdadera
- QUIT:condition: Sale de un bucle o método condicionalmente
- DO:condition: Llama a un método condicionalmente
- WRITE:condition: Muestra salida condicionalmente
- Cualquier comando: La mayoría de los comandos de ObjectScript soportan post-condicionales
- Sin ELSE: Los post-condicionales no tienen contraparte ELSE -- use IF/ELSE para eso
Notas Detalladas
Descripción general
Los post-condicionales son una característica distintiva de ObjectScript que permite ejecutar cualquier comando condicionalmente agregando dos puntos y una expresión booleana directamente después de la palabra clave del comando. Esto produce código conciso y legible para operaciones condicionales simples sin la sobrecarga de bloques IF/ELSE completos.
Sintaxis básica de post-condicional
SET x = 10
// SET with post-conditional
SET:x>5 message = "x is large"
WRITE message, ! // x is large
// Equivalent to:
IF x > 5 SET message = "x is large"
// WRITE with post-conditional
WRITE:x>5 "Greater than 5", !
// Multiple post-conditionals (each independent)
SET:x>20 category = "very large"
SET:x>10 category = "large"
SET:x>5 category = "medium"
SET:x<=5 category = "small"
WRITE category, ! // medium
QUIT con post-condicional
// Early exit from a FOR loop
SET sum = 0
FOR i = 1:1:100 {
SET sum = sum + i
QUIT:sum>100
}
WRITE "Sum: ", sum, " at i=", i, !
// Output: Sum: 105 at i=14
// In method: return early if precondition fails
ClassMethod Divide(a As %Numeric, b As %Numeric) As %Numeric
{
QUIT:b=0 "" // Return empty if division by zero
QUIT a / b
}
DO con post-condicional
// Call a method only if condition is met
DO:status'=$$$OK ..LogError(status)
// Multiple conditional calls
DO:age>=18 ..ProcessAdult(name)
DO:age<18 ..ProcessMinor(name)
Post-condicional con expresiones complejas
// Parentheses for complex conditions
SET:(x>0)&&(x<100) range = "valid"
// String conditions
SET name = "Alice"
WRITE:name="Alice" "Found Alice!", !
// Negation
SET:(obj'="") result = obj.Calculate()
// Post-conditional on KILL
KILL:cleanup tempVar
Patrones comunes
// Default value assignment
SET:('$DATA(config)) config = "default"
// Conditional increment
SET:isValid count = count + 1
// Guard clause in a method
ClassMethod Process(input As %String) As %Status
{
QUIT:input="" $$$ERROR($$$GeneralError, "Input required")
// ... rest of processing
QUIT $$$OK
}
// Conditional THROW
THROW:status'=$$$OK ##class(%Exception.StatusException).CreateFromStatus(status)
Referencias de Documentación
2. QUIT vs RETURN
Puntos Clave
- QUIT: Sale del contexto actual -- cuerpo de bucle, método o bloque DO
- RETURN: Siempre sale del método/rutina actual, incluso desde dentro de un bucle
- QUIT en bucle: Sale solo del bucle más interno, continúa después del bucle
- RETURN en bucle: Sale del método completo desde dentro del bucle
- Valor de retorno: Tanto QUIT expr como RETURN expr pueden devolver valores desde métodos
- QUIT desde método: Cuando se usa fuera de un bucle, QUIT sale del método (igual que RETURN)
Notas Detalladas
Descripción general
QUIT y RETURN ambos salen del código, pero difieren en de qué salen. QUIT sale del contexto envolvente más cercano (bucle o método), mientras que RETURN siempre sale del método. Esta distinción es crítica cuando necesita salir de un método desde dentro de un bucle anidado.
QUIT en bucles vs métodos
ClassMethod Example1()
{
WRITE "Before loop", !
FOR i = 1:1:10 {
QUIT:i=3 // Exits the FOR loop only
}
WRITE "After loop, i=", i, ! // Prints! i=3
WRITE "Method continues", ! // Also prints
}
ClassMethod Example2()
{
WRITE "Before loop", !
FOR i = 1:1:10 {
RETURN:i=3 // Exits the ENTIRE METHOD
}
WRITE "After loop", ! // NEVER reached
}
QUIT vs RETURN en bucles anidados
ClassMethod NestedExample()
{
FOR i = 1:1:5 {
FOR j = 1:1:5 {
IF (i = 3) && (j = 2) {
QUIT // Exits inner FOR loop only
// Outer loop continues with i=3, then i=4, i=5
}
}
WRITE "i=", i, ! // Prints for all i values
}
WRITE "Done", ! // Prints
}
ClassMethod NestedReturn()
{
FOR i = 1:1:5 {
FOR j = 1:1:5 {
IF (i = 3) && (j = 2) {
RETURN // Exits the ENTIRE method immediately
}
}
WRITE "i=", i, ! // Prints for i=1, i=2 only
}
WRITE "Done", ! // NEVER reached
}
Devolver valores
// QUIT with return value (in a method returning a value)
ClassMethod Add(a, b) As %Integer
{
QUIT a + b
}
// RETURN with return value
ClassMethod FindFirst(list As %ListOfDataTypes) As %String
{
FOR i = 1:1:list.Count() {
SET item = list.GetAt(i)
IF item [ "target" {
RETURN item // Exit method immediately with value
}
}
RETURN "" // Not found
}
// QUIT in a method with no return value
ClassMethod Process()
{
QUIT:errorCondition // Exit method (no return value)
// ... processing
}
QUIT en bloques DO
// QUIT exits a DO block (argumentless DO with code block)
DO {
SET x = $RANDOM(10)
QUIT:x=5 // Exits the DO block, not any outer loop
WRITE x, " "
} WHILE x '= 5
Referencias de Documentación
3. Evaluación booleana
Puntos Clave
- Verdadero: Cualquier valor numérico distinto de cero es verdadero (1, -1, 42, 3.14)
- Falso: Cero (0) es falso
- Cadena vacía: "" se evalúa como 0, que es falso
- Cadenas no numéricas: "abc" se evalúa como 0 (falso) porque su valor numérico es 0
- Cadenas con número inicial: "5abc" se evalúa como 5, que es verdadero
- Canónico: La veracidad depende de la interpretación numérica del valor
- Resultado booleano: Los operadores de comparación y lógicos siempre devuelven 0 o 1
Notas Detalladas
Descripción general
ObjectScript no tiene un tipo booleano dedicado. En su lugar, usa evaluación numérica: cero es falso, cualquier valor distinto de cero es verdadero. Cuando una cadena se evalúa como booleano, primero se convierte a su valor numérico. Comprender esta coerción es crítico para escribir condiciones correctas.
Reglas de veracidad
// Nonzero = true
IF 1 WRITE "1 is true", ! // prints
IF -1 WRITE "-1 is true", ! // prints
IF 42 WRITE "42 is true", ! // prints
IF 0.001 WRITE "0.001 is true", ! // prints
// Zero = false
IF 0 WRITE "0 is true", ! // does NOT print
IF '0 WRITE "0 is false", ! // prints
// Empty string = 0 = false
IF "" WRITE "empty is true", ! // does NOT print
SET x = ""
IF 'x WRITE "empty is false", ! // prints
// Non-numeric strings = 0 = false
IF "abc" WRITE "abc is true", ! // does NOT print
IF "hello" WRITE "hello is true", ! // does NOT print
// Leading numeric strings = their numeric value
IF "5abc" WRITE "5abc is true", ! // prints (5 is nonzero)
IF "0abc" WRITE "0abc is true", ! // does NOT print (0)
Resultados booleanos de comparaciones
// Comparisons return exactly 0 or 1
WRITE 5 > 3, ! // 1
WRITE 3 > 5, ! // 0
WRITE "A" = "A", ! // 1
WRITE "A" = "B", ! // 0
// Can store boolean results
SET isAdult = (age >= 18)
SET isValid = (name '= "") && (age > 0)
// Boolean arithmetic
SET total = (a > 0) + (b > 0) + (c > 0)
WRITE "Number of positive values: ", total, !
Errores comunes de veracidad
// PITFALL: Testing a string that should be boolean
SET flag = "yes"
IF flag WRITE "flag is true", ! // does NOT print!
// "yes" has numeric value 0, so it is false in boolean context
// Correct approach: test against specific values
IF flag = "yes" WRITE "flag is yes", ! // prints
// PITFALL: Empty string vs zero
// In boolean context (IF), "" acts like 0 (false)
// But "" and 0 are NOT equal with the = operator!
SET val = ""
IF val WRITE "truthy", ! // does NOT print ("" is falsy)
IF val = 0 WRITE "equal to zero", ! // does NOT print! ("" '= 0)
IF val = "" WRITE "equal to empty", ! // prints
SET zero = 0
IF zero WRITE "truthy", ! // does NOT print (0 is falsy)
IF zero = "" WRITE "equal to empty", ! // does NOT print! (0 '= "")
IF zero = 0 WRITE "equal to zero", ! // prints
// To coerce "" to numeric before comparison, use unary +
WRITE +"" = 0, ! // 1 (+"" gives 0, then 0 = 0)
WRITE "" = 0, ! // 0 ("" is not 0)
// PITFALL: Non-numeric strings are all falsy
IF "yes" WRITE "yes", ! // does NOT print ("yes" = 0 numerically)
IF "true" WRITE "true", ! // does NOT print
IF "abc" WRITE "abc", ! // does NOT print
WRITE "yes" = 0, ! // 0 ("yes" is not 0 -- different values)
WRITE +"yes" = 0, ! // 1 (+"yes" coerces to 0, then 0 = 0)
Operador NOT
SET x = 5
WRITE 'x, ! // 0 (NOT 5 = false)
SET y = 0
WRITE 'y, ! // 1 (NOT 0 = true)
// Double negation
WRITE ''x, ! // 1 (NOT NOT 5 = true)
WRITE ''y, ! // 0 (NOT NOT 0 = false)
// '' can normalize any value to 0 or 1
SET normalized = ''someValue
// normalized is now exactly 0 or 1
Veracidad en control de flujo
// IF uses truthiness
SET name = "Alice"
IF name WRITE "name has a value", ! // does NOT print ("Alice" = 0)
// Correct: check for non-empty
IF name '= "" WRITE "name is not empty", ! // prints
// $DATA returns 0 (falsy) or 1/10/11 (truthy)
IF $DATA(^config("key")) WRITE "key exists", !
// $LENGTH returns 0 for empty, positive for non-empty
IF $LENGTH(name) WRITE "name has length", ! // prints (5 > 0)
Referencias de Documentación
Resumen de Preparación para el Examen
Conceptos críticos a dominar:
- Sintaxis post-condicional: COMMAND:condition -- dos puntos directamente después del comando, sin espacio
- QUIT vs RETURN: QUIT sale del contexto más cercano (bucle o método); RETURN siempre sale del método
- QUIT en bucles anidados: Solo sale del bucle más interno -- use RETURN para salir del método
- Evaluación booleana: 0 = falso, distinto de cero = verdadero; "" es falso; "abc" es falso (valor numérico 0)
- Trampa de veracidad de cadenas: "yes", "true", "abc" son todos FALSOS porque su valor numérico es 0
- "" vs 0: Ambos son falsos en contexto booleano, pero `"" = 0` es FALSO -- son valores diferentes. Use el `+` unario para coaccionar cadenas a números antes de la comparación numérica
- Post-condicionales en cualquier comando: SET, QUIT, DO, WRITE, KILL, THROW todos los soportan
- Valores de retorno: Tanto QUIT expr como RETURN expr pueden devolver valores desde métodos
Escenarios comunes de examen:
- Predecir si QUIT sale de un bucle o método según el contexto
- Determinar la salida de código con post-condicionales
- Evaluar expresiones booleanas con valores de cadena (trampas de veracidad)
- Elegir entre QUIT y RETURN para una necesidad dada de control de flujo
- Escribir cláusulas de guarda con QUIT:condition en métodos
- Comprender que "" y 0 son ambos falsos pero `"" = 0` es falso
- Determinar qué líneas se ejecutan después de QUIT en un bucle anidado
Recomendaciones de práctica:
- Escribir métodos usando post-condicionales en lugar de bloques IF y verificar el comportamiento
- Crear bucles anidados y probar QUIT vs RETURN en diferentes niveles
- Experimentar con veracidad de varios valores: "", "abc", "0", "1", 0, 1, "5abc"
- Probar `"" = 0`, `0 = ""`, `+"" = 0` para comprender coerción vs comparación
- Escribir un método que use QUIT:condition como cláusula de guarda
- Practicar el patrón de QUIT:errorCondition $$$ERROR(...)
- Probar doble negación ('') para normalizar valores a booleano 0/1