मेरे पास .fsproj (उदा. <PackageReference Include="FSharp.Data" Version="3.0.0-beta4" />) में कुछ निर्भरताओं के साथ एक F# डॉटनेट प्रोजेक्ट है।

अब मैं अपने द्वारा लिखे गए मॉड्यूल में कुछ फ़ंक्शन का परीक्षण करना चाहता हूं, इसलिए मैं fsharpi शुरू करता हूं और अपने मॉड्यूल को #load "Program.fs";; के साथ लोड करने का प्रयास करता हूं।

हालांकि, तब मुझे error FS0039: The type 'CsvProvider' is not defined मिलता है।

मैं अपने मॉड्यूल को सही निर्भरताओं के साथ कैसे लोड कर सकता हूं?

मैंने वर्कअराउंड देखा है जिसमें कुछ अस्पष्ट सिस्टम निर्भर पथ से सभी आवश्यक dll को मैन्युअल रूप से लोड करना शामिल है (उदाहरण के लिए #F# इंटरैक्टिव (FSharpChart.fsx) में एक पैकेज लोड करें, लेकिन मुझे लगता है कि ऐसा करने का एक बेहतर तरीका होना चाहिए।

2
Peter Zeller 9 अगस्त 2018, 19:25

3 जवाब

सबसे बढ़िया उत्तर

ऐसा करने के लिए कुछ विकल्प हैं, उनमें से कोई भी पूर्ण नहीं है।

आयोनाइड

यदि आप आयोनाइड का उपयोग कर रहे हैं, तो आप F# दृश्य में किसी प्रोजेक्ट पर राइट क्लिक कर सकते हैं और "FSI के लिए संदर्भ उत्पन्न करें" चुनें। यह एक F# स्क्रिप्ट बनाएगा जो आपके लिए सभी निर्भरता और प्रोजेक्ट फ़ाइलों को लोड करती है। इसके नीचे अपना टेस्ट कोड लिखें।

इस दृष्टिकोण के नुकसान:

  • जब भी प्रोजेक्ट फ़ाइलें या निर्भरताएँ बदलती हैं, तो आपको हर बार प्रक्रिया को चलाने की आवश्यकता होगी।
  • लागू नहीं है जहां आपके पास वीएस कोड तक पहुंच नहीं है

पाकेट

यदि आप पाकेट का उपयोग कर रहे हैं, तो आप अपनी परियोजना के लिए "लोड स्क्रिप्ट" उत्पन्न कर सकते हैं:

dotnet paket generate-load-scripts

यह ./paket/load में F# स्क्रिप्ट जेनरेट करेगा। प्रत्येक निर्भरता (और इसकी सकर्मक निर्भरता) और प्रत्येक Paket "समूह" के लिए एक लोड स्क्रिप्ट होगी।

यदि आप यह पंक्ति जोड़ते हैं तो यह आपके paket.dependencies के साथ स्वचालित रूप से समन्वयित हो सकता है:

generate_load_scripts: true

देखें: https://fsprojects.github.io/Paket/paket- generate-load-scripts.html

इस दृष्टिकोण के नुकसान:

  • यह वास्तव में आपकी आवश्यकता से अधिक निर्भरताओं को लोड कर सकता है, जिसकी प्रदर्शन लागत होती है
  • आपको #load फ़ाइलों को मैन्युअल रूप से प्रोजेक्ट करना होगा

डॉटनेट + नुगेट

.NET 5 के साथ नया, आप सीधे अपनी fsx फाइलों में Nuget स्ट्रिंग्स लिख सकते हैं। त्वरित स्क्रिप्ट के लिए यह एक बढ़िया विशेषता है!

#r "nuget: FParsec"

// Package with a specific version
// #r "nuget: FParsec,1.1.1"

open FParsec

#load "./Types.fs"

// etc...

इस दृष्टिकोण के नुकसान:

  • यदि आप अपने प्रोजेक्ट कोड के लिए इसका उपयोग कर रहे हैं, तो यह पैकेज संस्करणों को Paket के साथ सिंक नहीं करता है
  • आपको #load फ़ाइलों को मैन्युअल रूप से प्रोजेक्ट करना होगा

एक दिन?

एक आदर्श दुनिया में, हम कुछ ऐसा करने में सक्षम होंगे:

#r "fsproj: ./my-proj.fsproj"

open FParsec

// etc...

इसके लिए यहां एक समस्या है: https://github.com/dotnet/fsharp/issues/ 8764

1
sdgfsdh 12 जिंदा 2021, 19:40

आयातित पुस्तकालयों में कोड तक पहुंच प्राप्त करने के लिए, आपको FSI को उन्हें लोड करने के लिए कहना होगा।

निम्नतम स्तर पर, यह एक #r निर्देश के साथ किया जा सकता है:

#r "./packages/FSharp.Data/lib/whatever/FSharp.Data.dll"

यह अक्सर एकबारगी उद्देश्यों के लिए पर्याप्त होता है।

हालांकि, अगर बहुत सारे संदर्भ हैं, तो आपका आईडीई आमतौर पर आपके लिए इसे स्वचालित कर सकता है। उदाहरण के लिए, विजुअल स्टूडियो में, आप प्रोजेक्ट पर राइट-क्लिक कर सकते हैं और या तो "एफ # इंटरएक्टिव को संदर्भ भेजें" या "संदर्भों के साथ स्क्रिप्ट फ़ाइल जेनरेट करें" (सटीक शब्दों के बारे में निश्चित नहीं) का चयन कर सकते हैं। यदि आपके पास आयनाइड एक्सटेंशन स्थापित है, तो वही विकल्प VSCode में उपलब्ध हैं।

साथ ही, FSI में सीधे समर्थन पैकेज के लिए एक सक्रिय प्रस्ताव+प्रोटोटाइप है - देखें https:/ /github.com/fsharp/fslang-suggestions/issues/542। हालाँकि, यह अभी तक विलय नहीं हुआ है और लगता है कि थोड़ा रुक गया है।

3
Fyodor Soikin 9 अगस्त 2018, 19:45
धन्यवाद। आयोनाइड विशेषता "संदर्भों के साथ स्क्रिप्ट फ़ाइल उत्पन्न करें" सही दिशा में एक कदम है। हालांकि, जब मैं इसे लोड करने का प्रयास करता हूं तो मुझे एक और त्रुटि मिलती है error FS0193: The module/namespace 'System' from compilation unit 'System.Runtime' did not contain the namespace, module or type 'ReadOnlySpan1'। हो सकता है कि मेरा fsharpi संस्करण उस लक्ष्य ढांचे के अनुकूल न हो जिसे मैंने प्रोजेक्ट में कॉन्फ़िगर किया था। अगर मैं इसे netcoreapp2.1 से net472 में बदलता हूं तो मुझे प्रोजेक्ट बनाने की कोशिश करते समय त्रुटि error MSB3644: The reference assembliesfor framework ".NETFramework,Version=v4.7.2" were not found. मिलती है।
 – 
Peter Zeller
9 अगस्त 2018, 20:02
साथ ही: क्या परियोजना संदर्भ उत्पन्न करने के लिए कोई कमांडलाइन टूल है या यह केवल कुछ आईडीई में उपलब्ध है?
 – 
Peter Zeller
9 अगस्त 2018, 20:06
3
यदि आप Paket में स्विच करते हैं, तो fsprojects.github.io/Paket/paket है। -generate-load-scripts.html
 – 
CaringDev
9 अगस्त 2018, 21:06

जैसा कि फ्योडोर के उत्तर पर टिप्पणियों में अनुरोध किया गया है, यहां एक स्क्रिप्ट है जिसका उपयोग मैंने अतीत में #r और #load को F# इंटरएक्टिव में .fsproj लोड करने के लिए आवश्यक निर्देश उत्पन्न करने के लिए किया है:

module References

#r "System.Xml"
#r "System.Xml.Linq"

open System
open System.IO
open System.Linq
open System.Xml.Linq

let inline isNotNull o = o |> isNull |> not

let private getProject path =
    Directory.EnumerateFiles(path, "*.*proj") |> Seq.head |> XDocument.Load    

let generateDlls path =
    let projectFile = getProject path
    let references =
        projectFile.Descendants <| XName.Get("HintPath", "http://schemas.microsoft.com/developer/msbuild/2003")
        |> Seq.filter (fun reference -> reference.Value.ToLower().EndsWith(".dll"))
        |> Seq.filter (fun reference -> reference.Value.StartsWith("$") |> not)
        |> Seq.map (fun reference -> reference.Value)
    let projects =
        projectFile.Descendants <| XName.Get("ProjectReference", "http://schemas.microsoft.com/developer/msbuild/2003")
        |> Seq.map (fun reference -> reference.Elements(XName.Get("Name", "http://schemas.microsoft.com/developer/msbuild/2003")).SingleOrDefault())
        |> Seq.filter (fun nameElement -> nameElement |> isNotNull)
        |> Seq.map (fun nameElement -> nameElement.Value)
        |> Seq.map (fun reference -> sprintf "../%s/bin/debug/%s.dll" reference reference)

    references 
    |> Seq.append projects
    |> Seq.iter (fun reference -> printfn "#r @\"%s\"" reference)

let generateFs path =
    let projectFile = getProject path
    projectFile.Descendants <| XName.Get("Compile", "http://schemas.microsoft.com/developer/msbuild/2003")
    |> Seq.map (fun reference -> reference.Attribute("Include" |> XName.op_Implicit))
    |> Seq.filter (fun reference -> reference |> isNotNull && reference.Value.ToLower().EndsWith("fs"))
    |> Seq.filter (fun reference -> reference.Value.Equals("AssemblyInfo.fs", StringComparison.CurrentCultureIgnoreCase) |> not)
    |> Seq.iter (fun reference -> printfn "#load @\"%s\"" reference.Value)


// Example Usage:
// #load @"GenerateReferences.fsx"
// References.generateDlls __SOURCE_DIRECTORY__
// References.generateFs __SOURCE_DIRECTORY__

मुझे यकीन नहीं है कि यह पूरी तरह से सही है, उदाहरण के लिए, मुझे नहीं लगता कि यह निर्भरता-आदेश सही हो जाता है। हालाँकि, यदि आप इसे बढ़ाना चाहते हैं तो यह एक उचित प्रारंभिक बिंदु होना चाहिए।

0
Aaron M. Eshbach 13 अगस्त 2018, 18:47