After working some more with Tiles, my mini-library for programmatic code generation, I've realized it has a feature that I haven't knowingly baked in, but which makes it a really good tool for the job. Namely, the code you write is composable.
Here's what I mean: If you want to generate a C function that prints out names of countries' capitals then you can generate the code that does the actual printing first:
data = {
"Afghanistan": "Kabul",
"Brazil": "Brasilia",
"Canada": "Ottawa",
}
body = t/''
for country, capital in data.items():
body |= t/"""
printf("@{capital} is the capital of @{country}");
"""
Once done, you cen generate the scaffolding:
program = t/"""
#include <stdio.h>
int main(void) {
@{body}
return 0;
}
"""
The example, of course, shows just two levels of nesting. In practice, however, you'd have many levels of nesting.
But whatever the nesting level, you, as a programmer, can focus on a single task at a time. First, you think about how to print the capitals. Then you think about the scaffolding. There's no overlap.
Compare that to your typical templating solution:
template = Template("""
#include <stdio.h>
int main(void) {
{% for country, capital in data.items() %}
printf("{{ capital }} is the capital of {{ country }}");
{% endfor %}
return 0;
}
""")
template.render(data=data)
Note how you start with writing scaffolding (include, main) then you switch to the business logic (printf), then you get back to scaffolding (return).
The example is trivial and as such, the both solutions are kind of comparable.
However, imagine there are five levels of nesting.
The code written using Tiles would, logically, look like this:
level1
level2
level3
level4
level5
The code written using one the classic templating tools, on the other hand, would look like this:
level1
level2
level3
level4
level5
level4
level3
level2
level1
March 2nd, 2019
I actually found your ribosome library to be pretty nice for generating code, and it’s also composable in surprising ways. I need to actually play around with Tiles but on first glance it seems harder to read and looks a lot more like straight text manipulation than ribosome or other template-based solutions.
If you’re curious, I wrote a C code generator with ribosome just for fun that you can find here (and I’d love to hear your thoughts on it, though perhaps via email since that’s a bit off-topic): https://github.com/saltzm/cgen
As for ribosome/tiles comparison, the crucial difference is that ribosome doesn't provide symbolic names for blocks of code. Each line of the generator can thus produce exactly one line of output that goes straight to the output file and that's it. With tiles, a block of code is a datatype and can be thus stored in a variable. Obviously, you can also have many variables and combine them in any way you see fit. You can write them to different files, combine them, store them to database, do transformations on them etc.
I've looked at cgen and notices that it was inspired by Pieter's writing on model-oriented programming. We've used to worked together on a fairly large project that was almost entirely code generated (OpenAMQ). The takeaway from that was that code generation is fun to write but hassle to read. Consequently, the code is virtually dead because no one wants to touch it.
That being said, sometimes there's just no other option than to generate code. E.g. when you want to do generic programming in Go. It's a tough problem.
With ribosome you can put a block of code in a function with no parameters, which is pretty similar, you have that in your "Colors" example.
I don't disagree, that's why I feel like you need to be able to keep the code and the models in the same place. Effictively I just want really hardcore and powerful metaprogramming that's easy to write, I guess, which is what I was trying out with cgen. I still haven't used it to build anything big though, though I'd like to someday :) Was a hobby project. Using it at the time seemed extremely powerful but I haven't come back to it.
Post preview:
Close preview