API Notation Updates

A few years ago I created an API notation to use with software specification documents: Back then I was working in a team that relied heavily on software specifications, and we were maintaining projects in objective-c, ruby, and javascript, so the notation emerged out of the need to communicate the public APIs in a way that was generic enough to make implementation in any language simple, while concise enough to avoid integration issues.

For example, I could use it to describe the library I use to build this blog[1]

// Library to generate an ephemeral html blog with a gemini archive
Blog
  -max_posts 
  -posts_directory 
  -archive_directory 
  -static_directory 
  -templates_directory 
  -remote_config 
  #add(post_location ) => Promise
  #update(post_location ) => Promise
  #publish(host ) => Promise
  #publish_archive(host ) => Promise
  #add_remote(remote ) => Promise
  #remove_remote() => Promise
  #sync_down() => Promise
  #sync_up() => Promise
  #generate() => Promise

=> [1] A Javascript implementation of that API

I had been using it unchanged for almost ten years, but recently decided to drop a specific symbol for callbacks, and instead add a "Throws" symbol #>. You can see the definition here, or in its home page[2]

// Anything after two forward slashes is a comment
NameOfClass.WithPossibleNamespace
   + class property
   - instance property
  ~> listened events (socket)
  +> listened events (class/module)
  -> listened events (instance)
  <~ dispatched events (socket)
  <+ dispatched events(class/module)
  <- dispatched events (instance)
  :: class method
   # instance method

Other symbols
  => returns
  #> throws
[xx] optional


Recommended order: class first, then sockets, then instance. Internally:
Properties, events, methods.

One of the patterns that I started using for functions is to instead define the whole function signature as part of the type definition. So for example, if you have a method that receives a function as an argument, you could write the following:

GenericManipulator
  #manipulate(input T, manipulator(input T, options ) => T #> ManipulationError) => T #> ManipulationError

I've found this pattern covers most cases where I need to pass a function.

In slightly related news, since I've recently moved fully to using neovim, I've also created a tree-sitter parser[3] that you can use as a neovim plugin. It was really fun to learn, but the documentations was clear and easy to follow. A bit less easy to follow was how to get the syntax highlighting to actually work with neovim, but it ended up working.

=> [2] API definition | [3] tree-sitter parser and neovim plugin.

If you use other editors, there's older versions of the plugin available for vim[4], vscode[5], and TextMate / Sublime Text[6]. They don't support the #> throws notation.

=> [4] Syntax for vim | [5] Syntax for vscode | [6] Syntax for TextMate and Sublime text

Proxy Information
Original URL
gemini://r.bdr.sh/gemlog/1696437389086/api_notation_updates.gmi
Status Code
Success (20)
Meta
text/gemini; lang=en
Capsule Response Time
163.059748 milliseconds
Gemini-to-HTML Time
0.683638 milliseconds

This content has been proxied by September (3851b).