Iced filter_map Column(...) usage

I am trying to build a Column based on a subset of iterated strings based on a filter:

       Column(auth.aka_iter().filter_map(|akaid| {
            match &lib.get_author(akaid) {
                None => None,
                Some(auth) => Some(row![
                    button(auth.name.as_str())
                        .on_press(|| Message::AuthorMessages(AuthorMessage::ToAKA(
                            *akaid,
                            auth.name.clone()
                        )))
                        .width(Length::FillPortion(9)),
                    button("del")
                        .on_press(|| Message::AuthorMessages(AuthorMessage::DeleteAka(*akaid)))
                        .style(iced::widget::button::danger)
                        .width(Length::FillPortion(1)),
                ].into()),
            }
        })),

Th compiler points to the row![...] call, (marking teh opening and closing '[' ']'and says:

error[E0308]: mismatched types
... above code segment ...
expected `Element<'_, {closure@...}, _, _>`, found `Element<'_, {closure@...}, ..., _>`
    |
    = note: expected struct `iced_core::element::Element<'_, {closure@src\library_window\author_gui.rs:127:35: 127:37}, _, _>`
               found struct `iced_core::element::Element<'_, {closure@src\library_window\author_gui.rs:133:35: 133:37}, Theme, _>`
    = note: no two closures, even if identical, have the same type
    = help: consider boxing your closure and/or using it as a trait object
    = note: this error originates in the macro `row` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0423]: expected function, tuple struct or tuple variant, found struct `Column`
    |
   ::: C:\Users\jmh\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\iced_widget-0.14.2\src\column.rs:35:1
    |
 35 |   pub struct Column<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer>
    |   -------------------------------------------------------------------------------- `Column` defined here
   --> src\library_window\author_gui.rs:122:9
    |
122 | /         Column(auth.aka_iter().filter_map(|akaid| {
123 | |             match &lib.get_author(akaid) {
124 | |                 None => None,
125 | |                 Some(auth) => Some(row![
...   |
138 | |         })),
    | |___________^
    |
   ::: C:\Users\jmh\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\iced_widget-0.14.2\src\helpers.rs:480:1
    |
480 | / pub fn column<'a, Message, Theme, Renderer>(
481 | |     children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
482 | | ) -> Column<'a, Message, Theme, Renderer>
483 | | where
484 | |     Renderer: core::Renderer,
    | |_____________________________- similarly named function `column` defined here
    |

I don't even understand the error enough to ask a useful question.
Thank you,
Joel

Guess from reading the docs: Try on_press_with instead of on_press.

And my follow-up guess to my guess is: If you get borrow checker errors about the closures not living long enough, try creating the messages first and using on_press.

                Some(auth) => {
                    let name = Message::AuthorMessages(...);
                    let del = Message::AuthorMessages(...);
                    Some(row![
                         button(auth.name.as_str()).on_press(name).width(...),
                         button("del").on_press(del).width(...),
                    ])
                }

I tried unwinding the iterators to see if those were the problem. Nope. Code:

let mut innercol = column![];

    for akaid in auth.aka_iter().filter(|akaid| {
        lib.get_author(akaid).is_some() && (guistate.filter.is_empty() || !lib.get_author(akaid).unwrap().name.contains(&guistate.filter)) 
    }) {
	innercol.push(row![
            button(auth.name.as_str())
                .on_press(|| Message::AuthorMessages(AuthorMessage::ToAKA(
                    *akaid,
                    auth.name.clone()
                )))
                .width(Length::FillPortion(9)),
            button("del")
                .on_press(|| Message::AuthorMessages(AuthorMessage::DeleteAka(*akaid)))
                .style(iced::widget::button::danger)
                .width(Length::FillPortion(1)),
        ]);
    }

Error:

error[E0308]: mismatched types
   --> src\library_window\author_gui.rs:117:16
    |
117 |       innercol.push(row![
    |  ___________________^
118 | |             button(auth.name.as_str())
119 | |                 .on_press(|| Message::AuthorMessages(AuthorMessage::ToAKA(
    | |                           -- the expected closure
120 | |                     *akaid,
...   |
125 | |                 .on_press(|| Message::AuthorMessages(AuthorMessage::DeleteAka(*akaid)))
    | |                           -- the found closure
126 | |                 .style(iced::widget::button::danger)
127 | |                 .width(Length::FillPortion(1)),
128 | |         ]);
    | |_________^ expected `Element<'_, {closure@...}, _, _>`, found `Element<'_, {closure@...}, ..., _>`
    |
    = note: expected struct `iced_core::element::Element<'_, {closure@src\library_window\author_gui.rs:119:27: 119:29}, _, _>`
               found struct `iced_core::element::Element<'_, {closure@src\library_window\author_gui.rs:125:27: 125:29}, Theme, _>`
    = note: no two closures, even if identical, have the same type
    = help: consider boxing your closure and/or using it as a trait object
    = note: this error originates in the macro `row` (in Nightly builds, run with -Z macro-backtrace for more info)

You're still calling on_press and not on_press_with there.

To elaborate on my guess,

  • on_press takes a parameter of the Button<..> called Message. But for ease of conversation, let's pretend the parameter was named Msg.

  • You're creating some enums named Message, so probably the type parameter called Msg is meant to be Message in your Button<..>s.

  • But you're not passing in a Message, you're passing in closures.

    • (The compiler tries to make them all the same type because all the Msgs need to be the same in the row!. That's the source of the compiler error about closures having different types.)
  • So you probably meant to use on_press_with, which takes a closure that returns a Msg.

Turns out I don't need the closures in on_press. So I am removing them. And that is helping the problems. Thanks. Getting from where it was pointing to the actual problem has been a little interesting. So it goes.