4 ms·
For what it's worth, I prefer the approach you describe. I have advocated for it for a long time. I've been writing C extensions to accelerate parsing in dyna
by haberman 11y ago
For what it's worth, I prefer the approach you describe. I have advocated for it for a long time. I've been writing C extensions to accelerate parsing in dynamic languages for 10 years, and I'm very familiar with this sort of dynamism.
It's interesting though that you describe this approach as more Pythonic, because one of the most outspoken critics of this approach is a hard-core Python guy that I work with who has lots of experience with the Python ecosystem. He feels very strongly that it is more Pythonic to have very flat/concrete generated code that is transparent to the reader, and really does not like the idea of hooking import and generating everything at runtime.
This is exactly what I am describing about how it is hard to please everybody. Different people appear to have fiercely different opinions about what is idiomatic.
When we wrote the Ruby protobuf implementation this year, we took an approach much more along the lines of what I personally prefer. The extension is mostly implemented in C, and it's very easy to build types at runtime. It doesn't directly import .proto files (which I would have preferred) because there was still some desire from others to have some kind of code generation. So the approach we took was to use a Ruby-like DSL for describing the protobuf schema. But really this is nothing but a translation of the .proto file into the Ruby DSL. ie. take the .proto file:
syntax = "proto3";
message Test {
int32 foo = 1;
double bar = 2;
Test test = 3;
}
The "generated code" for this is simply:
require 'google/protobuf'
Google::Protobuf::DescriptorPool.generated_pool.build do
add_message "Test" do
optional :foo, :int32, 1
optional :bar, :double, 2
optional :test, :message, 3, "Test"
end
end
Test = Google::Protobuf::DescriptorPool.generated_pool.lookup("Test").msgclass