8,390 karma · joined September 5, 2010
http://chris-granger.com http://www.witheve.com http://www.lighttable.com
At that point in time 5k was reasonable. The price would go up quite a bit if I were doing it now though. But I doubt I'd do it again - the work didn't end up being as exciting as I thought it would be.
What I would consider doing in the future is the "idea consulting" I discovered most people ended up needing. I have a knack for pulling things apart and putting them back together in interesting ways :)
EDIT: re FRP, you might find this Lambda The Ultimate post insightful: http://lambda-the-ultimate.org/node/4900
FRP has issues with openness and isn't real great at dealing with collections. It also forces you to express things kind of unnaturally (e.g. instead of "click this and increment x", you say "the counter is the count of all click events"). There are other methods of managing time, like Glitch[1] and Bloom[2] that seem more promising :)
[1]: http://lambda-the-ultimate.org/node/4910 [2]: http://boom.cs.berkeley.edu/
That's what really killed it for me and also one of the things that I found pretty surprising. Tracking references is apparently way harder than I realized. And while I thought we could come up with a decent way to do it, it really did just confuse people. I tried a bunch of different strategies, from names, to boxes that follow you around, to dataflow graphs. None of them seemed to be good enough.
(doseq [x (range|cursor|)]
)
You can wait until the end of time, but that won't finish ;) Whereas I probably wanted to get out (range 10) before it went off and looped forever.Text also doesn't provide you with stable IDs. If I previously had function "foo" in a file and now that's gone, but there's a function "bar" in the same place with roughly the same code, does that mean it was renamed? Or did foo get deleted and we need to surface that anything using foo is an error? How would you know? The only thing you have to go on is position and position can change for all sorts of other reasons. I ran into this problem with trying to do functions in single editors: when the file can change in any way, reconciling that file with your previous view of the world is tremendously difficult.
> in order to affect the real world, one must go there and roll up one's sleeves
This has always been our strategy :) Whatever we do come up with, it will be entirely shaped by working with real people on coming up with something that actually solves the problem.
I think this is the crux of the debate. The point isn't high quality visualizations, it's about bringing the simple little pictures you'd draw to solve your problem directly into the environment. Can you draw a box and put some text in it? Tada! Your own little representation of a card.
I'm not suggesting that you hire people out to build your representations :) This is about providing tools for understanding. Maybe you don't see value in that, and there's no reason you can't just keep seeing things as plain raw text (that's just a representation itself).
> Anyway, scale things up in a way that I don't have to write so many matplotlib calls and you will have my attention.
Give us a bit and I think we can provide a whole lot more than just that. But we'll see!
We ended up abandoning that path for now as there are some aspects of functional programming that prove pretty hard to teach people about and seem largely incidental.
I'm not saying we should forsake language, if you look at the now very out of date Aurora demo, all the operations have sentence descriptions. This certainly isn't an all or nothing thing. If it makes sense to visualize some aspect of the system in a way that is meaningful to me, I should be able to do so - that is after all how people often solve hard problems.
I never suggested otherwise, just that when you're in a domain you should be in that domain. That solution requires something more general purpose to glue domains together, which is the crux of the problem. What does such a language look like? How do you ensure you don't lose all the good properties you gain from the domain specific languages/editors when passing between them?
I think you present a false dichotomy though. General purpose languages are just as much about encoding a process. The distinction between compiling to the machine vs some abstract machine also isn't really relevant: this is about semantics, not implementation. And if you let implementation dictate the semantics you won't get very far from where we are now.
> What I strongly disagree with is claiming that the complexities that plague general purpose languages are somehow mitigated by building more domain specific languages.
I never said that :) I said that programming would be greatly improved by being observable, direct, and incidentally simple. And again those have nothing to do with what "level" you're programming at, they're just principles to apply. I do think there is a general solution that can encompass most of the levels (though I'm not interested in trying to do that any time soon), but there is a common case here and it certainly isn't high level theorem proving or embedded systems. It's stupidly simple automation tasks, or forms over data apps, or business workflows. The world works on poorly written excel spreadsheets and balls of Java mud. You don't have to fix everything to make a huge impact and the things we learn in doing so can help us push everything else forward too.
It seems like I can never win the contrast debate :p Try it now.
> The new C# compiler Roslyn makes determining relation fairly trivial, something that I'm assuming proved difficult in Clojure(script) and Javascript.
I had access to the language models then too, but the thing is relation is not always written directly into the code. This was the point I was making about locality. In a world with mutability, you can't really know what matters. We tend to cope with this by putting code that relates near each other (in the same file, in the same parts of a file, etc), but that relation isn't made specific in the call chain. It could be, and usually is, buried under several levels of indirection. The lack of locality really frustrated people, because the mainstream models we have for programming don't directly relate to flow and so it ended up being a square peg in a round whole kind of thing.
> so it's interesting to hear that you've decided against it
I've decided against it for the way we program now... :) Flow as a general concept is a very good one, and anything that can make that explicit would be wonderful. But we can't program with rampant mutation and callbacks and expect it to work out.
The problem ends up being that you're trading one form of cognitive load for another and it turns out that given our text-centric view of writing code, locality ends up having a lot of importance (which is lost in the model you're suggesting). There are lots of other issues with it at a practical level too. I've never seen an input model that works well with lots of disconnected little editors, for example. How do you navigate between them? How do you lay them out? What happens when the graph is disjoint? How do I get to some point in the flow of the program? What if I need multiple things that aren't directly related next to each other? How do you even determine relation?
After having implemented this in various forms about 4 times now, I'm fairly convinced this is one of those things that makes good intuitive sense, but bleeds to death from a whole bunch of paper cuts in practice.
The one case where this does seem successful though is in the step-wise debugging case. There's a very definite flow, locality matters a lot less, and debugging is an inherently mouse-oriented task - all the things you need for a zoom-based infinite canvas to work out.
Past that, you'd just need to add something to the python plugin that runs a tcp server in your process and then hooks into the python running code that's already there. https://github.com/LightTable/Python/blob/master/py-src/ltma...
If you have different needs, shoot us an email and I'm sure we can work something out.
Unfortunately, the notion of editing an AST is by definition language specific, so it's unlikely that someone could create the structural editor and just have it work for everybody. Moreover, as they mention here for Lamdu, it often requires looking at the language slightly differently and enforcing some rules that wouldn't normally exist in the code. But, with a decent foundation we can at least make writing the necessarily language specific parts relatively straightforward.
For those new to this world and wondering why this stuff doesn't seem to exist, one of the biggest problems with projectional editors is handling the translation problem. How do you reconcile changes in your representation with changes in the underlying code? Can you reliably parse handwritten code into your AST representation write it back and so on without any loss? What happens with handwritten styles that maybe don't fit into the projection's way of viewing the world? What if I know a better way to output the AST than you? It's also particularly difficult dealing with change over time since there are no true unique identifiers for bits of code.
The approach they're taking is likely the correct approach for the "future" - we should be designing languages and approaches to coincide with the ability to tool them. Even better would be to never have a handwritten format at all: the cannonical representation is always the AST. And though you might be able to edit a projection of it as text, you're never at a loss for how to get back to your "good" representation. This is the world I think we ultimately need to get to and you'll be seeing some really cool stuff from us in that vein early in 2014.