Why Isn’t Programming Futuristic?
ianbicking.org
ianbicking.org
People have called it a "jQuery for data types", and that isn't such a bad description. It allows you to uniformly interact with nested records (similar to objects), collections and variants (values chosen from a known set of possibilities--sum types).
It's systematic, modular and surprisingly powerful. Of course, like many powerful abstractions--including Haskell itself--it takes a bit of up-front effort to learn, but it's more than worth it.
those are the first lines from the macbeth witches if my memory serves correctly.
Lenses + Prisms (nicest way I know of in lens):
nested ^? foo . _Just . bar . _Just . baz . _Just
vs. the Maybe monad:
foo >=> bar >=> baz $ nested
https://www.fpcomplete.com/user/tel/lens-aeson-traversals-pr...
nested ^? foo . mapped . bar . mapped . baz . mapped
Which is also a bit closer to the nature of `>=>` chaining. I actually really like the _Just descent since it makes some of the failure modes for this lens very explicit.And then it should always be said that the lens has setter properties that the `>=>` chain does not.
However, I think these text dumps we work with should be organized differently. As it stands, we interact with code on a file-by-file basis. But any programmer knows that the execution path of a given program is rarely going to be contained within one file, and it's not going to execute from the top of the file to the bottom. Execution jumps from file to file, and programmers spend much of their time maintaining a mental model of these jumps.
I think this is the wrong way to program. I think execution path should be more easily accessible to a programmer, and they shouldn't have to navigate through function calls one "Go To Definition" at a time. This topic has become fourth year design project for myself and a few peers and we're trying to play with different representations of code on a function-by-function basis.
Here's a rough prototype we hacked together a few months ago: http://www.youtube.com/watch?v=Bm38U40HL4E
We've since integrated it into Visual Studio so as to retain Intellisense, syntax highlighting and existing plugin functionality. We're using Roslyn to gain insights into semantic information about the code.
[1] http://www.kickstarter.com/projects/noflo/noflo-development-...
[1]: http://www.andrewbragdon.com/codebubbles_site.asp
[2]: http://visualstudiogallery.msdn.microsoft.com/4a979842-b9aa-...
[3]: http://www.chris-granger.com/2012/04/12/light-table---a-new-...
I actually saw the Codeporium .dlls kicking around inside the DebuggerCanvas package. Most of the Visual Studio interfaces lack a lot of formal MSDN documentation, which has forced me to do some novel research haha.
Edit: Oh, you are Chris Granger haha. I'd also like to thank you for the Visual Studio 2010 editor tutorials, while I have the chance.
Light Table looks fantastic, and I hope it inspires a change within other IDEs as well.
1) The approach has been tried countless times before and failed.
2) Programmers don't need code abstracted away. Text is great for telling a machine what to do. The real pain point is in linking pieces of relevant text, something that OOP does pretty successfully, but still leaves some room for improvement.
3) Nobody has 25 feet of screen space to see an entire program on, and scrolling around over giant flows is a huge PITA.
4) Attempts to solve the screen real estate issues through collapsable nesting of flow paths usually lead the same incomprehensible rat's nests of logic that regular old code does.
5) Business people don't want to code, despite their fantasies of kicking all the expensive programmers to the curb. Computers usually do exactly what you tell them to, and talented programmers are different than your typical business people in that they have a knack for taking high level requirements and turning them into highly complex, low level implementations. Someone who has no interest in this sort of work will ever be any good at it IMHO.
6) Building flows requires 99% of the implementation to already be complete. Stringing together prebuilt modules with if/thens is not that difficult or unreadable in textual code anyway.
Regarding (1), I think we need to understand why it's been tried and why it's failed. Knowing that it's been tried before and failed should be enough to make you skeptical, but it shouldn't be enough to outright reject something unless it's a copying an old idea wholesale. That said, I think NoFlo specifically has very few new or interesting ideas.
but loved the visualisation space imagined / implemented for excel calculation paths in this recent submission.. i wonder whether a similar idea (ie. for viz.. not replacing an editor) would have mileage here, or would it just be so complex as to be indecipherable?
> hello_world()
--------------------
def hello_world
puts "hello world!"
end
and so on. Basically the code bubbles concept but inline. Maybe it'll be possible to get LT to do something like this in the future...Interfacing different kinds of computer systems together today is orders of magnitude simpler than it was even in the 90's, much less the 70's.
Sure, we're not all talking to our computers while they program themselves and driving around in flying cars. But software development technology has come a long, long way. Users are tons more empowered to do their own work now than they used to be. And the amount of knowledge and training needed to make a developer effective today is nothing like it used to be.
Eventually I used most UNIX systems, commercial and free versions thereof, including the tools most HN folks love. However I am a mouse/keyboard person and love my IDEs.
Every time I look at someone using plain vim/emacs with a few text terminals open, I see someone working in a UNIX System V system.
Because we intuitively see the world in this way, we are good at building and maintaining systems that work in this way.
Anything more sophisticated than that (algebra, relational databases) requires a lot of study and practice to get good at.
No. That's how physical space works. When you're a library, and you need your user to be able to find the books, you don't have a choice: any given book must be in one shelf, in one alley, in one room. And bam, you have a tree hierarchy that is three levels deep.
But our minds are better at dealing with tags. Just see how popular they are in blogs. I bet that a tag based file system would be vastly better at storing personal data than a hierarchical one.
But we choose to divide our buildings up into rooms. We choose to create that hierarchy.
Edit: I suppose, though, that our minds evolved to operate in physical space. Go hunt some zebra, go climb a tree... things like that...
Having watched people struggle with what is essentially a configurable search pane (specifically, the excellent thumbnail viewer in Windows Live Photo Viewer), there does need to be a simple default, probably one that looks just like a hierarchical file system. It just shouldn't be the only way to use the system.
-installed programs
-files installed (except configuration) by a program
-files installed (including configuration) by a program
-libraries
-a users personal files (including configuration).
-all files except bare bones install
-all files
-files on a specific hard drive
My conclusion was that my preferred layout would be
/os/ - bare bones install
/home/ - users files
/home/im3w1l/.conf/firefox - my configuration for firefox
/programs/ - installed program and libraries
/programs/libfuse/.conf - configuration for libfuse
/programs/firefox/.conf/im3w1l - my configuration for firefox
C:/programs - installed programs on specific hard drive
And that if a file is deleted from one place it is deleted from all. So rm /home/im3w1l/.conf/firefox -rf
would be the same as
rm /programs/firefox/.conf/im3w1l -rf
But I think a general tagged system has some problems, most notable filename collisions. Adding a tag to a file could create a collision for instance.
A variation on this theme would be to do away with explicit names altogether, and only use tags. The "name" of the file would just need to be reasonably unique. That one is probably best.
Now, when you search for a file, you just query for tags. Can also be done through the shell: it's just that those two commands would have the exact same effect:
cd /foo/bar
cd /bar/foo
As for the volume, you need them to transfer files between your USB key and your computer.Oh, thinking of using cryptographic hashes to name files… When you modify the file, the ID changes as well… that's a new file! By default, the old version should still be around. Imagine that: Git for the masses.
In other words, it's not futuristic because we're not terribly good at imagining the future.
The guts of modern computing is based on the fundamental logical architecture of Von Neumann and others, work of the 1940s and 1950s. We may be building things in software that couldn't have been imagined back then, but we're building it on structures designed back then.
Look at the iPad and modern tablet computers, in many ways the pinnacle of the modern computer movement. Then look up Alan Kay's Dynabook, which he invented (conceptually) in 1968! We're just now catching up with his vision from 45 years ago.
Please don't mention the iPad as a pinnacle of anything. It is not. It is merely a rehash of old technologies packed into a slick exterior and heavily marketed. It is more a tool of social status than a utility. Compare this to the HP Compaq TC1100, which was a tablet computer released seven years before the first iPad and the specifications of which trumped those of the iPad by double.
As for being victims of a constrained Von Neumann mindset, perhaps so. On the other hand I haven't really noticed any non-Von Neumann languages that are too practical for human purposes. Languages like APL and FP are quite esoteric, compared to the straightforward, if theoretically lacking, ALGOL model.
The iPad is more than heavily marketed dribble; it was actually usable when compared to the TC1100, and basically "realized the dream" of tablet computing when predecessors couldn't: specifications are shit, usability is king. Engineers often don't get that.
> As for being victims of a constrained Von Neumann mindset, perhaps so. On the other hand I haven't really noticed any non-Von Neumann languages that are too practical for human purposes. Languages like APL and FP are quite esoteric...
CUDA dominates the HPC world right now; MapReduce dominates big data processing. Vector machines and data-parallel pipelines have won big in their own domains. And I'm not even going to talk about relational database, all of which are very non Von Neumann computing models and have been very successful.
I had to figure out ways to undervolt the CPU so I could extend the battery. The battery typically lasted maybe 1-2 hours, but by undervolting I had gotten it to about 3. It was incredibly bulky and heavy, and it had no actual touch ability. It would heat up quite a bit.
Now the one good thing about it was it had a very accurate Wacom digitizer and man could it write notes. Shame there was never a good app for it.(OneNote maybe).
I think Microsoft took a cue from the way TC1100 provides a keyboard(not a shitty SurfaceRT one) that you can connect to and it's sturdy. Something I think the Surface is doing.
So overall not a usable device. My only question is that someone like Steve Jobs being around the same time never thought to release an Ipad at the time. I wonder why, did he think that the tech just wasn't ready hence not worth spoiling the user experience.
But, seriously, Haskell, for example, is quite practical (better than the imperative languages) for a big set of applications. One problem is that people want a language to rule them all - and that language can only be imperative; the other problem is that people don't want to learn different things, and a new paradigm is as different as you can get in programming. That makes everything else unpopular.
Don't get me wrong, I love Haskell, but I don't think it's very good at imperative programming, and I think there are much better solutions to be found to problems such as I/O.
Battery life is solid, unlike the tablets before (the figure I found for the TC1100 is 2-3h), the operating system is built for touch unlike Windows (or OS X). There are just no quirks to it that have to be explained by historical or technical circumstances. It just is. That's probably why it is so frustratingly non-futuristic :)
I searched through some old archives and found a scanned in PDF of the algorithm I wanted to implement from a late 60s fortran implementation. I converted it to node.js and Presto! The thing takes the exact same inputs, gives the exact same outputs, and does it all in... 35 milliseconds.
With the complexity of the algorithm and size of the dataset I am pretty sure it would have taken a mainframe the size of a warehouse and weeks to compute back then, but it showed me that the underlying data structures and mathematics have not changed in the least.
I have always tried to take it to heart that "we stand on the shoulders of giants" and all that, but this was really a turning point for me over the last few weeks, that many of the greats from the past would make us all look like morons if they were around today.
There are implementations of this algorithm in C, C++, Java, Python, Javascript, and probably others, but they are all at least an order of magnitude slower than the one that came out back then, given the same modern hardware, even in a language that is not exactly known for its computational prowess.
Perhaps these are the wrong limitations. Perhaps the limitations that really matter is how we think about programming. The discussion of sequential vs parallel programming comes to mind.
But it is one thing to think about programming as single threads which follow nice, clean flowcharts, and seeing the program as multiple threads woven or knitted together in complex ways. This isn't necessarily parallel programming, but it can range from things like Aspect-Oriented Programming to moving to asynchronous parallel programming and distributed systems.
But if we recognize this then maybe the solutions in the past, as inadequate as they were, were striking out in useful directions. Thus I am a fan of a sort of back to the future approach where we look sympathetically on discarded solutions for inspiration to future problems.
I'm surprised, however, given the talk about ASTs, that the article mentions nothing about LISPS and the notion of a language being homoiconic. Lot's of really awesome stuff happening in clojure that really does feel like the future (or the awesome past reloaded).
Checkout this article for more about lisp s-expressions vs XML. http://www.defmacro.org/ramblings/lisp.html
For me though this really comes together as a knotty problem in hardware description languages. They are also a great place to start on the problem because hardware is pretty easily specified as a 'problem'.
The obvious is that the low hanging fruit has been picked, so of course the rate of change is going to decrease as the problems get larger and harder to solve.
The less obvious is the massive influx of users for these languages/tools. There is an unavoidable regression to the mean related to ability/willingness to expend effort that comes from that influx.
In the previous era if you were involved in any way with programming you were, by definition, interested in pushing the boundaries. Now the majority are actively resistant to change like humans are with most things. This is their job, and changing how things work threatens their livelihood.
So why have the subset of people who are willing and able to do these things not doing them? I say some of them are doing it, but not enough to get a critical mass (at least a critical mass that would lead to the kinds of widespread improvements being discussed).
Obviously this is affected by the subculture I'm in but the most common reason I've encountered why these new ideas don't get traction is because it's considered a waste of time. Learning a new way of solving problems is time not spent spamming other social networks trying to increase signups to your social network. Growth Hacking is "getting shit done!", using some new technique that requires learning something new in order to be more productive is considered Ivory Tower bullshit.
Both Clojure and Haskell are communities I follow where there is real interesting futuristic work being done right now. But Node.js, with it's basis on callbacks is way more popular. Even though everyone in the 70's agreed that continuation passing style was a usability nightmare for programmers and put a strict limit on the complexity a human using it could handle.
Looking at it another way: Programming is futuristic, it's just that most people are too lazy to bother and just stick with the older stuff that works the way they are comfortable with, then human nature kicks in and labels everything they don't do as "stupid waste of time".
When I first encountered computer programming, we were still using line numbers. Now, about 20 years later, we've got Python and Ruby and Haskell and ubiquitous GC and… so many frameworks.
Programming is more futuristic than ever, and the tools available are continuing to evolve.
A lot of these points look like they're solved by Clojure, but Clojure is my hammer, so perhaps it's cognitive bias that these look like Clojure-shaped nails.
Don't get me wrong: Python pays the bills these days. And that language is an able workhorse. But boy do I miss Clojure. The reason I don't use it at work is that I work in Android, iOS and Google App Engine most of the time. Which means Java, Python and Objective-C. The code world has infantilized away from Lisp too far.
Records are, essentially, just maps with some type metadata attached. They're implemented as classes purely for performance purposes.
I really, really want to fix this--write a real post-plaintext programming environment. I've tried and failed so far (although at least I figured out the data structures) and I have my own life to live, issues to deal with, etc. All hope is not lost though. Rust is shaping up to be the exact foundation the next generation of programming environments needs. We'll get out of this plaintext plateau soon.
Re: "Better, more accessible ASTs," this is the aim of Steve Yegge's Grok Project.
Safe object traversal? Sure, reflection is a pain, but how would an improvement in this area bring us into the "future"? Also, I may have misunderstood, but isn't Lisp's object traversal about as safe as you can get?
More/better ASTs? I think he was trying to say "compilers should have APIs for third-party tools". Otherwise I don't see why it matters whether the compiler builds an AST or not.
"Direct manipulation of data" as coding? First of all, what does this even mean, and how is it better than the current standard of ASCII files? The author dismisses graphical programming languages as being too heavily focused on "symbolic manipulation". I'm guessing he's talking about LabVIEW, which is admittedly horrendous. But there are others. Blender's node-based shader system[1] fulfills many of these seemingly arbitrary wish-list items. It's easily accessible via Blender's Python API, it has a clearly visible AST, it's deterministic and massively parallel...
In short, I'm confused and unconvinced that the future envisioned in this article is better than what we have now.
[1] http://www.blender.org/development/release-logs/blender-242/...
ASTs: by representing the program in a more abstracted way, we can start to build tools that manipulate them in ways other than ASCII editors.
Direct manipulation of data: well, Bret brought this one up, not me. I thought it was a little odd. While spatial representation of code was about stretching our ASCII into something else, I chose to interpret this as stretching our concrete editing tools towards code. In other words, how do you add abstractions to concrete editing tools. I think the simplest task would be the one to start with: how do you parametrize something in a concrete data editor?
The secret to creating advanced tools is to minimize the magic. Crazy powerful tools still require the expert user to have a predictive mental model of what is really going on so that accurate decisions can be made and valuable experiences can be accumulated on the learning curve.
I would say, though, that the programming we do is by its very nature futuristic. So few humans have been able to interact with information the way programmers today do. The tool churn and huge volume of ideas and trials that we're going through will, eventually, become a mainstream way of working with ideas. It may take a long time.
The other thing is.. a hammer may seem like a simple and obvious tool, but there is still a huge gap between an expert and a novice when it comes to pounding nails. You still need a lot of practice.
Live coding: http://www.mrdoob.com/projects/htmleditor/ WebRTC: http://cbateman.com/demos/head-coupled/ (needs well-lit room to track your eye position) 3D: http://patapom.com/topics/WebGL/cathedral/index.html
And of course there's plenty more that can be done. People tout an IDE like Lighttable, which of course uses web technology to accomplish everything special it does.
Edit - and as ugly as Javascript is, it's pretty powerful. Has all the power of Lisp/Scheme, beat with a C-flavoured ugly stick for awhile, enhanced with advanced runtimes (V8), and transformed by transpilers/compilers, is even used to represent bytecode (asm.js) and emulate other platforms (http://fir.sh/projects/jsnes/ and http://copy.sh/v24/)
Edit2 - and of course, Smalltalk in the browser: http://amber-lang.net/ and a Lisp machine-type thing in the browser: http://alex.nisnevich.com/ecmachine/
Edit3 - WTF how did I not see this... http://idflood.github.io/ThreeNodes.js/public/index.html
Fast dynamic languages => Self (1986)
WebRTC => oN-Line System (1968)
It doesn't look very futurist to me.
But if you compare Ruby or Clojure to Forth or COBOL, there's no way you can't see how far we've come. And there's no end of improvement in sight.
[incidentally, i wrote a recursive descent combinator lib that worked on generic sequences, in python. afaik no-one ever used it for anything but strings. not even for parsing binary data in comms protocols. i extended it to a regexp engine; it was hopelessly slow. one reason regexps work so well is that they're so efficiently implemented on simple sequences of bytes. the overhead of "irregular" sequences is quite something - perhaps jits will help here (although pypy didn't help me)...]
"The Future of Programming", http://vimeo.com/71278954
"You need to be able to inspect and traverse objects, all objects."
Smalltalk? Lisp Machines?
"There also must be a culture where proper extensions are regularly provided on objects. Powerful tools are built on powerful paradigms, and enabling a paradigm isn’t the same thing as actually implementing it across a fully developed programming environment."
The MOP?
Are we doomed to keep on asking these questions again and again? An IT curriculum should include at least one unit where students are required to study the history of these things and write an essay.
Speaking of, that PL course was probably the closest to a CS history course that I ever took. The only other courses that came close were ones where I deliberately sought out papers on algorithms (AI, graphics) that had been developed in the 70s/80s relevant to projects I was working on. Other students just brute forced their solutions taking advantage of the much faster hardware available at the time.
I took an AI course at uni so that I could see some Lisp in action (and learn AI) but the bastard lecturers (2 of them) change it to ... JAVA! While still using the Norvig textbook that had the algorithms in LISP-y pseudocode. And with lead lecturer being a Vietnamese PhD who couldn't speak enough English to explain the most basic concept. 2/3 of the class flunked.
Way to go on your initiative to look for papers and context around your other courses! I bet the perspective it gave you has helped.
And the meta-object protocol is exactly what I'm talking about: extensibility without ubiquitous useful patterns. The MOP might (maybe) be helpful in implementing a prototype, but it wouldn't by itself create a system where goal-oriented traversal and search across an application was possible.
How about Smalltalk as a basis or the foundation of what you want? If somebody pursues the approach, how hard would it be to develop a layer that takes care of the safe-unsafe issue?
MOP: extensibility without ubiquitous useful patterns. My experience says that "ubiquitous patterns" manifest when you use a technology against real problems. So use the MOP to tackle several problems and then watch the patterns emerge. If 1/25th of the raw brain power had been applied to abominations like PHP had been diverted to using Lisp and exploring the meta patterns in there.... my gut says your blog post would have been about some cool framework you wrote to solve the problem ;)
On the other hand, if your concern crosses the single language barrier (you mention LINQ) then what sits at the top of Object Model A and Object Model B? It is some Meta Model or a specific library framework that understands both. Back to the meta again, back to all those leaves on a branch of history left unexplored.
What do we have instead? Brainpower, time, money and youth/a generation being devoted to the "hip hop VM" at Facebook.
Given your prolific programming output (thank you for pip and virtualenv, big admirer) it is no wonder that you ponder these issues and wish to pursue something higher up. What I was trying to get at is that, respectfully, you are not the first and that there might be some lessons in the history of our profession that we could learn from and use as a basis for progress.
Regarding ZeroVM, I am a bit confused as to what exactly "moving apps to data means". If I have a 20 GB log file to process living on a filesystem, how do I "move" my Python processor script to it?
I don't feel like Smalltalk is going anywhere, so I don't know. Smalltalk has some great lessons, but I don't think well defined data access is one of them. Haskell, as mentioned earlier in this thread, has some pretty strong guarantees. Probably too strong ;)
I think something like the simple Scheme/Ruby convention that mutable methods have a ! would go a long way. You'd need more than a casual convention though, it would have to be a real promise. Though maybe if you had search agents rooting around in any method without a ! you'd see people apply that convention more thoroughly ;)
"On the other hand, if your concern crosses the single language barrier (you mention LINQ) then what sits at the top of Object Model A and Object Model B?"
FFI. That is, in any language you have an interface to access external things, so if that interface also includes information about the thing you are accessing then you have an opportunity to traverse into other systems. That's where the extensibility comes into play: you can't typically enumerate an external resource efficiently, but with appropriate interfaces maybe you could route the more high-level goal to that external resource.
That's a little handwavy, but...
'Regarding ZeroVM, I am a bit confused as to what exactly "moving apps to data means".'
I'd say two things. First, in the cloud context you can move a routine to another server. For instance consider `SELECT user FROM users WHERE confirmed_not_spammer(user)`: lets say confirmed_not_spammer() is not a database function, it's something pretty complex that you've implemented outside of the database context. Given portable processes it's at least imaginable that you could send just that routine to the database server, and it could call out to that function.
Actually that's both things! First, you send the routine to another computer, second you can have inversion of control: instead of sending a fully-baked query to another process, you leave open the possibility that the other process calls back as part of the process of finishing the query.
This is all also very hand-wavy. I expect there are still massive amounts of tooling necessary to fulfill the promise of ZeroVM.
"Given your prolific programming output (thank you for pip and virtualenv, big admirer) it is no wonder that you ponder these issues and wish to pursue something higher up. What I was trying to get at is that, respectfully, you are not the first and that there might be some lessons in the history of our profession that we could learn from and use as a basis for progress."
There are lots of corners of computing I don't know about, and I'm interested in hearing about them. But in these particular cases I am aware of the history. I think it's a little too easy to say "hey, someone already did this!" when really you mean "hey, someone made what you describe possible!" – but everything is possible, that's what Turing Complete means. Creating a viable and rich environment in which productive work can happen is different than creating a context in which you could create that environment.
Maybe someone, using Smalltalk, created a general object search and reasoning algorithm. I would in fact not be surprised if that did exist at one time, and I would be interested in learning about it. Similarly in Common Lisp, or even today in Clojure. Someone has even noted an example in Haskell. But the specific product is of interest to me, not just the environment that spawned it.
For sure. To me it seems like a good environment for isolating processes and users in security and execution contexts -- just boot up an instance, perform a task and then destroy. How it applies to data processing is not very clear.
"But the specific product is of interest to me, not just the environment that spawned it."
I see what you mean. I feel that anyone creating such a product/environment will run into massive problems that are very non-technical. How do you get language owners/implementers to agree to a common standard especially in today's web where we see common denominators of data sharing like RSS slowly being strangled by the big players -- let alone co-operations in programming environments/runtimes. The reason I mention the "big players" is that without somebody getting funded to think about this in a serious manner for an extended period of time, it will be very hard. Organisations like universities have the brainpower for this but not the money or the drive.
Something encouraging here is the recent slew of JVM languages -- they share objects with Java. Limitation here is its all on a single platform.
Maybe with the recent announcement of a Haskell kernel for IPython environment there is room for doing some inter-lang op work?