How do you write reusable packages?

The import function in the Lua SDK has the restriction: "All files imported from main.lua (and imported from files imported from main.lua, and so on) are compiled into a single pdz file, and import runs the code from the file only once. A second import call from anywhere in the pdz will do nothing."

So if you create a helper package which returns an object or a table of functions, you can only import it in one file—the second place you try to import it, it will be nil. This is a problem for how I like to write small packages which return their contents (instead of making them globals).

Potential workarounds:

  1. Write my own cachedImport function which stores already-imported packages and returns them. It doesn't work because import requires a string literal; you can't pass a variable as the path. (But I would support this behavior for import as an SDK improvement.)
  2. Have my packages expose global functions. I could do this but I don't like it.
  3. Import all packages in one central place, store them in a global table, and access that table instead of calling import elsewhere. It's gross, but I'll probably do this.

How do you structure your packages?

1 Like

I usually have some global table and import them in main.lua. Then in whatever scripts I need them, I can declare a local const (underscore) to use it without needing to access globals every time.

I’ve never used lua in any other project though, so this might just be the playdate way.

Don't miss this trick from Shaun

And Nino's custom import trick

2 Likes

Thanks Gamma and Matt.

Shaun's trick isn't necessary anymore—in SDK version 2.3.0 this works just fine:

local pkg = import("pkg")

...as long as you only do it once for that package in the whole project.

Nino's trick is really neat. However using playdate.file.run instead of import has the downside (which he notes) of incurring a file read during runtime. I'll probably stick with import for now, but it's good to know about.

1 Like