2010-12-10 50 views
11

Avec F #, je crois comprendre que vous pouvez utiliser le mot-clé inline pour effectuer une spécialisation de type sur le site d'appel. C'est ::Comment fonctionne F # en ligne?

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

que ^a ou Contraint ^b doit avoir un membre statique comme op_Addition, ou l'un des construit en primitives, qui peut être utilisé pour combler le vide. Donc, si vous avez une méthode qui a un + et que vous passez un int et un court comme paramètres, elle déballe + d'une instruction pour utiliser la primitive intégrée pour int, et si vous passez un float et un octet il utilise l'opcode d'ajout de primitive float.

Comment cela se fait-il exactement au moment de la compilation? Comment pouvez-vous avoir une méthode dans le CLR qui permute l'opcode ou la méthode qu'il utilise en fonction du type?

Est-ce que ce comportement est possible avec Reflection.Emit? Je comprends que l'inline est effectuée sur le site d'appel, est-ce que cela signifie que le code ne fonctionne pas avec C#?

+0

Je ne sais pas vraiment beaucoup sur les internes, mais il ressemble au code source F # définissant l'opérateur '+' (C: \ Program Files (x86) \ FSharp-2.0.0.0 \ source \ fsharp \ FSharp .Core \ prim-types.fs ligne 3527) commute les types d'arguments au type de compilation et émet directement le code IL. – Juliet

Répondre

8

Comme suggéré par inline, le code est inséré sur le site d'appel. À chaque site d'appel, vous connaissez le paramètre de type concret ^T, de sorte que le code spécifique pour ce type y est inséré. Ceci est fait par le compilateur F #, vous ne pouvez pas le faire facilement dans un autre contexte (comme C# ou Ref.Emit).

La bibliothèque F # possède certaines fonctions en ligne qui peuvent encore être appelées par d'autres langages, le temps d'exécution de ces implémentations étant une répartition dynamique basée sur le type d'exécution, voir par ex. le code pour AdditionDynamic dans prim-types.fs dans le code de la bibliothèque F # Core pour avoir une idée.

+0

Donc, vous dites que c'est fondamentalement un truc de compilateur complexe? Si j'appelle un 'FSharpFunc <,>' de C# aurais-je le comportement désiré? –

+2

Toute instance du type 'FSharpFunc' (ou en fait la plupart des types) n'est pas (et ne peut pas) être' inline'. 'inline' s'applique aux méthodes et fonctions, et seulement une poignée d'entre elles dans la bibliothèque F #. La plupart des choses peuvent être appelées fine depuis C#, mais quelques fonctions F # 'inline' qui ne supportent pas l'invocation dynamique (comme' sin') ne peuvent être appelées que depuis F #, car le compilateur F # doit aligner le code sur le site d'appel. – Brian