views:

213

answers:

9

I know this is very abstract, however I believe it is very focused.

There are plenty of high-level languages today: C#, Java, VB, Python, etc., all created to abstract away low-level complexity and provide a more user-friendly programming experience. High-level languages can reduce, and most of the time completely remove, the necessity to perform low-level, process specific operations (such as pointer manipulation and memory management). Many also remove platform details (like file manipulation, user interface generation, etc.)

My two questions are:

  1. What else can/should be abstracted? Are there any more low-level semantics present in today's high-level languages that will be/should be abstracted away further?
  2. At what point does a general-purpose, high-level language become very high-level, a.k.a goal oriented?
+3  A: 
  1. What else can/should be abstracted? It always depends on your goal. There is no clear line here but I think it comes down to how much control do you need? There is usually a fairly heavy trade-off between abstraction and possibilities.
  2. When does a general-purpose, high level language become goal oriented? As soon as you can tell the language/programming environment what you want instead of what it should do.

In reality though... the line is completely arbitrary of course.

WoLpH
+2  A: 

Tcl has an official proposal (Tcl Improvement Proposal (TIP) 131 that pretty much solves the problem for good. All it needs is a volunteer to do the work. There's even a skeletal implementation with just a few of the details left out.

Bryan Oakley
Can that command be used recursively? :)
SimpleCoder
I can suggest an alternative implementation. Every compiler and interpreter I've ever used includes a perfect implementation of "read my mind and do what I don't mean". Pick one and insert a "not" in the right place - should work pretty well.
Steve314
@Steve314: Easy to implement. Just use `rmmadwim` with a programmer who *does* understand the requirements and the code to make it all happen will just appear in a puff of logic.
Donal Fellows
+1  A: 

Hrm, I think a few languages are attempting to spearhead some additional abstractions: Clojure with its STM and Erlang with the Actor model.

  1. About the only thing I can see that I can't see how it would be done is a language with concurrency checks akin to statically typed checking. I say this because the Halting problem exists.
  2. When it mows my lawn, makes me coffee in the morning, checks my email and tells me what happened in the news.
wheaties
+2  A: 

Certain Domain Specific Languages can be extremely "high level". A good example of this is Inform (used to write text adventures) where the programming language is not much different from plain English. Here's an excerpt from an example project:

The fireplace is scenery in the Entrance Hall. The description is "Unlit, vacant
[if Search is happening]. It is almost as though you are not expected[end if]."
The sound of the fireplace is "whistling wind". Understand "fire" or "whistling" 
or "wind" as the fireplace. Instead of burning the fireplace: say "There is no 
fuel prepared for a fire."

This is actual source code. :)

Martin
That is awesome! But I wonder how fast the language is?
SimpleCoder
That's not high level, it's just wordy.
Robert Harvey
It's goal specific (i.e. very high level: http://en.wikipedia.org/wiki/Very_high-level_programming_language)
SimpleCoder
@SimpleCoder - probably pretty quick. I've not used it, but the sample here has a fairly simple declarative structure. Once the semantics of those declarations has been extracted and analysed, it should compile to something that runs pretty fast. Having syntax such as `object "fireplace" : "scenery" { position = "Entrance Hall", ...}` instead would make no difference at all to the final run-time engine. Also, the fact that the language looks a bit like natural English doesn't mean a standard parsing algorithm can't handle it.
Steve314
The strange thing is... for some reason, it reminds me of LOLCode.
Steve314
"Teh cheezburgr iz noms in teh kitchen. Teh discripshun iz ..."
Steve314
It would be hard to use a standard parsing algorithm for Inform 7, since the syntax can be extended by various definitions. As I understand it, the compiler works by doing a ton of pattern matching and backtracking. But that has no bearing on the speed of the compiled program: Inform 7 code isn't interpreted, it's translated to a C-like language (Inform 6) which is then compiled to bytecode.
Jesse McGrew
As for whether or not it's high level: consider an Inform 7 statement like "now every married man who loves an unmarried woman is in Adulterer's Hell", which more-or-less expresses two filtered foreach loops with a single imperative statement. You provide the condition you want to become true, prefix it with "now", and the compiler figures out how to make it happen (within reason). I'd call that high level.
Jesse McGrew
+2  A: 

Haskell even allows you to define imperative block structures (while, for, ...) as library functions. It isn't very good at it, though.

