4 ms·
That doesn't work in languages with nominal types, and even structurally-typed languages can have a hard time. You call a function that returns a v1975/SomeStr
by jmillikin 4y ago
That doesn't work in languages with nominal types, and even structurally-typed languages can have a hard time.
You call a function that returns a v1975/SomeStruct and pass it to a function expecting a v2022/SomeStruct. What does the new function do when some of the struct fields are set to invalid values?
- netr0ute 4y agoWhat if the type was a "Some1975Struct" that got passed? Then that would give a huge blaring error because it's not the same type as a "Some2022Struct".
- jmillikin 4y agoThe naming convention isn't important. If the structs are from different versions of the library then you either have a type error (nominal types) or have to figure out the semantics of arbitrarily uninitialized fields.
- admax88qqq 4y agoYou do option 3, manually adapt one type to the other because they are different types. If you call one function that returns an int and need to pass it to another function that expects a char* what do you do?
- jmillikin 4y agoI think you may have lost track of what this thread is discussing. To be more concrete, let's say you have the following code (pseudo-Go): package main import "example.com/http_server" // v2 import "example.com/utils" // transitively depends on http_server v1 function main() { var srv *http_server.Server = http_server.New() utils.ServeHttp(srv) } You're going to have a problem, because ServeHttp expects an HTTP server struct from the v1 API, and you're passing in a struct from the v2 API. If you tried to write an adapter for this then (1) you'd need to somehow construct a concrete proxy of a type you don't control, and (2) there's no way to import both the v1 and v2 APIs at the same time in your code, so you don't have a way to declare a conversion function. That's why APIs with versions declared by dependency edges are impractical.
- mseepgood 4y ago> there's no way to import both the v1 and v2 APIs at the same time in your code, so you don't have a way to declare a conversion function. In Go major versions have different import paths. You can import multiple major versions of the same library: import ( http_server_old "example.com/http_server" http_server_new "example.com/http_server/v2" )
- jmillikin 4y agoSure, but that's not what's being discussed here. In C and C++, it's idiomatic to have different major versions use the same includeable name, with the version resolution handled by the build system.
- staunton 4y ago... where "build system" means a bunch of preprocessor macros, at which point you just use the oldest version of everything available and never update anything that works.
- vbezhenar 4y agoSo my thoughts are as follows: 1. Every source file must be annotated with language version. 2. Every language version can remove things from previous language versions. More like "hide" I guess, but you can't compile source file that's using removed features or APIs. So to migrate to new version you're supposed to change sources. Of course preferable using some migration tools, but that's out of scope. 3. You can access old API indirectly. For example if you're using library which uses old API and returns struct from that old API. 4. There should be some well thought rules for situation that you describe. To make structs forward and backward compatible as much as possible. May be even to provide some implicitly running migrations to convert between structs with different versions. 5. If there's no way to automatically convert v1975/SomeStruct to v2022/SomeStruct, you can't do that and need to convert it manually. This is hard problem and must be thought on every level: data layout compatibilities, ABI compatibilities, type system compatibilities. But I'm not convinced that it's unsolvable problem. And if solved it would provide great benefit allowing lots of freedom and agility for language development.