2009-06-02 19 views
5

Ich versuche, in Expert F durch ein Beispiel zu arbeiten #, die auf v1.9.2 basiert, aber die CTP Versionen nach, dass genug geändert, dass einige von ihnen nicht einmal kompilieren Sie mehr.Expert F # Web-Crawler Beispiel

Ich habe Probleme mit Listing 13-13. Hier ist der Ausschnitt aus der urlCollector Objektdefinition:

let urlCollector = 
    MailboxProcessor.Start(fun self -> 
     let rec waitForUrl (visited : Set<string>) = 
      async { if visited.Count < limit then 
         let! url = self.Receive() 
         if not (visited.Contains(url)) then 
          do! Async.Start 
           (async { let! links = collectLinks url 
             for link in links do 
             do self <-- link }) 

         return! waitForUrl(visited.Add(url)) } 

      waitForUrl(Set.Empty)) 

ich mit Version bin Kompilieren 1.9.6.16, und der Compiler beschwert sich so:

  1. unvollständige strukturierte Konstrukt an oder vor diesem Punkt in ausdruck [nach dem letzten paren]
  2. Fehler im Rückgabeausdruck für dieses 'let'. Mögliche falsche Einrückung [bezieht sich auf die Definition waitForUrl]

Kann jemand hier was schief gehen?

Antwort

3

Es sieht so aus, als ob die letzte Zeile 4 Leerzeichen enthalten muss.

EDIT: eigentlich sieht es so aus, als gäbe es hier mehr. Unter der Annahme, dies ist die gleiche Probe wie here, dann ist hier eine Version, die ich geändert nur mit der 1.9.6.16 Release synchron zu sein:

open System.Collections.Generic 
open System.Net 
open System.IO 
open System.Threading 
open System.Text.RegularExpressions 

let limit = 10  

let linkPat = "href=\s*\"[^\"h]*(http://[^&\"]*)\"" 
let getLinks (txt:string) = 
    [ for m in Regex.Matches(txt,linkPat) -> m.Groups.Item(1).Value ] 

let (<--) (mp: MailboxProcessor<_>) x = mp.Post(x) 

// A type that helps limit the number of active web requests 
type RequestGate(n:int) = 
    let semaphore = new Semaphore(initialCount=n,maximumCount=n) 
    member x.AcquireAsync(?timeout) = 
     async { let! ok = semaphore.AsyncWaitOne(?millisecondsTimeout=timeout) 
       if ok then 
        return 
        { new System.IDisposable with 
         member x.Dispose() = 
          semaphore.Release() |> ignore } 
       else 
        return! failwith "couldn't acquire a semaphore" } 

// Gate the number of active web requests 
let webRequestGate = RequestGate(5) 

// Fetch the URL, and post the results to the urlCollector. 
let collectLinks (url:string) = 
    async { // An Async web request with a global gate 
      let! html = 
       async { // Acquire an entry in the webRequestGate. Release 
         // it when 'holder' goes out of scope 
         use! holder = webRequestGate.AcquireAsync() 

         // Wait for the WebResponse 
         let req = WebRequest.Create(url,Timeout=5) 

         use! response = req.AsyncGetResponse() 

         // Get the response stream 
         use reader = new StreamReader(
          response.GetResponseStream()) 

         // Read the response stream 
         return! reader.AsyncReadToEnd() } 

      // Compute the links, synchronously 
      let links = getLinks html 

      // Report, synchronously 
      do printfn "finished reading %s, got %d links" 
        url (List.length links) 

      // We're done 
      return links } 

let urlCollector = 
    MailboxProcessor.Start(fun self -> 
     let rec waitForUrl (visited : Set<string>) = 
      async { if visited.Count < limit then 
         let! url = self.Receive() 
         if not (visited.Contains(url)) then 
          Async.Start 
           (async { let! links = collectLinks url 
             for link in links do 
              do self <-- link }) 
         return! waitForUrl(visited.Add(url)) } 

     waitForUrl(Set.Empty)) 

urlCollector <-- "http://news.google.com" 
// wait for keypress to end program 
System.Console.ReadKey() |> ignore 
+0

Vereinbarte ... manchmal Definition Block durch Einrücken Unbekannter als hilfreich ist. Ich habe mir angewöhnt, Anfangs-/Ende-Token hinzuzufügen, um auszulösen, wo lange oder tief verschachtelte Blöcke beginnen und enden. Sie werden nicht in der #light-Syntax benötigt, sind aber weiterhin verfügbar. – flatline

+0

Danke - ich werde es versuchen. Ich denke, eine Sache, die irreführend war, und die unglückliche Tatsache, dass die richtige Einrückung wichtig ist, bestand darin, dass das Beispiel im Buch einen Seitenumbruch umfasst. Daher ist es schwierig zu sagen, wo die Einrückung ausgerichtet ist. –

+0

Dies ist wieder gebrochen :( – Benjol