In terms on how to distinguish functions, you could just have some suffix, like foo@base and foo@local.
I played a bit with Unison before, but I don't think I tried this. I'm sure it's a non-issue though because it's not hard to imagine how tools would help here.
The difference is that in git the repo structure is metadata. The data (the contents of particular commits) is completely independent of the repo structure and so you can change the latter without changing the former. Furthermore, when you try to build a program, you only ever deal with a single commit. You never build a program from multiple commits at once. Program linking has nothing to do with the repo structure.
But in unison, the "repo structure" is no longer metadata, it's part of the program. It is now part and parcel of your linker. So when you change the "repo structure" you are changing the behavior of the program.
Git works precisely because it separates data (program) from metadata (repo structure). When you glom them together the way unisom does, you get some gnarly problems to which I don't see any immediately evident solutions.
The problem, explicitly and concisely is this: Referential elements of structures introduce cascading re-hashing.
There is however a solution to this by adding a layer of (invariant) semantic indirection for referential (as opposed to inlined embedded ‘value’ tuples) types. With this approach, at this point, we obtain 2 benefits: ‘object’ re-evaluation (rehash) is only necessary when object structure changes (not the referents); and in an object graph, cascades will only impact the immediate referents’ ‘value’ mappings.
caveat that I felt extremely queasy seeing this post on hn — a session of self criticism ensued regarding the topic of “laziness” :D — so haven’t read beyond the upsetting intro to Unison.
Also, it seems like a solution to the really nasty problem of changing transitive dependencies.
If you run "todo" it will show you everything that needs to be updated (thought it doesn't force you to update anything).
If you change the type of the function, you'll need to update all usages one by one, or choose to leave some usages with the old function (which may be desirable in some circumstances, e.g. where the bug you fix is never reached from that caller and you want to be maximally backwards-compatible)... UCM will show you everywhere you need to do that... you can get all references to a function before you modify it as well by running "dependents my-fun".
> In Unison, changing what names are mapped to which hashes is done with structured refactoring sessions, rather than the typical approach of just mutating text files in place and then fixing a long list of misleading compile errors and failed tests. A Unison codebase is never in a broken state, even midway through a refactoring.
> If your codebase is like a skyscraper, the typical approach to refactoring is like ripping out one of the foundational columns. The skyscraper collapses in a pile of rubble (a long list of misleading compile errors), and you attempt to rebuild a standing skyscraper from that rubble.
> The Unison approach is to keep the existing skyscraper around and just copy bits of it over to a new skyscraper, using a magic cloning tool. The codebase is never in a broken state. All your code is runnable. It's just that, midway through, you may not have fully constructed the second skyscraper and cut over all the names. Unison keeps track of that and gives you a tidy todo list to work through.
I agree that patching other people's code is not always possible, or easy. On the other hand, you can patch your own library using indirections to the new version.
If the change can’t be made automatically because it breaks stuff, then UCM guides you through propagating manually.
You’d have to do this manual propagation in any language. Unison is a little nicer about it than most languages, since it just tells you what needs an update (and will suggest an order in which to make the updates) instead of giving you type errors or test failures.
Maybe there is a solution to this problem, but a cursory review of the language description didn't turn one up. It seems like a Really Hard Problem because there is nothing that can structurally distinguish between a new function that is created for its own sake, and a new function that is intended to be a bug-fixed (or otherwise enhanced) version of an old one.
Maybe a unison aficionado can enlighten me?