Extra thoughts on “Assemblage” Oriented Programming

Brief followup thoughts on the previous article. Read that first.

Classes?

Classes are really just techniques to help construct objects. In an “Assemblage” language the Assemblage or Pattern itself is the way you construct the objects. The grammar explains how to parse a plain EDN or JSON-like data-literal into the assemblage.

So perhaps we don’t need classes in our Assemblage language.

Inheritance?

Much of the experience of the last four decades is that inheritance is almost more trouble than it’s worth. The “brittle base-class” problem etc. OO practice tends towards re-use through delegating to components, rather than inheritance.

As Charles Scalfani says here, in the real world, containment / ownership relationships are far more common and far easier to reason about and work with than class or type hierarchies.

So why do OO languages emphasize, and provide special infrastructure resources to help with, inheritance hierarchies but not containment hierarchies?

Good question. The + sigil in my suggested Assemblage language is explicit language support for containment. Perhaps there could be more. And we can dispense with inheritance.

Our Assemblage language can use prototypes when something like inheritance is absolutely necessary.

Module boundaries

Defining module boundaries, loosening coupling at boundaries and data-hiding to prevent leakage of dependency through module boundaries are obviously good practices. But making each individual class a hard bounded module is a mistake. One of the pains of Java is that classes which are inevitably and rightly highly interdependent are obliged to be more stand-offish and formal with each other than they need to be.

In Assemblage programming, the Assemblage is the natural module. An entire Assemblage would likely live within a single file. The brief, elegant grammatical description of the assemblage in a single place means that it’s easy to understand the structure of the assemblage and, if necessary, when changing it, to understand that change everywhere in the assemblage’s code.

So it makes no sense to decouple objects within the assemblage from each other. Or to hide the details of the inner structure of one object in the assemblage from others in the same assemblage.

Data hiding / privacy, if supported / enforced at all by the language, should be at the level of the assemblage and not the individual objects.

At the same time, stricter, fine-grained control over mutability is more useful. Explicitly immutable fields within objects make data-hiding less of an issue as it’s impossible for other parts of the assemblage to make unexpected changes to it.

What’s wrong with OO?

Some thinking over at Quora : What’s wrong with OO?

Continuing some thoughts that have been haunting me since I originally phrased them in the answer about designing the perfect programming language : Phil Jones’s answer to How would you design the perfect programming language?.

And in response to Alan Mellor‘s comment on Phil Jones’s answer to In what direction computer science is going for next 10 years? where he says he’d prefer to program a “device swarm” in OOP.

There’s nothing wrong with OO.

Considering the kind of OO you get in Smalltalk (which is really the only OO worth thinking about), it’s a beautifully simple and elegant and powerful paradigm for programming.

The problem is OO languages.

As I put it in my answer :

>It’s that mismatch between a program that thinks of itself as a network of interacting objects, and a language that has no explicit concept of “a network of interacting objects” and no convenient way to express it, that makes Java and friends such hard work. Somewhere deep in the heart of the UML is a good intuition, struggling to find a viable implementation.

These days I’m all about languages for declaring / representing data. OO is a fantastic semantics / virtual machine for thinking about programs. And it’s even fine for data. Data is just a network or assemblage of interconnected objects.

BUT …

No OO language has such an explicit concept of network or assemblage. They all stop at the level of class. Ie. the generalized form of a single object type.

But why does this need to be the case?

Why can’t we have a way of declaring a collection of classes / objects in one go?

I started thinking in terms of JSON or EDN-like notations.
But there’s an obvious problem. Object networks are fundamentally networks (or lattices) not hierarchies.
But all our notations for serializing complex data-structures into a linear text file can really only handle hierarchical data. You use indentation or brackets or XML-style tags to indicated sub-levels of the tree.

But we all know that the connections between objects in a network or system break out of hierarchies and demand a “anything can connect to anything” structure. And that becomes awkward.

Either you go for a special “network drawing” tools of the kind that UML goes for. Or you have some arbitrary and ugly
way to define the hierarchy breaking connections.

But then a couple of days ago I was watching a talk which briefly covered the ML / Haskell family of languages’ algebraic data-types. Which are great for defining complex data schemas in a way that’s almost like Backus-Naur or grammatical definitions.

And it occurred to me that these would work pretty well for an assemblage of objects too.

So here’s the question … could we add some higher level
aggregate command to our OO languages that looks something like this. I’m going to call this “Pattern”. But maybe “Schema” or “Assemblage” would be better.

Here goes :

Pattern make: #CarPattern from:
     Car = Engine Chassi Wheel[4] ModelName
     Engine = noCylinders horsepower
     Chassi = width depth weight
     Wheel = diameter
     ModelName = string.

This is a pretty standard schema-like definition. And in Haskell you often see the algebraic types defined together so you can quickly read such a schema.

Whereas in pretty much every OO language in practice, there is so much emphasis on individual classes that the wider schema gets lost. You can’t see the forest for the trees. That’s true of Java which forces you to put each class definition in a separate file, but also Smalltalk where the Class Browser puts each class in its place in the hierarchy, usually based on type rather than affinity.

