2010-12-10 18 views
11

Con F # entiendo que puede usar la palabra clave en línea para realizar una especialización de tipo en el sitio de llamadas. Es decir ::¿Cómo funciona F # inline?

val inline (+) : ^a -> ^b -> ^c 
     when (^a or ^b) : (static member (+) : ^a * ^b -> ^c) 

Restringe que ^a o ^b debe tener un miembro estático como op_Addition, o uno de los incorporados en las primitivas, que se puede utilizar para rellenar el hueco.

Así que si tienes un método que tiene un + y pasas un int y un short como parámetros, desenvuelve + en una instrucción para usar la primitiva incorporada para int, y si pasas en un flotante y un byte utiliza el código de operación de suma primitiva flotante.

¿Cómo se hace esto exactamente en tiempo de compilación? ¿Cómo se puede tener un método en el CLR que cambie qué código de operación o método utiliza en función del tipo?

¿Es posible este comportamiento con Reflection.Emit? Entiendo que la alineación se realiza en el sitio de llamada, ¿eso significa que el código no funciona con C#?

+0

No sé mucho sobre las partes internas, pero parece que el código fuente F # define el operador '+' (C: \ Archivos de programa (x86) \ FSharp-2.0.0.0 \ source \ fsharp \ FSharp .Core \ prim-types.fs línea 3527) activa los tipos de argumento en el tipo de compilación y emite código IL directamente. – Juliet

Respuesta

8

Según lo sugerido por inline, el código está subrayado en el sitio de la llamada. En cada sitio de llamada, conoce el parámetro de tipo concreto ^T, por lo que el código específico para ese tipo se inserta allí.

Esto se hace mediante el compilador F #, no se puede hacer fácilmente en otro contexto (como C# o Ref.Emit).

La biblioteca F # tiene algunas funciones en línea que aún pueden ser llamadas por otros idiomas, el tiempo de ejecución para esas implementaciones hace el despacho dinámico basado en el tipo de tiempo de ejecución, ver p. el código para AdditionDynamic en prim-types.fs en el código de la biblioteca F # Core para tener una idea.

+0

¿Entonces estás diciendo que básicamente es un elaborado truco de compilación? Si llamo a 'FSharpFunc <,> 'desde C#, ¿obtendría el comportamiento deseado? –

+2

Cualquier instancia del tipo 'FSharpFunc' (o de hecho la mayoría de los tipos) no es (y no puede) ser' en línea'. 'inline' se aplica a métodos y funciones, y solo un puñado de ellos en la biblioteca F #. La mayoría de las cosas se pueden llamar finas desde C#, pero algunas funciones F # 'en línea' que no admiten la invocación dinámica (como' sin') solo pueden invocarse desde F #, ya que el compilador F # debe alinear el código en el sitio de llamadas. – Brian