Funciones insertadas

Las funciones insertadas son funciones integradas directamente en el código de llamada.

Usar funciones insertadas

Cuando se usan parámetros de tipo estático, las funciones parametrizadas por parámetros de tipo deben estar insertadas. Esto garantiza que el compilador pueda resolver estos parámetros de tipo. Cuando se usan parámetros de tipo genérico normales, no hay ninguna restricción de este tipo.

Aparte de habilitar el uso de restricciones miembro, las funciones insertadas pueden resultar útiles para optimizar el código. Sin embargo, el uso excesivo de funciones insertadas puede hacer que el código sea menos resistente a los cambios en las optimizaciones del compilador y la implementación de funciones de biblioteca. Por este motivo, debes evitar el uso de funciones insertadas para la optimización a menos que hayas probado todas las demás técnicas de optimización. La creación de una función o un método insertado a veces puede mejorar el rendimiento, pero eso no siempre es el caso. Por lo tanto, también debes usar medidas de rendimiento para comprobar que, de hecho, cualquier función determinada insertada tiene un efecto positivo.

El inline modificador se puede aplicar a funciones en el nivel superior, en el nivel de módulo o en el nivel de método de una clase.

En el ejemplo de código siguiente se muestra una función insertada en el nivel superior, un método de instancia en línea y un método estático insertado.

let inline increment x = x + 1
type WrapInt32() =
    member inline this.incrementByOne(x) = x + 1
    static member inline Increment(x) = x + 1

Funciones insertadas y inferencia de tipos

La presencia de inline afecta a la inferencia de tipos. Esto se debe a que las funciones insertadas pueden tener parámetros de tipo resueltos estáticamente, mientras que las funciones no insertadas no pueden. En el ejemplo de código siguiente se muestra un caso en inline el que resulta útil porque se usa una función que tiene un parámetro de tipo resuelto estáticamente, el float operador de conversión.

let inline printAsFloatingPoint number =
    printfn "%f" (float number)

Sin el modificador inline, la inferencia de tipos obliga a la función a tomar un tipo específico, en este caso int. Pero con el modificador inline, la función también se deduce que tiene un parámetro de tipo resuelto estáticamente. Con el modificador inline, el tipo se deduce como el siguiente:

^a -> unit when ^a : (static member op_Explicit : ^a -> float)

Esto significa que la función acepta cualquier tipo que admita una conversión a float.

InlineIfLambda

El compilador de F# incluye un optimizador que realiza la inserción de código. El atributo InlineIfLambda permite que el código indique opcionalmente que, si un argumento se determina como una función lambda, ese argumento siempre debe insertarse en los sitios de llamada. Para obtener más información, consulta F# RFC FS-1098.

Por ejemplo, considera la siguiente función iterateTwice para atravesar una matriz:

let inline iterateTwice ([<InlineIfLambda>] action) (array: 'T[]) =
    for i = 0 to array.Length-1 do
        action array[i]
    for i = 0 to array.Length-1 do
        action array[i]

Si el sitio de llamada es:

let arr = [| 1.. 100 |]
let mutable sum = 0
arr  |> iterateTwice (fun x ->
    sum <- sum + x)

Después de insertar y otras optimizaciones, el código se convierte en:

let arr = [| 1..100 |]
let mutable sum = 0
for i = 0 to arr.Length - 1 do
    sum <- sum + arr[i] 
for i = 0 to arr.Length - 1 do
    sum <- sum + arr[i] 

Esta optimización se aplica independientemente del tamaño de la expresión lambda implicada. Esta característica también se puede usar para implementar la anulación de bucles y transformaciones similares de forma más confiable.

Se puede activar una advertencia de participación (/warnon:3517 o propiedad <WarnOn>3517</WarnOn>) para indicar lugares en el código donde InlineIfLambda los argumentos no están enlazados a expresiones lambda en los sitios de llamada. En situaciones normales, esta advertencia no debe estar habilitada. Sin embargo, en ciertos tipos de programación de alto rendimiento, puede ser útil asegurarse de que todo el código está insertado y acoplado.

Vea también