Para añadir alguna explicación para el código publicado por ChaosPandion, el problema con las funciones F # como abs
es que se puede trabajar con cualquier tipo numérico. No hay forma de expresar esto simplemente usando los genéricos F # /. NET: las únicas restricciones admitidas son que el parámetro de tipo implementa una determinada interfaz o tiene un constructor, pero no hay restricciones para los tipos numéricos.
Por lo tanto, F # también es compatible con las restricciones estáticas (es el parámetro de tipo ^a
lugar de costumbre 'a
) y éstas se procesan en tiempo de compilación usando procesos en línea (esto también explica por qué la función tiene que ser inline
). Usted puede escribir propia función con restricciones estáticas mediante el uso de las funciones incorporadas de LanguagePrimitives
que contiene muchas funciones útiles que requieren algunas limitaciones:
> let inline half (num: ^a) : ^a =
LanguagePrimitives.DivideByInt< (^a) > num 2
;;
val inline half : ^a -> ^a
when ^a : (static member DivideByInt : ^a * int -> ^a)
> half 42.0;;
val it : float = 21.0
> half 42.0f;;
val it : float32 = 21.0f
Tenga en cuenta que las restricciones se infieren - DivideByInt
requiere que el tipo tiene DivideByInt
miembro, por lo nuestra función requiere lo mismo (y funcionará con tu propio tipo si también tiene este miembro, ¡lo cual es bastante útil!).
Además de esto, la implementación de abs
utiliza dos trucos adicionales que se permiten sólo en la # biblioteca F - especifica código diferente (que se utilizará cuando inlining) para diferentes tipos (utilizando when ^a:int = ....
) y una caja de reserva, que usa el miembro Abs
, por lo que funcionará con cualquier tipo enumerado explícitamente o un tipo con Abs
miembro. Otro truco es la función retype
, que "cambia el tipo", pero no contiene ningún código; el único propósito es hacer que el código revise el tipo, pero esto podría ser muy inseguro, por lo que se usa solo en las bibliotecas F #.
no tiene que comparar X con 0 para encontrar su valor absoluto; puede compararlo con -X. – Simon
@Simon parece un buen punto. PERO, su método no es correcto. Considera x = -2147483648. –
sí, buen punto, aunque sospecho que obtendría la misma excepción al tratar de evaluar -X en ese caso como ABS() debería arrojar de todos modos. – Simon