In the example code, get_user_projects doesn't seem to be explicitly called.
Not in the Perl. But in the template, the line [% FOREACH project IN worklist(me.id) %] calls worklist as a function with the appropriate ID as its argument.
I would assume that in your code, if you don't change to 'frames' => list_frames() (as already suggested), then you would need to call the frames as a function rather than treating it as a variable: probably like [% FOREACH frame IN frames() %] (untested)
(But it seems to me that you shouldn't need to call a function from the template, unless the data will change based on some parameter from the template, like the me.id argument in the tutorial example. Since you're not feeding anything back to the function, why not just define frames as the arrayref rather than the coderef?)