6
votes

Comment obtenir un nom d'une variable entrant dans une fonction comme paramètre utilisant f #?

Y a-t-il un moyen dans F # Comment obtenir un nom d'une variable transmis dans une fonction?

Exemple: p> xxx pré>

Merci d'avance p>

EDIT: P>

Pourquoi ce code ne fonctionne pas? Il est assorti comme valeur, donc je ne peux pas récupérer le nom "Variable". P>

type Test() =
  let getName (e:Quotations.Expr) =
    match e with
      | Quotations.Patterns.PropertyGet (_, pi, _) -> pi.Name + " property"
      | Quotations.Patterns.Value(a) -> failwith "Value matched"
      | _ -> failwith "other matched"
  member x.plot v = v |> getName |> printfn "%s"

let o = new Test()

let display () =
  let variable = 5.
  o.plot <@ variable @>

let runTheCode fn = fn()

runTheCode display


0 commentaires

3 Réponses :


1
votes

Vous pourriez peut-être y parvenir avec des citations de code: xxx

la fonction fn sera adopté un objet expr objet, lequel Il doit être lancé vers citations.var (qu'il ne s'agira que si vous ne passerez qu'une seule variable) et extraire l'élément d'instance nom


1 commentaires

Bonjour, merci pour votre réponse. Comment puis-je le jeter? Ceci: Laissez Velexpr = <@ Velocity @> Laisser casted = velexpr:?> Citations.var ne fonctionne pas



12
votes

Pour compléter la réponse de Marcelo, oui, vous pouvez utiliser des citations pour cette tâche: xxx pré>

Comme vous pouvez le voir dans le code, les valeurs de définition supérieure de la définition du haut lié (fonctions ou variables) sont implémentées. En tant que propriétés d'une classe. p>

Je ne trouve plus que le lien indique comment un morceau de code F # pourrait être réécrit de manière fonctionnelle avec C #. Voir le code, il devient évident pourquoi vous avez besoin d'un modèle code> Modèle code>. P>

MAINTENANT si vous souhaitez évaluer l'expression aussi, vous devrez installer F # PowerPack et référence fsharp.powerpack.linq code> dans votre projet. P> IT ajoute une méthode evaluntyped code> sur expr code> classe .. p> xxx pré>

Si vous devez le faire pour la méthode d'une instance, voici comment je le ferais: P>

let fn (e:Expr<'T>) = 
  match e with
    | PropertyGet (eo, pi, li) -> pi.Name, (e.EvalUntyped() :?> 'T)
    | _ -> failwith "not a let-bound value"
    
let name, value = fn <@velocity@> //value has type int here
printfn "%s %d" name value


6 commentaires

Salut, merci beaucoup! Une question supplémentaire. Comment puis-je obtenir une valeur hors de l'expression?


Merci! Et une dernière question :) Si le FN est membre d'un type (membre de cette.fn = ...), comment puis-je le faire?


Juste pour être curieux, pourquoi avez-vous besoin de récupérer le nom d'une valeur / membre?


Eh bien, j'ai créé un type matlab qui communique avec Matlab :). Et si vous souhaitez tracer une variable, vous appelez "membre de cette.plot variables", puis j'ai besoin de récupérer des noms des variables et de les envoyer à Matlab. Donc, j'ai besoin de récupérer des noms des paramètres des fonctions des membres comme la parcelle, etc.


Bonjour, j'ai modifié mon premier message, pourriez-vous s'il vous plaît jeter un coup d'oeil à ça? Est-ce la bonne façon, comment poster des questions supplémentaires?


Bonjour, je suis désolé de ne pas penser que c'est faisable. Vous pouvez obtenir le nom d'une valeur à l'aide de citations, mais uniquement pour les valeurs de définition de haut niveau. Donc, vous devrez prendre "Let variable = 5." hors de la fonction d'affichage et mettez-le au niveau supérieur. Oui, si vous avez des questions supplémentaires, vous devrez éditer votre Q. Vous avez fait raison. Mais n'hésitez pas à poser une nouvelle nouvelle question.



0
votes

Basé sur les solutions précédentes, je suis sorti avec une solution plus générique où vous pouvez obtenir le nom des fonctions, des lambdas, des valeurs, des propriétés, des méthodes, des méthodes statiques, des domaines publics, des types d'union:

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns

let cout (s:string)= System.Console.WriteLine (s)

let rec getName exprs =
    let fixDeclaringType (dt:string) =
        match dt with
        | fsi  when fsi.StartsWith("FSI_") -> "Fsi"
        | _ -> dt
    let toStr (xDeclType: System.Type) x = sprintf "%s.%s" (fixDeclaringType xDeclType.Name)  x
    match exprs with
    | Patterns.Call(_, mi, _) -> 
        toStr mi.DeclaringType mi.Name
    | Patterns.Lambda(_, expr) -> 
        getName expr
    | Patterns.PropertyGet (e, pi, li) ->  
        toStr pi.DeclaringType pi.Name
    | Patterns.FieldGet (_, fi) -> 
        toStr fi.DeclaringType fi.Name
    | Patterns.NewUnionCase(uci, _) -> 
        toStr uci.DeclaringType uci.Name
    | expresion -> "unknown_name"


let value = ""
let funcky a = a
let lambdy = fun(x) -> x*2
type WithStatic = 
    | A | B
    with static member StaticMethod a = a
let someIP = System.Net.IPAddress.Parse("10.132.0.48")


getName <@ value @> |> cout
getName <@ funcky @> |> cout
getName <@ lambdy @> |> cout
getName <@ WithStatic.A @> |> cout
getName <@ WithStatic.StaticMethod @> |> cout
getName <@ someIP.MapToIPv4 @> |> cout  
getName <@ System.Net.IPAddress.Parse @> |> cout  
getName <@ System.Net.IPAddress.Broadcast @> |> cout  


0 commentaires