2009-06-02 12 views
5

Estoy tratando de trabajar a través de un ejemplo en el Experto F #, que se basa en v1.9.2, pero los lanzamientos de CTP después de que han cambiado lo suficiente para que algunos de ellos ni siquiera compilar más.experto rastreador ejemplo F # Web

Tengo algunos problemas con la lista 13-13. He aquí el fragmento de la definición urlCollector objeto:

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)) 

Estoy compilando con la versión 1.9.6.16 , y el compilador se queja de esta manera:

  1. construcción incompleta estructurada en o antes de este punto en expresión [después de la última paren]
  2. error en la expresión de retorno para este 'let'. Posible indentación incorrecta [se refiere a la definición de let waitForUrl]

¿Alguien puede detectar qué está mal aquí?

Respuesta

3

Parece que la última línea debe tener 4 espacios sin sangrar.

EDITAR: en realidad, parece que hay más cosas sucediendo aquí. Asumiendo que esto es la misma muestra que here, entonces aquí es una versión que acaba de modificar para estar en sintonía con el lanzamiento 1.9.6.16:

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

convenido ... a veces bloquean definiciones de sangrado es más oscura que útiles. He adquirido el hábito de agregar tokens de inicio/final para establecer dónde comienzan y terminan los bloques largos o profundamente anidados. No son necesarios en la sintaxis #light, pero aún están disponibles. – flatline

+0

Gracias - Voy a intentarlo. Supongo que una cosa que fue engañosa, y muy desafortunada dada la importancia de la sangría adecuada, fue que el ejemplo en el libro abarca un salto de página, por lo que es difícil decir dónde se alinea la sangría. –

+0

Esto se rompe de nuevo :( – Benjol