So, in my example, on compilation or execution (depending on the kind of language this is) this Pattern definition would produce a number of classes : Car, Engine, Chassi, Wheels, ModelName, with instance variables based on their terminals.

But these objects also have slots or instance variables for the components. Or in the case of Wheel, there’s a Wheel class, but the Car class has a collection or array of four of these Wheels.

I’ve long thought that it would be useful for a language to have an explicit distinction between slots containing objects that are components “internal” to an object, and slots containing other external objects that are lent to it, or that represent things outside itself.

Here I’ve added a new notation. By default the grammar defines components. But a + sigil at the front of the name makes something a reference to an external object.

Pattern make: #SchoolPattern from:
    School = Classroom[] Teacher[] Pupil[] Curriculum
    Classroom = id
    Teacher = Name employeeNumber
    Pupil = Name studentNumber
    Curriculum = SchoolClass[]
    SchoolClass = +Teacher +Classroom +Pupil[] name hour
    Name = firstName lastName.

Note : I’ve used SchoolClass rather than Class to avoid ambiguity with the OO notion of Classes. Here it’s a collection of Students in a Classroom with a particular Teacher at a particular hour.

But our notation is explicit that these objects stored in the SchoolClass slots come from elsewhere in the system. They are not internal to, or limited to a particular SchoolClass. They can appear outside any particular SchoolClass. Perhaps there’s a Teacher who isn’t currently teaching anything this semester.

Now what about or?

Pattern make: #Vehicle from:
    Vehicle = Car | Truck | Bus.

In a statically typed language like Haskell, or even a statically typed OO language like Java, this kind of feature would be meaningful. In a dynamically typed Smalltalk or Python maybe not so much but there could be value to it.

I’m in favour of languages that try to eliminate null values.

We could certainly imagine a Smalltalk-like that doesn’t allow nulls in slots by default. But has some kind of Maybe or Optional for when it’s necessary. And this can be a sigil too. Let’s go with ?

Pattern make: #Student from:
    Student = id Name email ?whatsapp
    Name = firstName lastName.

Here the whatsapp value is explicitly wrapped in however the language thinks about Maybes.

And we can imagine a language with default immutability but sigils again used for explicit mutability. We’ll use @ for mutable instance variables.

Pattern make: #PongPattern from:
    Pong = Paddle[2] Ball
    Paddle = x @y height color
    Ball = @x @y @dx @dy color radius.

Immutable instance variables like the x co-ord of the Paddles and the colours of everything on screen are set at construction time. Only the y of the paddle and the x, y, dx and dy of the ball can change at a later time.

So how do we construct and instantiate a pattern?

Well, we already have a basic grammar for our model which can now be pressed into service in serializing / deserializing the data from our collection of objects into some kind of data-structure.

Everything which is internal must eventually bottom out as primitive numbers and strings or simple objects.

So, for example, using a hiccup-like notation :

PongPattern :constructAll
    [:Pong [:Paddle 10 250 50 (Color new: 255 100 100)]
           [:Paddle 490 250 50 (Color new: 100 100 255)]
           [:Ball 250 250 1 -1 (Color new: 100 255 100) 4] ]

Note that parsing data-structures is a place where even in a dynamically typed language the | is useful.

Anything external must be passed in as an object reference.

What about abstract classes and interfaces? In one sense, the algebraic data gives you that for free. In a statically typed language, a Vehicle would be something that could either be a Car or a Truck or a Bus.

What about adding methods to classes?

This would be in a separate section of the schema definition. And work more like C++ or (as I understand as I’ve never used it) CLOS.

Something like :

Pattern make: #PongPattern from:
    Pong = Paddle[2] Ball
    Paddle = x @y height color @score
    Ball = @x @y @dx @dy color radius
  methods:
    Ball:
        testAgainst: player1 and: player2
            (self @y < 3) ifTrue: [@dy = 1].
            (self @y > 497) ifTrue: [@dy = -1].
            (self collideWith: player1) ifTrue: [@dx = 1].
            (self collideWith: player2) ifTrue: [@dx = -1].
            (self @x < 0) ifTrue: [ player2 incScore.
                                    self @x := 250.
                                    self @y := 250.
                                  ].
            (self @x > 500) ifTrue: [ player1 incScore.
                                      self @x := 250.
                                      self @y := 250.
                                  ].

etc.

Anyway … that’s the first braindump.

Just to note. This isn’t meant to be changing the semantics of a running OO system. When Patterns are made they just turn into Classes. When Patterns are constructed instantiated we create and instantiate ordinary Objects.

It’s just that this gives us a way of making the concept of network or assemblage of objects explicit within the language. And helps save us from what seems to make OO so wearisome. The fiddling with fragments. The dreaded “Ravioli code”

A Tower of Simple Systems

I posted this on Future Programming at Quora : A Tower of Simple Systems

