multidimensional abstraction?

An old saw: IIUC, a problem faced by programming languages is that there are multiple dimensions which ideally could all be serviced, but in the end in 2D ASCII aren't. The "expression problem" is a classic example thereof. I am wondering what the current state of the art is / new promising directions people have seen?

For me, a big part of the problem is that "it depends". When I'm writing code it doesn't bug me to have it split up, but when I'm debugging code I'd rather see things "linearized" rather than have to chase through inheritance relationships to figure out the total gestalt. What underlying representation could we have to allow us to view the code in different ways?

Subtext (RIP?), CoreTalk (ok, that might be impenetrable), what else? Are we just doomed as long as we're still using ASCII? If so, what is the least offensive approach? Generic programming a la STL? Multimethods? How can we ground the investigation: what metrics tell us which approach is best / does the least harm?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

One could say that this

One could say that this "modularity problem" is the holy grail of PL that one way or the other all of us are chasing after. Of course, we all define the problem differently, or focus on different parts, but what you seem to be aiming at is a "grand solution" that solves the entire problem at once. The pursuit of a grand solution has wasted many hours of many PL grad student's life before they become more pragmatic and look for a small chunk to attack.

As for current events, I'm disappointed by AOP and hope that it continues too be ramped down so that its resources can be directed at new/more promising approaches. The code generation approach is promising, and we are beginning to see some promising constructs (mixins, pattern matching) hit the mainstream (e.g., Scala). Tools can solve some of the problem, I'm amazed at how stagnated Eclipse/Visual Studio debugging have become, there is so much that could be done in making the view of a running program easier to navigate.

ASCII is probably here to stay in programming just as books haven't really been replaced by radio or video. Natural language could be more heavily utilized to make ASCII more expressive and modular. We could also break the page metaphor to distribute chunks of ascii code in a 2D space, use more visual methods to connect and manipulate various chunks. But to be honest, books/reports/thesis/magazines/webazines are still pretty linear, we haven't evolved linear in understanding and communicating.

Linearity Considered Harmful

I'm not convinced that ease of printing is a good argument for linearity. Do electronics magazines/journals insist that circuit designs are represented in ascii? Personally I find it strange that we are so hung up on linear representations in situations where graphs would be vastly clearer. Of course linear text has its advantages, such as ease of copying. One solution might be a graphical notation with underlying metadata.


What is the ratio of EEs really using the graphical view of some chip mask to understand what it does, vs. using Verilog simulations or whatever?

Where does visual programming fall down? (i assume that is something the LtU community already has 'answered').

I think the CoreTalk (among other systems, but it has the most fun time-cube-esque web site) approach of trying to offer multiple views of stuff is sorta seems to be obviously a good thought: that our development systems should be multi-modal.

Maps have their uses, but

Maps have their uses, but you still need text to make sense of them. So maybe we could design PLs that make use of more maps/schematics. But still, a decent size IC is much easier to understand in VHDL then the resulting visual layout.


A good point, but I wonder if your IC analogy is particularily valid in this situation. Perhaps you are visualising a single vast two dimensional layout constrained to prohibit crossing tracks? I was thinking more along the lines of small expandable sub networks with clear abstraction boundaries. Or possibly dynamically editable views of an underlying abstractionless graph similar to the fluid AOP mentioned elsewhere in this thread. Anyway the point I was trying to make is that (IMO) linear text is not the final word in programming - at least from an end user perspective. And it sounds like you agree to an extent.

re: grand solution

As people might well have surmised, i'm not a bear of large PLT brain. But if i were, the 2 approaches that come to mind for tackling this are (based on clueless hand-waving of mine):

(A) ignore ASCII and only talk about core/base/axiomatic things: "i have an algorithm, i have data, how should i be able to slice and dice them; in other words, what is intrinsic and what is possibly variable about them, what dials could i offer up?" get as abstract-away-from-ascii as possible.

(B) take a TDD approach to some concrete thing by picking some problems to study incrementally e.g. start with expression problem and come up with a great answer to it, then pick another classic issue and refactor, etc.

Sort of (A) bottom-up vs. (B) top-down. Not that people haven't already tried to do such things, i'd assume.

When i think about (A) i guess i end up thinking that multimethods make a lot of pragmatic sense vs. the OO/FP dichotomy wrt expression problem. But I'm a layman; it sounds like e.g. dmbarbour thinks there are other better approaches to take.

When i think about (B) i'm at a loss to think it is anything super new, although perhaps most people making new languages do so with some agenda in mind rather than really trying to approach it with a pure TDD "i have no concept of the solution, and will only do what i'm forced to" attitude, if such process might offer up any new insights.

(C) subtext rocks, if only for pointing out "ASCII sucks! duh!"

Tools can solve some of the

Tools can solve some of the problem, I'm amazed at how stagnated Eclipse/Visual Studio debugging have become, there is so much that could be done in making the view of a running program easier to navigate.

Eclipse is definitely a dead end. Visual Studio 2010 has promise, as it will be written in WPF. However, I'm not sure how system performance will hold up. I would personally like to start a Silverlight/Moonlight based IDE project, but the lack of hardware graphics acceleration is a letdown.

Also, you can't seriously be amazed. You are on the cutting edge of this stuff. The current stuff isn't bad, it just lacks good language models and error models, etc. to juice things up. This conceptual issue will always be a tooling bottleneck.

