Hacker News new | past | comments | ask | show | jobs | submit login

I'm not sure if I'm missing anything, but if you ever need something like this, it generally means that you have a serious issue in your design.

I can understand templating languages (e.g. jinja2) which add dynamic logic using a high level language (e.g. Python) to a dumb markdown language (e.g. HTML), but I don't see the need to generate code for another high level language.




It's mainly useful for automating chunks of documentation.

Markdown files on GitHub for example don't support any form of templating language - but Cog is a template language which can be hidden away in <!-- comments --> in your Markdown, and then executed using a separate command:

    cog -r README.md
So it's a templating language for files that don't usually support templating languages, but that do support comments.


A metaprogramming technique like source-code generation is not a serious issue in any design. It's especially helpful if the source of truth in your design is external to the current code base. You can generate:

- documentation from source-code files, some CLI frameworks are offering this (eg. oclif[0])

- types from schema files, and schemas from types (eg. quicktype[1])

- API clients and servers from specifications (eg. openapi-generator[2])

...these are all repetitive tasks that can be automated.

That being said, I wouldn't personally generate it in the build step, but rather introduce an additional generate step for it and sync the generated output with the VCS of choice. I recently wrote about it a bit here[3].

[0]: https://github.com/oclif/oclif#oclif-readme

[1]: https://app.quicktype.io/

[2]: https://github.com/OpenAPITools/openapi-generator

[3]: https://blog.whilenot.dev/posts/typescript-source-code-gener...


Exactly. I've used something like this before when writing a lexer and a parser and it was really helpful.


Before the introduction of generics quite a few projects used source code generation in Go projects, to make them manageable.

(Lisps, OTOH, have macro capabilities that do the same thing elegantly behind the scenes.)


It is not for dynamic logic, it is more like a code generation tool. The inlined output means that you don't have to rerun the embedded code every time, which is useful for many cases where templating as a part of the build process would be inadaquate or cumbersome.


I would often prefer to have this kind of code generation to magic reflection or dynamism at runtime, especially if runtime magicks come with a performance cost. For example in JavaScript you can intercept any method call or object access at runtime using Proxy, or in Ruby using method_missing, but it such code is often hard to maintain and understand.

If you statically generate a bunch of methods from a schema, it’s very easy to just read the output source, and the JIT is much happier with the code.


Sometimes it's easier to just codegen than to figure out the performant way to do something like read some spec file and generate an API from it. Especially if the generation target is something like Java or C++.

Code generation is also nice for things like generating Typescript definitions for your frontend to interact with a backend API. The value is partly derived from Python being a language with great introspection tools, so the codegen code itself is easy.

It's not so much that this is the principled way of doing things, but it might be a way that is good enough and gets you where you need to be, in a slightly reproducible fashion.


then you have not gone high enough in abstraction/interoperability within some code food-chain .

i had python code that generated another python code which then generated C (and C++) for wrapping CORBA.. 20 years ago.

Like 1000 LOC generated 5k that generated about 100K C.. No way to make that by hand - and keep it consistent.. Unless, one has to employ large number of people for the sake of it..


Can you see the need for it when the high level language is overly verbose or requires boilerplate? Or simply very limited in terms of generics etc? Or maybe you're mixing languages and you want to generate interfaces between them.

We use something like this (our own version, not in Python) for the above cases. We generate VHDL and C. It's incredibly powerful.


There’s definitely use cases for example API client generation.


The most common use I can think of is to align your classes to the schema of your database. Entity Framework uses that (the C# equivalent is called T4 or TTTT).


Or one’s been programming in C++ where they use an ungodly amount of preprocessor and templates.. cog solves that elegantly.


At least with preprocessor and templates the compiler errors point to your actual source files, not to some auto-generated mess.


Cog generates inline code, the compiler will still point to the code unlike the preprocessor.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: