Lamdu – towards a new programming experience
lamdu.org
lamdu.org
The last one is probably the most serious, as it doesn't seem to be enough to plug new diff tool into git. There are still places like GitHub, which are hard to modify. That would mean one would need whole new ecosystem for such language.
Having underlying textual format, possibly based on s-expressions might help. You could modify it using AST editor, but still be able to read the code as text and diff it. Other option is to have two-columns editor, with one column being text source and the other AST, making it possible to edit any of two and have the other updated.
But on the other hand, when I started Clojure full time, I switched to using Emacs + Paredit + CIDER (née nrepl.el). And come to think of it, I still open Xcode whenever I'm about to crank out any Swift or Objective-C code.
I think the difference between those situations and Lamdu's approach is that you still can access the files using any other editor you want. You just don't want to, because that given editor is best(ish) for that given language due to IDE features that help edit it more conveniently. Whereas this Lamdu stuff isn't just a matter of convenience, it's part of the language/environment/experience itself.
So yeah, I would never touch this, because it's basically got lock-in that requires its own custom everything, from version control, to needing to rewrite plugins my editor has but Lamdu doesn't (if that's even possible!), etc.
Imagine semantic version control that can parse your AST and tell you which methods, expression, classes, functions etc were modified, instead of just syntax changes like "this line of text is different because you added a semicolon."
I'd love to see more semantic-focused tools, eventually leading to generic solutions that work across any AST. Polyglot IDEs like IntelliJ IDEA can come close, but only because they implement their own parsers, to derive an... AST!
Note that not seen in the screenshot are the `reduce` and `max` functions which I've implemented, though those are pretty simple.
I also can't wait till I'll be able to really use Lamdu.
Lamdu has a nominal type called "Stream" (nominal types are basically like Haskell's newtypes). You can refer to them via their names in holes. The purple arrows represent packing/unpacking depending on which side they appear.
The Stream nominal type has a single type parameter `a` which is the item type, and is defined as:
Stream a = () -> (Empty + NonEmpty { head :: a, tail :: Stream a })
(Note the + above is type-level plus, a sum type).So inside the Stream you find a function from unit (representing lazy computation) to a sum type of 2 cases:
Empty - equivalent to Haskell's []
NonEmpty - a cons, equivalent to (:)
The NonEmpty case has 2 named parameters (head, tail). Maybe it will become an infix (:) in the future.When you pack a Stream nominal, Lamdu auto-completes the lazy suspension (half circle character), and then lets you fill in `Empty` or `NonEmpty`.
When you unpack a Stream nominal, Lamdu offers completions that force the suspended computation (apply with `()`) and then do case analysis (represented by a colon) on each of the sum constructors.
There's the "Stream" nominal type, shown below in Haskell-like text syntax:
newtype Stream a = () -> (Empty | NonEmpty { head :: a, tail :: Stream a })
To construct a "Stream", we type "stream" in a hole and pick "Stream« ◗ _", which wraps a "deferred computation" ("◗ _") in the nominal "Stream" type constructor.Now the type of the value inside the hole within is just "Empty | NonEmpty { head :: a, tail :: Stream a }", now type "nonempty" and pick it.
Working in Smalltalk images can be "live-editing", if you run your application at the same time.
Both of these examples work on a method-basis: you change the code, trigger a rebuild the method and it is used from then on, not automatically after each change/keypress.
There is a bunch of live-coding stuff for creating music, but that often is used with smaller programs and writing the entire program as part of the performance.
I think here the more important thing is that it doesn't work on source code that is then parsed and compiled, but directly on a tree structure representing the program. Live-coding is sort of a side effect, because you a) don't have to reparse everything and b) always can have a state that is a valid program.
Furthermore, Redux has a devtools library [2] (you can view a gif of it in action in the repo) that lets you do time-travel for debugging purposes. I don't use it much, but it can be occasionally useful.
[0] http://webpack.github.io/docs/hot-module-replacement-with-we...
I think it would be more useful to build a tool that helps visualize the overall structure of a program. The usefulness of such a tool would increase as the size of the program increased.
You can leave a "hole" in the structure where you're not finished yet.
You can have type errors but they are nicely localized (despite having global type inference).
This is a nitpick, but an important one IMO - this syntax is only "lightweight" in an environment where the tooling types "◗" for you. Elsewhere (comment boxes / SO / IRC / etc), you're stuck figuring out how to type U+25D7 or breaking flow to pick it from a menu...
In Lamdu, each subexpression has its identity that survives as it is edited, moved, etc. This helps merge changes with far fewer conflicts.
Lamdu also allows attaching English names to identifiers, in addition to Chinese names, Hebrew names, etc. This approach can hopefully rid the world of duplicated libraries where the code is nearly the same but the names are Chinese. This kind of rich metadata doesn't survive well when serializing to text.
Lamdu will also maintain(and distribute) code indexing alongside the code such that the algorithmic complexity of refactoring large projects is not O(project size). Text is not a good data structure to perform these operations.
Lamdu also maintains many invariants about the code (e.g all type errors are localized and marked as such), what would Lamdu do if you try to load text that doesn't maintain the invariant?
We also believe the entire textual tool chain could be so much better if it were rewritten to work with asts.
So for us the only value in textual integration is the "old world" of programming, and we're creating Lamdu much because of our dissatisfaction with that world.
Some of this issues could be resolved while staying within plain text, well to some extent at least. There're various attempts to encode metadata into plain text source code. Loading partially incorrect code should be possible, that's what many IDEs do successfully.
Plain text is the most portable data format ever invented, any incentive to replace it should have very convincing benefits.
Encoding the metadata in the text would lose the benefit of using text. At that point you may as well store the code as XML or indeed as we do, in a key value store.
We could layer our data on top of text but this would lose the algorithmic benefits of a good data structure, and wouldn't actually be editable reasonably with a simple text editor.
Not only.
The article references related work, but somehow it focuses on a single level of liveness[0], which is instantaneous feedback. It is great when you recompile your game update function while running it, but as far as day-to-day coding is concerned, I find it sufficient, and in fact less distracting, to have feedback only when I want it.
[0] https://liveprogramming.github.io/liveblog/2013/01/a-history...
How are you meant to implement the reverse function without a helper function? I tried defining an anonymous lambda function in a let statement, but recursion isn't allowed it seems. And interesting project though! well done
It's been clear to us that we need animations for structural editing so that it's clear to the user what's going on, and we're not familiar with a GUI library that provides us with what we needed, so we made this custom one.
Currently it's part of Lamdu's sources, but we could make it an independent library if there's demand.
[0] http://extempore.moso.com.au/
[1] https://paulbatchelor.github.io/proj/sporth.htmlSo relating to Lamdu, you could say that what you see is the abstract representation. The representation is a bitmap, of course you can't evaluate that.
When you write C++, you actually just write characters, right? Does that mean that you are not writing a program? No, those characters may comprise a program in the end. I see Lamdu the same way: Even though you only manipulate a graphical rendering of the program, it still is all you need to write that program. Just like with C++, you don't see the actual representation of the program (because you can't really 'see' a data structure, you need to encode it), you only see the characters, but you can write the program anyway.
Lamdu is a purely functional programming language so far, I believe. You don't need input, since you can, in the one expression you have available, call a function with arbitrary parameters. You can say that it does not allow for long-running interactive programs, but that is easy to add later once the foundations are in order.
"See the value of some binary logic in real time"
"You can't make syntax errors"
All of this and more, and it works on a small subset of a language that nobody uses!
These are the sorts of things that would be really interesting to a student in their first programming class. I can't imagine anyone with any experience needing or even wanting this.
This is presented and explained better than I could by Bret Victor's "inventing on principle" talk.
We need to get programming out of the "blindly manipulating symbols" phase.
Here's an explanation of what the term means: http://blog.absentdesign.com/2013/05/blindly-manipulating-sy...
What they call 'blindly manipulating symbols' I call 'automation'. That is the entire point of computers in the first place, to very quickly perform tasks so that a human doesn't have to. That means describing the solution to those tasks. This is no different than mathematicians using equations. We don't need to do the entire process of solving every problem if they are the same except for changes in some parameters, we can write an equation and plug the parameters in. In software, we can write an algorithm/program that solves some specific problem, so long as the solution is the same and only the inputs are changing. Since programming languages support branching, we can make these algorithms as general as we think is useful.
Lamdu is partially about bringing the benefits of spreadsheets to general purpose programming.
If you often have to run your code so that you can verify that it is doing what you thought it would do, you don't have any idea what is going on and it's going to be a disaster.
Of course you need to run it to catch mistakes that anybody will make, but not to check that the code does what you think it will do.
For example, in some language you have my_list.sort() method. What does this do to the list? Does it sort it in place? Does this lock the list from other changes? Will concurrent changes to the list corrupt it? What is the expected runtime of this? If the list contains strings, how are they sorted? By unicode code point? By binary utf-8 encoded value? Randomly?
You should just know all those answers in whatever environment you are working in. If you don't you should study up on it. Trying to get a project finished by repeated guess and check is going to take an eternity and you are going to do a poor job.