Re-reading the answer I reposted here a couple of days ago about the “Holy Grail” of programming language design : modification.

https://www.quora.com/q/qqylyzqgpwisoecc/What-is-the-Holy-Grail-of-programming-language-design

So here’s a question.

A dumb solution …

But what if we created a system as a tower of “snapshots” of solutions?

Git and other source control systems already store our development history as a series of snapshots.

Containers already give us the way to snapshot full systems.

Things like Amazon Lambda give us the ability to spin-up functions quickly and cheaply on demand.

So …

… what if, when I build a system, I just make a system that handles the first use-case or user story.

That’s now “frozen” at the base of my tower.

Then a new use-case or user story comes in. Instead of trying to slot handling this use-case into my existing program, I just create a new, trivially simple, solution to handle it. That gets added as the next “floor” of the tower.

Now the system is up and running. A user interaction happens.
The system first tries to see if the current top-floor of the tower can handle the behaviour. If it can, fine. If not then we simply drop down to the layer of the tower below it to see if that can handle the story.

And so on …

Effectively our tower of old versions of the system is acting rather like an immutable database, “story-handlers”. For any user-story we can keep adding new handlers for it to the top of the tower (where it supersedes older versions). Other user stories which haven’t changed, we just fall down the tower until we find a handler for them.
Would this simplify trying to compose complex systems?

Obviously this will work best when each user-story handler is a purely functional program (easy and cheap to spin up) and state is kept in an external database.

What does everyone think? Is this just crazy or a viable way of approaching the problem of growing a system? Ie. embrace the fact that you’re going to get cruft (or layers of archaeology) building up anyway, so just handle that explicitly?

Can we call it “Cruft-oriented programming” 🙂 ?

On Architecture and Modules

Another long Quora Answer

Why is it important to agree on software architecture principles?

