|
|
|
|
|
by ratzkewatzke
1481 days ago
|
|
Without rat-holing on "should," here's something I had to do the other day: I am providing language-level APIs for a complex web service, one in Python and one in Common Lisp. The service has dozens of operations, all of which are wrapped around a REST API that takes query strings and headers in its inputs, and produces very different outputs. Model for this is something like S3. In most languages, I have two choices: I can push the complexity to the users, making them plug the query string values into a big map or option object; or I can write dozens of functions, most of which are boilerplate. In Python I wrote dozens of functions (I obviously reused a set of central ones, but there's lots of scaffolding to do, e.g., translation of arguments from user types to strings appropriate HTTP headers). In Lisp I wrote a macro that operates on a set of query string and header inputs, and then defines a function appropriate for the user-level API. When I fix bugs in the macro, I automatically fix all of the functions. The trade-off is that the macro is itself a function that's operating at two different semantic levels (pre- and post-compilation), and it might be challenging to read for newcomers to Lisps. But this let me hide all the nasty API complexity from my users while writing substantially fewer lines of code. New additions are a single defmacro line. |
|