2009-07-18 5 views
2

je les suivantes (travail) bit de code:F # tuyau fourche

let a = 
    File.ReadAllLines("C:\ColorTable.dat") 
    |> Array.filter (fun i -> i.StartsWith(" ")) 
    |> Array.iter (fun i -> 
     Console.WriteLine(@"ColorList.Add({0}, ""{1}"");", extract_num i, extract_col i) 
     f.WriteLine(@"ColorList.Add({0}, ""{1}"");", extract_num i, extract_col i) 
     ) 

Les fonctions extract_num et extract_col appliquent une expression régulière à la ligne du fichier et extraire une partie de celui-ci. Ensuite, j'imprime une chaîne formatée à la console et dans un fichier.

Pour cela, j'écris deux fois la partie formatée. Qu'est-ce qu'une façon plus propre de faire cela? Je pourrais définir une fonction pour accepter extract_num et extract_col qui renvoient la chaîne formatée et l'appellent deux fois, bien sûr, mais, pour le plaisir d'apprendre, quelle est la manière fonctionnelle de faire cela? En dehors de mon esprit, est-ce que je peux envoyer la chaîne formatée à la fois à la console et au fichier avec une sorte de forking?

Merci

Répondre

3

est ici un code ...

open System.IO 
let ComposeTextWriters (tws:TextWriter[]) = 
    { new TextWriter() with 
     override this.Encoding = System.Text.Encoding.Default 
     override this.Write(c:char) = 
      tws |> Array.iter (fun tw -> tw.Write(c)) } 

let data = [(1,1); (2,2); (3,3)] 

[<EntryPoint>] 
let Main(_) = 
    use fileToWrite = new StreamWriter(File.OpenWrite("out.txt")) :> TextWriter 
    let stdout = System.Console.Out 
    let compositeOut = ComposeTextWriters [|fileToWrite;stdout|] 
    data |> List.iter (fun (x,y) -> 
     compositeOut.WriteLine("{0}: '{1}'", x, y)) 
    0 

Je ne sais pas si cela est une excellente façon de le faire, mais il semble fonctionner. ComposeTextWriters prend en entrée un tableau de TextWriters et renvoie un nouveau TextWriter qui écrit toutes les sorties sur chacun d'entre eux. Est-ce le genre de chose que vous cherchez?

0

Je prendrais en compte votre logique pour extraire et imprimer des valeurs dans leurs propres fonctions. En outre, votre a sera toujours unit - Je suppose que vous voudrez peut-être sauvegarder les valeurs que vous produisez ailleurs. Je pourrais réécrire votre code quelque chose comme ceci:

let a = 
    let extract_values s = (extract_num s),(extract_col s) 
    let print_values (num,col) = 
     let msg = sprintf "ColorList.Add(%A \"%A\")" num col 
     Console.WriteLine(msg) 
     f.WriteLine(msg) 
     num,col 
    File.ReadAllLines("C:\ColorTable.dat") 
    |> Array.filter (fun s -> s.StartsWith(" ")) 
    |> Array.map extract_values 
    |> Array.map print_values 

a serait un tableau des num,col paires.

Si vous ne se soucient pas réellement sur les valeurs extraites, vous pouvez retourner à la place une chaîne et passer directement dans print:

let extract_values s = 
    sprintf "ColorList.Add(%A \"%A\")" (extract_num s) (extract_col s) 
let print_values (s : string) = 
    Console.WriteLine(s) 
    f.WriteLine(s) 
File.ReadAllLines("C:\ColorTable.dat") 
|> Array.filter (fun s -> s.StartsWith(" ")) 
|> Array.map extract_values 
|> Array.iter print_values 
1

Si je comprends bien la question, le « tube de fourche » vous « re demander pourrait ressembler à

let fork f g x = (f x); (g x); 

Et vous pouvez l'utiliser comme ceci:

let extract i = sprintf "ColorList.Add(%A \"%A\")" (extract_num i) (extract_col i) 

File.ReadAllLines("C:\ColorTable.dat") 
    |> Array.filter (fun s -> s.StartsWith(" ")) 
    |> Array.iter (extract >> fork Console.WriteLine f.WriteLine); 

(Basé sur le code de la réponse de dahlbyk)