In a sense, some of this is an update on my thinking on “modularity” (eg. ThoughtStorms:DecompositionByLanguageIsProbablyAModularityMistake

Well, possibly it’s only important in an “organizational” sense.

In that people in your team or project need to be aligned in their conception of the architectural principles or they’ll be working against each other or fighting.

OTOH, are absolute / global architectural principles important?

I’m inclined to think that it’s the same as in the case of “real” architecture. Of buildings and cities.

In architecture I’m a big fan of Christopher Alexander (inventor of “Pattern Languages”) The point about Alexander’s “Timeless Way of Building” is that it IS universal, but part of the universalism is intense awareness of local conditions. It champions the traditional and “vernacular”. It’s small-c “conservative”, in the Burkean sense. Believing that “what people have been doing a lot of around here for last few hundred years is probably a good idea”

OTOH, taking a bunch of ideas that have become successful in France and dumbly re-applying them in Brazil in the name of some bogus “universality” can be, at best ridiculous, and at worst disastrous.

So there are many heuristics and patterns that are useful, but have to be seen in context. How much abstraction and indirection you might need can depend on the kind of project, the language you are using, the type of user, type of interaction, platform the software is hosted on etc.

I increasingly believe that writing good software is like being a good butcher.

Butchery is about knowing where the natural joints of the animal are and carving along them. This allows you, in the minimal number of cuts with minimal effort, to produce the maximum useful pieces of meat.

The same is true of software. It’s about getting a feel for exactly where the natural module boundaries of your application are. What things need to be decoupled and how much decoupling / indirection is needed at each boundary.

Getting that wrong is what leads to expensive problems. And being “wrong” can mean both too close coupling of things that should be more loosely coupled with extra layers of indirection. And ALSO too much unnecessary indirection / abstraction between things that naturally should be more cohesive.

We tend to teach the importance of putting in abstractions / layers of indirection, but ignore the cost of doing it when we don’t need it.

People sometimes cite Richard Gabriel’s Worse Is Better as a rather vague principle. But read it carefully and a LOT of it is about exactly this problem. How much a function should expose the caller to its own failures.

The intuition we are all taught to cultivate, “Do the Right Thing” is that the module should protect the caller as much as possible. “Worse is better” argues that in this case, the module incurs too high a cost (in complexity) from trying to protect the caller from this failure. And that it’s both “worse” but, in fact, “better” to let the caller deal with the failure.

The important point is here is that the general principle is not “never protect the caller from your failure”. Nor is it “always protect the caller from your failure”. The important lesson is that “better” is to recognise what is the right answer in this particular situation.

If “agreed architectural principles” is taken to mean dumb applications of heuristics : “always use an extra abstraction layer” then they are worse than useless. They’re positively dangerous.

If the “agreed architectural principle” is “look at what people have been doing here for a decade, understand why, and follow that” then we’re on to something.

There are patterns that are nearly essential in Java. But pointless in Python.

Java and C++ are extremely similar languages in many way … BUT if you write Java in C++ or C++ in Java you are doing things very wrong.

They are not substitutes.

Java IS suitable for writing huge systems in a way which C++ just isn’t. If you try to write the kind of mega-application that Java is used for in C++ it’s going to be horrible. Juggling that much memory allocation by hand is intractable.

Use C / C++ for small, independent low-level programs, and glue them together in something else (eg. write small independent tools orchestrated within the operating system, or as libraries called from a Python script).

OTOH, trying to write the small programs for which C / C++ are good in Java is overkill. You are going to put too many abstract boundaries and the cost of garbage collection into something that should be smaller, simpler and faster.

One thing which is particularly egregious about Java (and the C++ heritage it comes from) is that these languages have an impoverished vocabulary for talking about “boundaries” between modules. They see classes and objects as a universal solution for everything.

In fact almost all programming languages have fairly poor vocabularies.

When we think of software in terms of architecture, or in terms of the “natural joints” we start to see many kinds of joints / membranes between the parts of our systems. With many degrees of permeability. Many features of languages are about this : the inlineability of functions, hygiene in macros, scope rules, “referential transparency”, data-hiding, lazy vs. eager evaluation of function arguments, the access rules for classes, synchronous messages to objects vs. asynchronous messages to actors, go-routines, sockets, the Unix pipe, internet protocols, microservices, integration “at the glass”, integration in the database, centralization / decentralization of databases.

All these are issues to do with “what kind of boundary is there between THIS and THAT?” How permeable is the boundary? How much do dependencies leak through? What obligations does it incur? What timing commitments does it need? How is the data communicated represented? How are errors checked and controlled?

We recognise this huge variety. But our languages often don’t. Most languages try to hide the variety behind a single principle : everything is a function. Or everything is passing messages between objects defined with classes. Or everything is an actor with async. messages.

While there is something very attractive about this simplicity and uniformity. Sooner or later you find yourself somewhere where the kinds of boundaries you want between the parts DON’T correspond well to the kinds of boundaries that your simple principle defines. You think actors and immutability are way cooler than mutable objects. And then you try to write a photo-editing program that applies filters to huge bitmaps.

So one architectural issue is that our languages try to enforce a single type of boundary when we want many.

The other is arbitrary and unnecessary boundaries. The biggest culprit is the difference between what is inside the program and what is outside it. Inside the program we have function calls, messages, possibly go-routines and internal queues / async. channels. Outside we have async. pipes from the OS. And synchronous socket communication. And a separation of database engine and cache engine. And search engine. And front-end web-server. And client. And server. And microservices. And XML-RPC and SOAP. And Amazon Lambda and similar “function as a service” etc etc.

Our program is divided into files. And various languages and frameworks insist that they should be divided within the file system in a particular way.

Our systems are arbitrarily divided by the underlying architecture of our platforms. Regardless of the natural joints of our applications.

I believe that one task for the next generation of languages is to be able to describe a range of boundary / membrane types and their permeability, timing and protocol requirements, all within a coherent and simple vocabulary. And where questions like “is this communication synchronous or asynchronous”, “lazy or eager” etc. are explicit “parameters” or alternatives within our language.

The other things these languages must do is transcend the “inside the program” / “outside the program” distinction. Today we have applications which have maybe a couple of lines of code doing calculations and other “business” logic. And a huge external “extro-structure”, often dozens of config files and MVC separated directories, to represent routing, caching, permissioning etc. architecture.

We need programming languages where the large scale architecture is a first class citizen of the program. Not something which has to be laboriously built around it. And when the program compiles, it compiles to not only object code, but to automated architecture : Puppet or Ansible scripts, Continuous Integration, containerization, orchestration of Kubernetes pods. This is where the DevOps revolution needs to end up. Languages that are as fluent in talking about all the parts of our systems, and all the kinds of communication between them.

So why am I talking about this in a question about “principles”?

Because software as an art / discipline / profession / culture advances when we take informal ideas and turn them into formal code that can be executed. Heuristics and “good practice” become patterns, become libraries, and ultimately become language features.

Architectural principles will ultimately be recognised and “agreed upon” parts of our practice when they finally become part of the languages we use everyday.

Which language is better for creating DSLs, Clojure or Haskell?

Another Quora answer. Part of my increasing admiration for the virtues of EDN in Clojure.

Which language is better for creating DSLs, Clojure or Haskell?

Clojure has a slightly different philosophy than most Lisps, I think.

In Clojure you’d be more likely to make your “DSL” in EDN (“Extensible Data Notation”, which is a bit like JSON but with more features). It’s completely integrated with / interoperable with Clojure itself. You can embed EDN anywhere in a Clojure program, and embed Clojure function calls anywhere in an EDN data-structure.

And you get “parsing” for free.

That’s how languages like hiccup are built.

So if you just want to make “a DSL” (ie. convenient high-level domain specific notation for an application) then 99% of the time, a hiccup-like EDN dialect is going to be fine, and you don’t have to write anything at all.

In that sense, code you don’t have to write is better than code you do.

If you need a specific DSL with a specific syntax which isn’t EDN (or s-expressions) then you’ll be back to writing your own parser.

Here, Clojure has its own Yacc-like and parser-combinator libraries. I’m not sure they’re very different from Haskell’s. But you don’t have Haskell’s algebraic data-types, so there’s no type system helping you. I guess it’s a bit more effort to get a Clojure DSL right using Instaparse etc. than in Haskell.

There is Spec, which does some of the job but is certainly more verbose and less elegant than Haskell’s algebraic data.

So yeah, Haskell probably wins for writing general DSLs but if you just want to make small, simple domain-specific notations for things in your application, and don’t mind the EDN look, then Clojure is fine. That’s trivially easy.

Pharo and a new Smalltalk

On Quora, I’m often ranting about Smalltalk. And how I’d like to see a “clean-slate” reinvention. Much as Clojure is a clean-slate reinvention of Common Lisp.

Over on this answer I was asked what I think of Pharo.

My response veered off somewhat :

I’ve had a quick look at Pharo. And it’s certainly quite nice. An improvement on Squeak.

But I have a more radical / somewhat idiosyncratic desire. Which I know is probably not something that actual Smalltalk people relate to. But I think it would be a winner.

What I think is, that part of the “cruft” I’d like to see a “blank slate” Smalltalk get rid of, is the “desktop metaphor” and all those silly little overlapping windows, icons, pull out menus etc. Morphic and whatever else.

That doesn’t mean go to something like GNU Smalltalk. No, I still want a live environment that’s Smalltalk all the way down.

I just don’t think anyone wants a desktop metaphor in 2018.

If I’m going to write a “desktop” app, then I don’t want it stuck inside another non-standard app. And if I’m not going to write a “desktop app” I don’t want the overhead of having to think about and implement that kind of interface.

What I think Smalltalk should look like in 2018 is something like Jupyter / iPython notebook. Or, at a pinch, Hypercard.

I open “Smalltalk” (whether that’s a browser-based version equivalent to Amber, LivelyKernel or Peter Fisk ‘s Smalltalk Express, or a desktop version like Pharo or Squeak), and what I see is a “smart notebook” type metaphor :

A single page that takes up the whole window. To which I can start adding “cells” or “cards” containing either code or “literate” styled documentation, or output produced by the code.

You’d still have tools like the Class Browser etc. But they’d be integrated within the same UI. Ie. the class browser is just more “pages” in the notebook. There’s no workspace or transcript because every page can have live code on it.

This UI is immediate. And focused on “do something”. You don’t have to learn how to navigate around a non-standard UI because it’s the conventions we’re already used to from the web and our mobile devices. Navigation between pages, appending “cells” or “cards in the stream” the kind we’re used to in chat apps.

Other UI conventions would be services that look like bots in Slack or Telegram eg. services at a name which can be invoked in a cell on any page through a little dialogue. And there would be notification streams too. “RecentChanges”, recently generated output. Messages from other users (it should be easy to share individual pages with other users)

I think if you took the underlying Smalltalk engine / VM / image. Stripped out all the legacy “desktop UI” stuff, and replaced with a simpler “multi-page notebook” metaphor, then it could be massively more compelling to people. It then becomes a “personal notebook” for doing little sketches / experiments.

If it’s also “social” ie. has chat streams. Or is like the Smallest Federated Wiki. Or has other ways to sync sketches and pages etc. then this would be spectacular.

And the Smalltalk VM / infrastructure is perfect for it.

But right now, anyone who looks into Smalltalk to see what all the fuss is about is confronted with an alien / non-standard ugly desktop, full of unfamiliar tools. Sure, that “Welcome to Pharo” window with all the tabs is an improvement on other systems. But it’s still not good enough.

I open Pharo, and I don’t know what to “do”. How to start playing around and doing something useful and fun.

A Replacement for PHP

I asked Quora for ideas for how a replacement PHP might look.

On the whole people are not enthusiastic. Alexander Tchitchigin had an interesting answer, but which focused on the basic theme of “once we move away from PHP’s weaknesses, we might as well use any language.

Which prompted me to write this comment elaborating what I was interested in. Plus some ideas of my own.

I agree that there are downsides to “embedded in HTML”.

But I think we can also see various what I call “pendulums” in computer science. For example between centralization and decentralization. Centralization gives you economies of scale, eliminates redundancy and makes it easier to see the wood for the trees. Decentralization makes it easier to modularize (or divide and conquer), easier to test and find bugs, easier to scale, easier to improve individual modules etc.

The pendulum oscillates because whenever one of these principles becomes more dominant, everyone starts to feel the pain and see the attraction of the other pole. And then stories start proliferating of the virtues of shifting the other way. Once everyone does, of course, there’s a pull back to the first way again. And so the pendulum continues to swing.

Right now I’m seeing this centralized / decentralized tension in ClojureScript web-frameworks. Comparing using Reagent directly with devcards vs. using Re-frame. Trying to decide whether the convenience of the modularity of keeping state decentralized in individual reagent components and being able to use devcards, outweighs the extra transparency of centralizing state in the re-frame db.

Now I think this thing about “MVC vs. templates with code” is another pendulum rather than an absolute principle.

At the end of the day, HTML is the data-structure for the application’s GUI. And the GUI data-structure does need to be fairly tightly integrated with the code. It doesn’t make sense to try to decouple them too much. You need a button attached to a handler attached to some transformation in your business logic. There’s no point trying to keep these things apart. A button without functionality makes no sense. Nor does functionality that can’t be accessed through the UI.

I’m now using Hiccup to generate HTML. And the place to do it is obviously tightly integrated with the actual functionality of the app in the code itself.

Yes, there are still some MVCish intuitions at work. But I don’t need or want a language to try to hard enforce that separation between UI and functionality either in separate files or with separate languages, when a simple DSL in the main programming language is sufficient.

But when you look at a Reagent (ie. React) component it’s basically a Huccup template with some extra code in it.

Now the brilliance of PHP, the reason it’s so popular is that :

a) it’s just there, pretty much always.

