fn get_links(link_nodes: Select) -> Option<String> {

        let mut rel_permalink: Option<String> = for node in link_nodes {
            link = String::from(node.value().attr("href")?);

            return Some(link);
        };

        Some(rel_permalink)
    }

This is what I’m trying to do, and I’ve been stuck with this code for an hour, I simply don’t know how to put this function togheter… Essentially I would like to take some link_nodes and just return the link String, but I’m stuck in the use of Option with the ? operator… Pheraps trying to write it with match would clear things out(?)

Also I come from JavaScript in which expressions do not have their own scope, meaning I’m having troubles to understand how to get out a variable from a for loop, should I initialize the rel_permalink variable as the for loop result?

This are the errors i get:

error[E0308]: mismatched types
  --> src/main.rs:55:49
   |
55 |           let mut rel_permalink: Option<String> = for node in link_nodes {
   |  _________________________________________________^
56 | |             link = String::from(node.value().attr("href")?);
57 | |
58 | |             return Some(link);
59 | |         };
   | |_________^ expected `Option<String>`, found `()`
   |
   = note:   expected enum `Option<String>`
           found unit type `()`
note: the function expects a value to always be returned, but loops might run zero times
  --> src/main.rs:55:49
   |
55 |         let mut rel_permalink: Option<String> = for node in link_nodes {
   |                                                 ^^^^^^^^^^^^^^^^^^^^^^ this might have zero elements to iterate on
56 |             link = String::from(node.value().attr("href")?);
   |                                                          - if the loop doesn't execute, this value would never get returned
57 |
58 |             return Some(link);
   |             ----------------- if the loop doesn't execute, this value would never get returned
   = help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility
  • gigapixel@mastodontti.fi
    link
    fedilink
    arrow-up
    1
    ·
    5 hours ago

    @dontblink It’s a little unclear what you want to do. It looks like Select implements into iterator. As far as I can parse your code you want to get the first node with a href element. In that case you should do:

    link\_nodes.into\_iter().filter\_map(|node| node.value().attr("href")).map(String::from).next()  
    
    • gigapixel@mastodontti.fi
      link
      fedilink
      arrow-up
      1
      ·
      5 hours ago

      @dontblink Here’s a little explanation for the methods
      - into\_iter : converts Select into an iterator (a for loop does this implicitly)
      - filter\_map: takes an iterator and constructs an iterator from an Fn(T) -\> Option\<S\> where the emitted elements are the elements for which applying the function/closure is Some
      - next: takes the next element of the iterator as an Option.

        • gigapixel@mastodontti.fi
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          5 hours ago

          @dontblink If you really want to do it in a loop, you could do something like

          fn get\_links(link\_nodes: Select) -\> Option\<String\> {  
           let mut rel\_permalink: Option\<String\> = None;  
           for node in link\_nodes {  
           if let Some(link) = node.value().attr("href")? {  
           rel\_permalink = Some(String::from(link));  
           break  
           }  
           };  
           rel\_permalink  
          }  
          

          That said, your function name suggest you want _all_ links, so some kind of collection of links. Is this the case?