How to pass extra arguments to typeahead handler


I’ve got a use case where I want to pass a list into the typeahead handler function:

def get_schema():
    bikeshares = get_gbfs_list()

    def search_bikeshares(pattern):
        return search(bikeshares, pattern)
    return schema.Schema(
        version = "1",
        fields = [
                id = "company",
                name = "Search providers",
                desc = "A list of bikeshare providers that match search.",
                icon = "bicycle",
                handler = search_bikeshares,

The bikeshares = get_gbfs_list() fetches a list of items via an API so I just want to run this once. Then the typeahead handler should optimally be provided this list and search using a simple for loop (or just the built in filter in the typeahead module).

As you can see from my example code I’ve tried to use a nested function with a closure over the list of bike shares, but I just get an error:

2022/07/24 13:01:15 error loading applet: failed to load applet: parsing schema for apps/bikeshare/ field 0 references non-existent handler "search_bikeshares"

I’ve also tried using a lambda function with much the same result. So this seems to not work in go starlark. I could fetch and assign the list in the main scope of the module, that is outside the get_schema() call. But then I believe the list will be fetched every time the Pixlet app is run because the API call would run every time the module is loaded.

Any advice would be greatly appreciated.

As a temporary solution I’ve opted for using the cache module with a TTL of 24 hours. On each user input pattern the bikeshare CSV can then first be looked up in the cache, and if there is simply parsed. If not in cache the handler function fetches the CSV from the external URL and caches it. So:

def search(pattern):
    bikeshare_csv = cache.get("bikeshare_csv")
    if bikeshare_csv == None:
        bikeshare_csv = get_gbfs_csv()
        cache.set("bikeshare_csv", bikeshare_csv, ttl_seconds=60*60*24)
    bikeshares =  csv.read_all(
        source = bikeshare_csv,
    return [bikeshare_to_option(bikeshare) for bikeshare in bikeshares]