Hi all,
Evan floated an idea a while ago that I've now prototyped and would like your opinion on before it goes any further: records — user‑defined record types that generate their own blocks, and are nothing more than dictionaries at runtime.
The problem
Dictionaries are how we build "a thing with named parts" today, and they work — but the key is free text at every use site. "adress" and "address" are both fine in the editor; the mistake only shows up on the phone as a "not found" value, and often much later. The forum has been asking for a way around this for years:
- Create a structure or class — "with lists I don't have the names of the values… as for the dictionary, I don't like the not found"
- [Feature requests] – Language — structs / records in the wish list
- Warning notice at dictionary (add a pair) and mit‑cml/appinventor-sources #4056 / #4060 — the duplicate‑key checker only exists because keys are strings we can't reason about
- ABG's point in the original dictionaries RFC: a
{"user":"ABG","score":0}in a Do It bubble tells you nothing about what it is
The idea
One new definition block per screen:
define record Person — fields givenName, surname, born (with defaults; a gear to add/remove/rename fields)
Once a record is defined, its blocks appear in the drawer, exactly like a procedure's call block appears once you define the procedure:
make Person— one socket per field, defaults filled inPerson.surname of …/set Person.born of … to …— field names are dropdowns, not textis … a Person?/as Person …— recognise a record that came back from TinyDB, Web or a list
Rename a field in the definition and every block follows; delete a field and the blocks that use it get a warning. Typeblocking works (Person. lists the fields). The address book from the tutorials, side by side:
dictionary version
record version
Why it's cheap
A record is a dictionary with a "@type" pair naming it — the JSON‑LD convention. Everything the blocks generate uses the dictionary primitives the runtime already has (make-yail-dictionary, yail-dictionary-lookup, yail-dictionary-set-pair, yail-dictionary?), so:
- no Companion update, no runtime change, Android and iOS alike;
- every dictionary block still works on a record (it is one), and every list/dictionary tool, TinyDB, Web and JSON round‑trip already handles it;
- a project that uses records opens fine in any build that has the blocks; the
.aiais just blocks.
The only things that live in the editor are the definition, the dropdowns and the warnings — which is exactly where the errors are today.
Where I'd like your thoughts
- How many blocks? The prototype has six (
define,make,get,set,is a,as). The minimal version is two:defineplus afield ▾ of Person ▾dropdown block that plugs into the existing dictionary blocks — typo‑proof keys and rename for the smallest change, but nomake Personwith a socket per field. Which would you rather teach? - The name. "record" vs "struct", "object", "type", "shape"… For beginners, is record the right word?
- Strictness. By default a getter on a dictionary that lacks the field is a runtime error (not a silent default); the
"@type"tag is only checked if you tick strict on the definition. Right default? - Scope. Definitions are per screen, like procedures. Should they be project‑wide?
- Anything you'd have wanted this for that the design doesn't cover.
The design doc
The full proposal — problem statement, the blocks, the checks in the editor, the generated YAIL, versioning and the implementation plan — is here, open for comments:
Records in App Inventor — implementation proposal
Please leave your review as comments in the doc (anyone with the link can comment) — that keeps the discussion next to the design it's about — and use this thread for the bigger questions above. The prototype is on a branch (records, off ucr); happy to put up a test build if there's interest.
Thanks — and thanks to Evan for the idea.
Preet




