3 ms·
This looks attractive at first but it has one show-stopping problem AFAICT: if it turns out that a function has a bug, you can't fix it by changing the function
by lisper 4y ago
This looks attractive at first but it has one show-stopping problem AFAICT: if it turns out that a function has a bug, you can't fix it by changing the function definition. You have to create a new function and then change every single call site from the old definition to the new one.
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?
- zawodnaya 4y agoThe UCM tool propagates the changes for you automatically. It also creates a patch that you can distribute with your release to update any dependents automatically. 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.
- dietr1ch 4y agoWell, you can say the same about git right? If you need to change an old commit, then you'd need to re-create all the commits that depend on it. Which is true, but something we leave to tools. In git we can just rebase or absorb. 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.
- lisper 4y ago> Well, you can say the same about git right? 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.
- eternalban 4y agoThere is a solution to this problem of content addressable structures. I was (paper, head) designing the same general approach 10 years ago, borrowing a sort of ~homoiconicity from Lisp (code and data are just tuples of structured hashes) as well. 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.
- dust1n 4y agoI’m no aficionado but I believe this is handled by the code manager and not the language https://www.unison-lang.org/learn/ucm-commands/#moveterm https://www.unison-lang.org/learn/ucm-commands/#moveterm
- antipurist 4y agoNot a unison aficionado, but I believe this is an OK problem to have given that we already have to deal with a (weaker) variant of the same problem in every other PL: if your dependency has a bug, you/dependency vendors have to create a new version of that dependency and then change every single module that depends on it. The scale might be different, but the nature of this Really Hard Problem appears to be the same in both cases. Also, it seems like a solution to the really nasty problem of changing transitive dependencies.
- brabel 4y agoIf the change you've made did not modify the type of the function, then updating all usages of that function is as simple as running "patch". 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".
- dmos62 4y agoHere's a relevant excerpt from "The big idea" article linked in this one: > 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.
- worldsayshi 4y agoIf there's tooling that can do this efficiently it sounds like it can be a win since all changes in implementation details become explicit and can potentially be more easily tracked.
- dmytrish 4y agoIt's trivial to find every possible call site of a function in a Unison codebase. 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.