The "not very good at it" is basically why Haskell has no imperative conditional loops in its standard library. It's one of the surprises that result from monads. You can write functions for while etc, but they're not very practical. The condition result has to be action (type IO Bool) since it needs to be sensitive to the loop body side-effects even if it has none of its own. Since IO Bool and Bool are two different types, writing the conditions is awkward. It's much easier to use the idiomatic tail call style which is (in readability and maintainability terms) not much different to using goto. Imperative loops are implicit and not visibly obvious, and you can get tail-call spaghetti similar to ye olde goto spaghetti. For it to be a real problem it'd be the programmers style thats at fault - not the language - but you can say that about almost anything.

The problem doesn't arise in a language like C because all conditions (and everything else) are implicitly side-effect-sensitive and potentially side-effecting actions, so all the operators etc are already designed for that context.

Still - the strict separation of side-effecting and non-side-effecting code is a good idea, and the ability to write custom block structures as library functions is interesting. So I think there will be a very good language some time in the future which will steal ideas from (but not be) Haskell. It will have imperative while loops as standard, but it will allow side-effect-sensitive conditions to be written in much the same form as any other condition. It will accept the direct equivalent of not hIsEOF myFileHandle.

The question is... will it allow you to define your own block structures? Is that even a good idea? It's interesting, but many interesting ideas are actually bad ideas. Personally, I have my doubts.

Steve314
+2  A: 

One of the problems with including very high level abstractions in a language is that sometimes they're not adequate for everything you want to get done, so you end up needing the lower level abstractions, too. The problem with having high and low level abstractions in the same language is that the high level abstractions can become leaky very easily if you can probe them via low level abstractions.

Java, for example, is not even that high level a language, but it is designed to be safe (in the sense that abstractions don't leak) first and foremost. Therefore, some things are just impossible to do in Java. For example, you can't write Java's garbage collector within Java, or roll your own object system using pointer cast polymorphism, or write an operating system (at least not a traditional one).

In contrast, D offers both high level and low level facilities. D's garbage collector, for example, is written in D. This sounds good and for the most part it is. However, when you start mixing abstraction levels in a single codebase the abstractions can leak, especially if you use casts or unions to defeat the type system. Therefore, to successfully program in D you might occasionally need to be aware of some low-level details to deal with leaky abstractions, even if you don't need them for the task at hand.

dsimcha
All non-trivial abstractions leak - but this is a good point anyway. Flexibility, robustness and simplicity are often in conflict. Mixing differing levels of leaky abstraction is definitely fits that rule.
Steve314
A: 

I think that frameworks are the next step.

the0ther
A: 
  • Currently some "languages" are for UAT (which is close to what one could call a goal and with a goal requires tests because it is the only way it could be explained, e.g. Fit for the test part); those could be merged with programming languages.
  • Pretty much every language is getting access to more and more high level interfaces (i.e., abstraction) requiring less and less code from you and abstracted from the OS (see how easy it's to make GUI application now in C#, compared to C++ MFC, compared to C++ Win32 API).
  • As for the programming languages they could get more of the best features of other development methods: I'm thinking of Aspect-oriented programming which could help solve many OO issue and is already partly implemented in some form in C# and Java (like issues regarding logging, transactions...).
  • UML ultimate goal (was?) to allow the UML viesw along with the diagrams' details to be sufficient to code the system; UML is also a language (in the larger meaning).
  • IDE should also be included: You can now set how a dialog should resize from the IDE while you often had to code it before. Later you may be able to style your whole application or website from a drop list of themes just like any skin-able application. And a lot more could come.

Imagine the union of those in a unified environment, because the development environment is a big part of the development just as the libraries one has access to and its level of access.

Wernight
+1  A: 

I think a hypothetical future language will allow you to write a verifier instead of an implementation. The compiler then analyzes that verifier and (attempts to) write an implementation matching your spec. (Obviously the compiler must fail or fall back to brute force sometimes, because it is not a halting solver.)

Essentially, a logic language with ridiculous optimizations compared to brute forcing the answer.

Even though verification code can be longer than implementation code, it acts as much better documentation and is closer to what a spec looks like. You trade more code-typing time for less documentation/spec/code desyncing.

For example:

int32 Remainder(int32 numerator, int32 denominator) {
    requires denominator != 0
    ensures Math.Abs(result) < Math.Abs(denominator)
    ensures exists n suchthat n*denominator + result == numerator
}
int32 EuclideanRemainder(int32 numerator, int32 denominator) {
    requires denominator != 0
    ensures result >= 0
    ensures result < Math.Abs(denominator)
    ensures exists n suchthat n*denominator + result == numerator
}

results in:

//warning: suggested precondition: denominator != int32.MinValue due to Math.Abs
int32 Remainder(int32 numerator, int32 denominator) {
    return numerator % denominator;
}
int32 EuclideanRemainder(int32 numerator, int32 denominator) {
    return ((numerator % denominator) + denominator) % denominator;
}
Strilanc