b) it simplifies simple sites considerably by automatically mapping the routing onto the directory structure of the file-system. There are many cases when that is fine. Why should I have to hand code a whole layer of routing inside my code when the file system already provides me with a logical hierarchical layout?

I think there’s still value in the “map files to pages” part of PHP. And that’s what I’d expect a “new PHP” to keep. Along with the “available everywhere” bit.

Of course, how it might look, might be more like Hiccup, a light-weight DSL rather than the verbosity of HTML. With each file implicitly mapped to a React component. Perhaps something like I started describing here : Phil Jones’ answer to What’s the best programming language for applications and GUIs?

In that other answer, I talk about what I found interesting in Eve : the event-handling within the language through “when” clauses and an implicit underlying data-structure.

And I tried to sketch what a language that brought events to Hiccup might look like :

 <pre>
    (defcomponent click-counter
        {:localstate ['counter 0]
         :when (on-click "the-button") #(reset! counter (+ @counter 1))
         :view
          [:div
             [:p "Counter clicked " @counter " times"]
             [:button {:id "the-button"} "Click Me"]
          ]
        }
    )
</pre>

Many frameworks encourage you to put components etc. in different files and directories anyway. Why not make this “official” in the same way that Python makes indentation official. And use the directory structure to infer the program structure?

A powerful modern language with the easy accessibility defaults of PHP would be a powerful combination.

Expression in Programming Languages

Source: My Quora Answer :

If Clojure is so expressive, and is basically Lisp, hasn’t there been any progress in expressivity in the last 50 years?
Well, as Paul Graham put it quite well, Lisp started as a kind of maths. That’s why it doesn’t go out of date. Or not in the short term.
You should probably judge the evolution of expressivity in programming languages by comparing them to the inventions of new concepts / theories / notations in maths (or even science), not by comparison to other kinds of technological development like faster processors or bigger hard drives.
What I’d suggest is that it turns out that function application is an amazingly powerful and general way to express “tell the computer to calculate something”.
Once you have a notation for defining, composing and applying functions (which is what Lisp is), then you already have an extraordinarily powerful toolkit for expressing programs. Add in Lisp’s macros which let you deconstruct, manipulate and reconstruct the definitions of functions, programmatically, and you basically have so much expressive power that it’s hard to see how to improve on it.
You can argue in the case of macros that, in fact, while the idea has been in Lisp for a while, the notation and semantics is still being actively fiddled with. We know that macros in principle are a good idea. But we’re still working on the right language to express them.
Perhaps we can also argue that there’s still room for evolving some other bits of expressivity. Eg. how to best express Communicating Sequential Processes or similar structures for concurrency etc. In Lisp all these things look like functions (or forms) because that’s the nature of Lisp. But often within the particular form we are still working out how best to express these higher level ideas.
Now, the fact that functions are more or less great for expressing computation doesn’t mean that the search for expressivity in programming languages has stopped. But it’s moved its focus elsewhere.
So there are three places where we’ve tried to go beyond function application (which Lisp serves admirably) and improve expression :

  • expressing constraints on our programs through types.
  • expressing data-structures
  • expressing large-scale architecture

These are somewhat intertwined, but let’s separate them.
Types
Types are the big one. Especially in languages like Haskell and the more exotic derivatives (Idris, Agda etc.) Types don’t tell the computer to DO anything more that you can tell it to do in Lisp. But they tell it what can / can’t be done in general. Which sometimes lets the compiler infer other things. But largely stops the programmer shooting themselves in the foot. Many programmers find this a great boost to productivity as it prevents many unnecessary errors during development.
Clearly, the type declarations in languages like Haskell or Agda are powerfully expressive. But I, personally. have yet to see a notation for expressing types that I really like or find intuitive and readable. So I believe that there is scope for improving the expressivity of type declarations. Now, sure some of that is adding power to existing notations like Hindley-Milner type systems. But I wouldn’t rule out something dramatically different in this area.
One big challenge is this : by definition, types cut across particular bits of computation. They are general / global / operating “at a distance”. One question is where to write this kind of information. Gather it together in standard “header” files? Or spread across the code, where it’s closest to where its used? What are the scoping rules for types? Can you have local or “inner” types? Or are all types global? What happens when data which is typed locally leaks into a wider context?
Data Structures
Lisp’s lists are incredibly flexible, general purpose data-structures. But also very low-level / “primitive”.
I don’t really know other Lisps. But it seems to me that Clojure’s introduction of both a { } notation for dictionaries / maps. And a [ ] notation for data vectors has been useful. Complex data literals can now be constructed out of these by following the EDN format. And it’s given rise to things like Hiccup for representing HTML and equivalents for other user-interfaces or configuration data. EDN is pretty similar to the way you define data in other contemporary languages like Javascript’s JSON etc. So it’s not that “radical”. But it’s nice to have these data structures completely integrated with the Clojure code representation.
Can we improve expressivity for this kind of data representation language?
I’m inclined to say that things like Markdown or YAML, that bring in white-space, make complex data-structures even more human readable and writable and therefore “expressive” than even JSON / EDN.
In most Lisps, but not Clojure, you can define reader-macros to embed DSLs of this form within programs.
So Lisps have highish expressivity in this area of declaring data. In Clojure through extending S-expressions into EDN and in other Lisps through applying reader-macros to make data DSLs.
Can we go further?
By collapsing data-structure into algebraic types, Haskell also comes up with a neat way of expressing data. With the added power of recursion and or-ed alternatives.
This leads us to imagine another line of developments for expression of data structures that brings these features. Perhaps ending up like regular or context free grammars.
Of course, you can write parser combinators in any functional language. Which gives you a reasonable way to represent such grammars. But ideally you want your grammar definition language sufficiently integrated with your programming language that you can use this knowledge of data-structure everywhere, such as pattern-matching arguments to functions.
Haskell, Clojure’s map representation, and perhaps Spec are moves in this direction.
But for real expressivity about data-structures, we’d have a full declarative / pattern-matching grammar-defining sub-language integrated with our function application language, for things like pattern matching, searching and even transformations. Think somewhere between BNF and JQuery selectors.
Shen’s “Sequent Calculus” might be giving us that. If I understand it correctly.
A third direction to increase expressivity in defining data-structures is to go beyond custom languages, and go for custom interactive editors (think things like spreadsheet grids or drawing applications for graphics) which manipulate particular recognised data types. These increase expressivity even further, but are very domain / application specific.
Architecture
“Architecture” is everywhere. It describes how different modules relate. How different services on different machines can be tied together. It defines the components of a user-interface and how they’re wired up to call-back handlers or streams of event processors. “Config files” are architecture. Architecture is what we’re trying to capture in “dependency injection”. And class hierarchies.
We need ways to express architecture, but mainly we rely either on code (programmatically constructing UIs), or more general data-structures. (Dreaded XML files.)
Or specific language features for specific architectural concerns (eg. the explicit “extends” keyword to describe inheritance in Java.)
OO / message passing languages like Smalltalk and IO do push you into thinking more architecturally than many FP languages do. Even “class” is an architectural term. OO languages push you towards thinking about OO design, and ideas like roles / responsibilities of various components or actors within the system.
Types are also in this story. To Haskell programmers, type-declarations are like UML diagrams are to Java programmers. They express large scale architecture of how all the components fit together. People skilled in Haskell and in reading type declarations probably read a great deal of the architecture of a large system just by looking at type declarations.
However, the problem with types, and OO classes etc. is that they are basically about … er … “types”. They’re great at expressing “this kind of function handles that kind of data”. Or “this kind of thing is like that kind of thing except different in these ways”.
But they aren’t particularly good to express relations between “tokens” or “concrete individuals”. For example, if you want to say “this server sits at address W.X.Y.Z” and uses a database which lives at “A.B.C.D:e”, then you’re back to config. files, dependency injection problems and the standard resources of describing data-structures. Architecture is treated as just another kind of data-structure.
Yes, good expressivity in data-structure helps a lot. So EDN or JSON beats out XML.
But, really, it feels like there’s still scope for a lot of improvement in the way we talk about these concrete relationships in (or alongside) our programs.
OK, I’m rambling …
tl;dr : function definition / application is a great way to express computation. Lisp got that right in the 1960s, and combined with macros is about as good as it gets to express computation. All the other improvements in expressivity have been developed to express other things : types and constraints, data-structures and architecture. In these areas, we’ve already been able to improve on Lisp. And can probably do even better than we’ve done so far.

Could the internet disappear within 20 years?

From a Quora answer I just made :
The protocol will still exist.
But there is now a real danger that “the internet” will have been successfully enclosed by private corporations.
What will that look like?
1. the end of net neutrality means that the phone companies / network providers can choose to prioritise packets from certain companies / services. They start to demand a premium from popular services.
2. most people don’t notice or care because they only use a few popular services anyway : Facebook, Google, Microsoft, Twitter, Pinterest, Netflix etc. These large corporations complain but start to pay the premium to be first class citizens. Packets from other services / web-addresses get deprioritized.
3. the commercial Content Delivery Networks probably play a role here. Basically anyone who wants to provide content to the public will need to go via a CDN because they’ll be the ones cutting the deals between the phone companies and any company smaller than Facebook and Google. That’s probably how Quora and Pinterest etc. will keep going.
4. Meanwhile, governments will continue to try to reassert control over internet content. In the name of clamping down on piracy, pornography, fake news, terrorism, online harassment, illegal crypto-currencies etc. they’ll start putting more pressure on online services to police their content. Facebook and Google will be increasingly required to co-operate. Smaller services will find they need to be vetted to get onto the CDN.
5. Also networking “hardware” is increasingly moved into software. Routers become generic boxes whose protocols are just software configuration.
6. Finally, phone companies, CDNs and router companies figure out some “improved” protocols which make the shaping and inspection of traffic more efficient. Stripped of the need to route generic packets from anywhere to anywhere, this new infrastructure, brought through a software update, is sold to the consumers as an “upgrade”.
7. By now, consumer IP is dead. Email protocols stop working. (Google and other “web-mail” providers arrange an alternative that looks the same but works over the new protocol. Or perhaps integrates directly with other messaging providers.) Communication is via Facebook and Twitter which work on the new protocol. Other P2P protocols that rely on IP also stop working. No more bittorrent, btsync, syncthing, webrtc etc.
IP survives as a “legacy system” for corporate users of course. Too many large companies still depend on it. But it will now be expensive, like most “enterprise” kit.
Within 20 years, we’ll find that the remaining “free” internet, where any ordinary person can hire a web-server and put up their own content independent of any of the major corporations or systematic government oversight is reduced to a tiny minority of hobbyists like amateur radio. Most people never access it or even know of its existence.
If you don’t like this scenario, NOW is the time to do something about it.
Not just do what you can to defend net-neutrality, but start to use the free / peer-to-peer, open protocols that we still have. Run your own web-site or blog. Use RSS to share content. Use webrtc to do your video conferencing, and bittorrent to share legitimate files. Do what you can to make sure that there is just too much demand and usage of the open protocols and internet that the large corporations can’t afford to try to switch it off because they know they’ll be losing too many customers.
Once most people aren’t using the internet, taking it away becomes easy.

What's wrong with C++?

Another Quora answer : Phil Jones’s answer to Why is C++ considered a bad language?
This is one of those rare occasions I disagree with Simon Kinahan; although his answer sets the scene for this one.
[Simon says that C++ isn’t a bad language. It’s the right choice if you need low-level memory control and the ability to build powerful higher-level abstractions.]
C++ is a bad language because it’s built on a flawed philosophy : which is that you should add power to a language by kludging it in “horizontally” in the form of libraries rather than “vertically” by building new Domain Specific Languages to express it.
Stroustrup is very explicit about this, rhetorically asking “why go to other languages for new features when you can add them as libraries in C++?”
Well, the answer is, adding new higher level conceptual thinking in the form of a library doesn’t really hide the old thinking from you. Or allow you to abandon it.
C++’s abstractions leak, more or less on purpose. Because you can never escape the underlying low-level thinking when you’re just using this stuff via libraries. You are stuck with the syntax and mindset of the low-level, even as you add more and more frameworks on top.
Yes, you can explicitly add garbage collection to a C++ program. But you can’t relax and stop thinking about memory management. It can’t disappear completely beneath the horizon of things you need to be aware of the way it does in Java.
Yes, you can have higher-level strings, that can abstract Unicode-ness etc. via a library. But you can never be sure that you won’t confront strings that are simple byte-arrays coming from another part of your large system.
Etc.
C++’s ability to build high-level abstractions uncomfortably falls between two stools.
It encourage you to think you can and should be building large applications full of application logic. But doesn’t give you the real abstracting power to focus only at that application level.
This explains the otherwise mysterious paradox that C is a good language, so how could something that is “C plus more stuff” possibly be a bad one? Well, it’s exactly the “more plussing” that’s the problem.
With C, you KNOW you should only use it to build relatively small things. It doesn’t pretend to offer you mechanisms to build big things. And so you turn to the obvious tools for scaling up : lex and yacc to build small scripting languages, the Unix pipe to orchestrate multiple small tools . C++ gives you just enough rope to hang yourself. Just enough powerful abstraction building capacity in the language itself that you (or that guy who used to work in your company 15 years ago ) thought it might be possible to reinvent half of Common Lisp’s data-manipulation capability and half an operating systems’ worth of concurrent process management inside your sprawling monolithic application.
I don’t see why it shouldn’t be possible to combine low-level memory management and efficiency with high level abstraction building. But proper abstraction building requires something more like macros or similar capabilities to make a level of expression which really transcends the low level. That’s exactly what C++ lacks.