0
\$\begingroup\$

The code snippet below examines a nuget package file (zip file with meta) and extracts all file names referenced inside. The final result should be a Set<string> with all file names. My problem is that the code looks like a nested Linq query in c# and the usage of Seq.iter blocks me to build the Set collection. Can you please give me some kind of advice how to improve the F# code? Am I missing some fundamental concept?

getDependencies nugetPackagesFile
                |> Seq.iter(fun (name,ver) ->
                    name + "." + ver
                    |> fun pkgName ->
                        !! ("./src/packages/*/" + pkgName + ".nupkg")
                        |> Seq.iter(fun pkg ->
                            global.NuGet.ZipPackage(pkg).GetFiles()
                            |> Seq.iter(fun file -> filename file.Path |> printfn "%s")))

Current output:

Elders.Cronus.dll
Elders.Cronus.pdb
Elders.Cronus.DomainModeling.dll
Elders.Cronus.DomainModeling.pdb
log4net.dll
log4net.xml
log4net.dll
log4net.xml
log4net.dll
log4net.xml
log4net.dll
log4net.xml
log4net.dll
log4net.xml
log4net.dll
log4net.xml
log4net.dll
log4net.xml
Elders.Multithreading.Scheduler.dll
Elders.Multithreading.Scheduler.pdb
protobuf-net.dll
protobuf-net.pdb
protobuf-net.xml
protobuf-net.dll
protobuf-net.pdb
protobuf-net.xml
protobuf-net.dll
protobuf-net.pdb
protobuf-net.xml
\$\endgroup\$
  • \$\begingroup\$ Please only state the code purpose in the title \$\endgroup\$ – Caridorc May 16 '15 at 14:06
  • \$\begingroup\$ all f# looks like linq to me! \$\endgroup\$ – Ewan May 17 '15 at 10:45
  • \$\begingroup\$ is ot the GetFiles call which is making this non-functional? maybe if you build the list of files first? \$\endgroup\$ – Ewan May 17 '15 at 10:49
  • \$\begingroup\$ @Ewan the call Seq.iter is what bothers me because it returns unit. I am missing something like Select in Linq \$\endgroup\$ – mynkow May 17 '15 at 17:15
  • \$\begingroup\$ IEnumerable.Select is Seq.map in F# \$\endgroup\$ – CaringDev May 19 '15 at 20:22
2
\$\begingroup\$

Without being able to actually test (I can only guess what getDependencies, nugetPackagesFile, !! and filename are), something along the following should produce your desired set of dependencies:

getDependencies nugetPackagesFile
|> Seq.collect (fun (name, ver) -> 
       !! (sprintf "./src/packages/*/%s.%s.nupkg" name ver)
       |> Seq.collect (fun pkg -> NuGet.ZipPackage(pkg).GetFiles())
       |> Seq.map (fun f -> filename f.Path))
|> Set.ofSeq

or, depending on your taste (kind of DFS vs. BFS)

getDependencies nugetPackagesFile
|> Seq.collect (fun (name, ver) -> !! (sprintf "./src/packages/*/%s.%s.nupkg" name ver))
|> Seq.collect (fun pkg -> NuGet.ZipPackage(pkg).GetFiles())
|> Seq.map (fun f -> filename f.Path)
|> Set.ofSeq

where Seq.collect and map correspond to IEnumerable.SelectMany respectively Select in C#

\$\endgroup\$
0
\$\begingroup\$

Your code is very much imperative. I think this reads better:

for name, ver in getDependencies nugetPackagesFile do
    let pkgName = name + "." + ver
    for pkg in !! ("./src/packages/*/" + pkgName + ".nupkg") do
        for file in global.NuGet.ZipPackage(pkg).GetFiles() do
            filename file.Path |> printfn "%s"
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.