To avoid the conceptual issues, it is much simpler to think of a simpler programming model without these challenges.

Composition of Concerns

One golden trio for n-ary dimensional abstraction of values is the ability to:

  • provide a name with a value, possibly contributing from more than one source components
  • combine these values by some user-defined function (e.g. to create a multi-method, construct an open type, build a function, load data into a logical proposition, build a list of unit-tests, or simply override based on ordering or a statement of priority)
  • require the gestalt (post-combination) named value in one or more source components; this needs to maintain other properties, so if types or values are immutable then it mustn't be possible to observe a partial combination.

This approach achieves dependency-injection simultaneously with modularity, though one must still have a means to specify which source components are linked into a build and their relative override order. The above three operations form the basis of IBM's Hyper Spaces, and can be used to generalize Aspect Oriented Programming without any special cut-points.

The yin/yang principle for language design: for any feature, support equally its categorical dual.

Modularity without dependency inversion has a serious yin/yang imbalance. Symptoms include warts and pimples such as the expression problem. Partial solutions (such as open functions and datatypes, multi-methods, open classes) cure a few of the symptoms, but still won't make it easy to support a variety of useful abstractions (such as logic programming, policy descriptions) without involving a framework.

i would appreciate hearing more about "this imbalance"

not sure i can visualize what the imbalance really is in my head.

(why multimethods appeal to me:

i think one of the problems is that w/out them, we run into the problem of "which abstraction is primary?" which is i think what is the basis of the FP vs. OO faces-of-a-coin of the expression problem.

so i think any solution to the overarching problem has to allow great flexibility (but with good clear demarcation) in the choice of how "dispatches" are done.)

To visualize duality, you

To visualize duality, you must represent something as a directed graph, flip the arrows, then figure out what the new graph is telling you.

E.g. there is a duality between records (a value from which you can project one of a set of named values) and sum-types (a value into which you can inject one of a set of tagged values). By the Yin Yang principle of language design, a language with records would have a (metaphorical) "yin-yang imbalance" if it doesn't also support equivalent sum-types. There is a similar duality between object constructors and dependency-injection. C++ fails on both these points (it does support C unions, but can't use those with destructors). These imbalances are experienced when one utilizes a framework like a crutch or otherwise works around the missing feature.

For modularity, the graph is that of influence: a module (call it M) exports values/types/functions/etc., and other modules (N, O, P) can name module M and import them, thus introducing an influence from M to N, O, and P. The duality here would be to reverse the arrows: allow modules N, O, and P to influence values/types/functions in M. The 'special' feature here is that nothing but the arrows gets flipped: M does not necessarily name N, O, or P.

It is common that languages offer little ability for client modules N, O, P to influence values/types/functions in M. Limited influence makes separate compilation easier. But the Yin Yang principle of language design would tell you that there is likely to be a problem.

The 'expression problem' is just one of the symptoms. It is not a symptom of code being written in linear text, but rather of modules favoring unidirectional influence.

I see multi-methods as a cure for a symptom. I'm not particularly satisfied with them.

thanks! (will keep re-reading and pondering)

The 'expression problem' is just one of the symptoms. It is not a symptom of code being written in linear text, but rather of modules favoring unidirectional influence.

ah right, even if the ASCII weren't constraining, it seems to me that the issue with FP or OO in the exp-problem is that somebody chose a primary abstraction for dispatch.

Fluid AOP

Ultimately I think the solution involves what Gregor Kiczales calls "fluid AOP". I talked about this a bit in a blog post Modularity in Many Dimensions.

re: fluid aop

I'm reading that and trying to grok it, but off the cuff one thing it makes me wonder is: How much can a person really be expected to hold in their head? Obviously not a lot, hence the power of abstraction. The problem is that i guess one can only wield a single abstraction at a time in terms of having readable ASCII code. (I mean, isn't that one thing that is supposed to be great in the beginning about AOP, but which doesn't really pan out, as you note?) Which means you end up perhaps sort of choosing the lesser of several optional design approach evils.

Is there any representational approach (text, graphics, smell, audio, haptics, i dunno what) which can let us apply multiple simultaneous abstractioning?

re: fluidity

Cohesion-on-demand turns weaving and unweaving into a browsing activity. The programmer no longer has to reason about complex composition rules à la multi-methods or static aspects, as she can simply inspect the content of the relevant view.

i do wonder: is it really possible to hide things and make sure the hidden things don't impact the thing that isn't hidden? or to have the system perhaps be able to alert you if the change in the visible thing would clash with the hidden aspects?

in other words, abstractions interact, and we need to know that, and we need to see that, and we need to handle that, unfortunately. which is perhaps one of the things that totally dogs us and attempts to "solve" the uberissue?

p.s. i really like your phrase "modularity space" and that really sounds like what i guess we'd like to discover/define: an underlying model that somehow has several views onto it.

a small refinement

as has been said many times in many places, another problem is that we tend to have (currently, as the state of the art goes) essential abstraction interdependencies, and then we have lots that are incidental because somehow the system sucks (e.g. shared mutable state vs. stm or actor model, say). so it would of course be key for any successful 'answers' to the uberissue to avoid non-essential coupling.

so if things are kept as clean as can be, it would then be interesting to see just how independent the abstractions can be.