<https://youtu.be/gCWtkvDQ2ZI>
# thinking-together
s

https://youtu.be/gCWtkvDQ2ZI

💯 4
👍 3
g
ah man i feel like i just realized the sheer scope of potential for ast hashing: for example, you could write a function that uses the unison environment to search for a function that transforms its argument’s datatype into a target one (and i’m sure the teams aware of this)
s
Sounds like hoogle? You can search by function signature. BTW Squean and Pharo also have 'search by example' (https://wiki.squeak.org/squeak/1916)
With AST hashing you'd need the exact hash (or the exact source code that produced the hash) to search by hash? Or am I missing something/
g
I mean actually metaprogramming: so like
Copy code
AttemptStringConversion :: Any -> Maybe String
def AttemptStringConversion someData
perhapsCorrectFunction = Unison.Codebase.SearchBySignature((typeOf SomeData) -> String)
hopefullyString = perhapsCorrectFunction someData
switch hopefullyString 
  String -> Just hopefullyString
  _ -> Nothing
something like that
should brush up on haskells actual syntax again
s
oh interesting yeah. I think this means the index of functions is available for meta programming. Nitpicking terms here but I think this is different from 'ast hashing'.
g
the thing the AST hash gets you is that you can disambiguate between a bunch of functions with type signatures, and not worry about them being renamed when you’re still doing dynamic lookup? maybe? a bit fuzzy on specifics here
like the way you get a robust index of functions for metaprogramming is by having a unique and permanent identifier for each one
g
I finally saw this video. As usual I'm probably mis-understanding something but I had ton of questions rename: If I have xyz = abc() + def() and I go change .unison/hasofabc/names/abc->def so now my code reads xyz = def() + def() ?!!? rename: One of the biggest issues in programming on the documentation side is the internet is full of examples of old deprecated code. So I decide that the function sould be named "doTheThing" as that would make the code more readable than "thingADoRunRun" that I named it originally. Ideally I'd like to lead all devs to use "doTheThing" but in unison "thingADoRunRun" will last forever and all examples using it will still work. You might think that's good. I think it's bad. I makes it impossible to deprecate old examples and docs refactoring: So there's a bug in function foo, I fix the bug (change the implementation of foo). All the code is referencing the old implimentation by hash instead of indirectly by name so no bugs can ever get fixed? In fact I don't even get how to write code in general. Let's say I write this add(a, b) = a * b a = add(1, 2) b = add(3, 4) c = add(5, 6) Then I run and see there was a mistake. I type * where I meant +. So change add to add(a, b) = a + b But the other 3 lines are pointing to the old version of add since they're tied to its implementation hash not to the word "add". Worse, how do I even fix the 3 lines? going back to the first renaming issue I can end up with these 3 lines all referring to different functions. that would seem super confusing a = add(1, 2) b = add(3, 4) c = add(5, 6) no builds: Inspired by haskell I can't know before hand that a specific type is going to work with a specific implementation until I pass that type though the implementation's ast can it? In other words the compiler needs to apply the ast substuting the type I pass in and then see if that type is compatible with every statement in the ast? conflicts: the diamond conflict you mention is not an issue in modern JavaScript (es6 modules or even old amd modules). All names are in local space period. You can easily have an app that uses v1 and v2 of a library. In other words this issue was solved without the complex hashing and required custom IDE to code solution. searching: the example is given that there are 2 functions named the same thing DoTheThing(v1), DoTheThing(v2). So now I can't, as a human, at a glance, know which version of the function is being called. I have to ask the IDE, which version of this function is this really? In JS I can just look at the import statement.
import {DoTheThing} from 'dth/v2';
g
rename 1: yes i think that would work but not sure why you’d ever do that except as a prank rename 2: the name never existed exactly. everyone’s code still runs because the only thing that changed was the human-readable alias, not the machine-checked identifier. so if you were browsing the code with the unison package manager, it would show you the most up-to-date names except where you had overridden them locally. the only difference here is that both old and new examples would work, and you could verify that they ran the same code
refactoring: i don’t think you’ve quite grasped how the system works. you might want to watch that part of the talk again? on every compile the names of your functions get replaced by codes generated from the compiled abstract syntax of their respective function bodies so when you change the body of your add function and replace * with +, the ast of your add function changes, its hashed ID changes, and every instance of the word “add” gets replaced with a different hashID in your code
searching: i think you’re neglecting to notice the amount of information you’ve found previous to typing that import statement. you had to at some point google “redux form alternatives” or whatever, identify an implementation you wanted, read docs/examples, find the correct function or module to import, etc. that context gives you all the information you need to understand ‘import {DoTheThing} from...’ unison’s approach would enable you to skip most of that by letting you query available code on the package manager by for example type and/or function name and then quickly swipe through until you found the one your were looking for
no builds: not sure i understand this one conflicts: if you’ve seriously never had a problem with dependencies in javascript i’m not sure this value prop is going to appeal to you
i’m not rock-solid on the technical implementation of unison but it does seem like most of what you’re missing is the motivation for the project
g
refactoring: i don’t think you’ve quite grasped how the system works. you might want to watch that part of the talk again? on every compile the names of your functions get replaced by codes generated from the compiled abstract syntax of their respective function bodies
so when you change the body of your add function and replace * with +, the ast of your add function changes, its hashed ID changes, and every instance of the word “add” gets replaced with a different hashID in your code
they showed distributed code so when machine A sees a hash for function newABC and machine B sees a hash for oldABC how does machine B know it needs to replace all oldABC hashes with newABC hashes. Or as another example would be pulling in someone else's updated library. Your code says a = #12456(b, c). The new library used to define #123456 but now only defines #123457. In any previous system pulling in the new updated library matches on name but in their system there is not match anymore. Your code is still referencing the old hash
conflicts: if you’ve seriously never had a problem with dependencies in javascript i’m not sure this value prop is going to appeal to you
JS can function perfectly with zero conflicts unlike C/C++/C#/Java/Swift. You can make up conflicts by polluting the global namespace but that's on you. JS gives you way to make all modules not pollute any namespaces unlike C/C++/C#/Java/Switf. Back before Common JS, AMD and ES6 modules it was common to have that those conflicts. That pretty much all disappeared with CommonJS, AMD and now especially with ES6 modules. Any module that pollutes the global name space is shamed until they stop.
rename 1
You don't have to be pranking to have those issues. You only have to have 2+ devs who rename things. A new problem has been added, one that didn't exist before. That problem is that from the programmers POV they can't look at a function name and know which function it is at a glance. They have to rely on the IDE to help them at best. This is a common complaint of C++ that there are so many invisible places in the language that can make it hard to really understand what the code is doing at a glance and because of that such a feature has been excluded from many languages in direct response to the problems it causes in C++. So adding a similar feature here doesn't sound like a win