No. I would not use a function in a query. That's what you're doing now and that is what is slow. I would create a procedure in a module and call it from a form. The procedure would open a query that sorted the table in the order that would allow it to be concatenated. The loop would read through the query, record by record, when the "id" changed, it would write the previous record and start concatenating in a new one. Your query would then join to the temp table.
But, I wouldn't actually do this at all unless the client insisted that the concatenated values were somehow critical to whatever he was doing with this data. I'm just giving you a solution that will probably be more efficient than doing the concatenation in a query. I don't know how many rows you have but if you have a thousand rows, the function was opening and closing the recordset 1000 times. That is a lot of overhead. If your one side table is small and your many-side table is also small, then doing this with the concat function will be slightly sluggish but not annoyingly so.
I haven't looked at the concat function in a long time but the code I'm suggesting is essentially the same logic with one difference, instead of taking in the ID of the 1-side record and reading only the many-side table looking for records with that ID, you are reading the entire many-side table, SORTED (this is critical) and concatenating the values for ALL ids and saving each set as a record in a temp table.