Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Why don't we listen to Occam's Razor when it comes to programming languages?
6 points by LightMachine on Dec 9, 2015 | hide | past | favorite | 18 comments
Repeatedly through the history of humanity, huge advancements came from the conception of simple systems that replaced complex systems. An example is the decimal system itself. It does essentially the same that roman numbers do, except much better, for being simpler. And that very fact opened doors for science to progress much faster, because we weren't busy spending evenings multiplying numbers. This is one of countless examples that show there is a great benefit in pursuing the simplest alternative.

When it comes to programming languages, we didn't learn that lesson. Each other day someone develops a new fancy programming language with X more features, not realizing that all those features are already present on the simplest languages. The λ-calculus - a 70 year old system - already does everything that all those do, simpler and faster (compiling to Haskell, it already runs an order of magnitude faster than the average Python program). We treat PLs like products, but in reality they're just mathematical objects. Imagine if each other day someone created a new fancy numeric system? Why, instead of designing hundreds of fancy, complex programming languages, aren't we focusing in studying how those features manifest on the simplest languages, and implementing faster evaluators for them?

Here is Euler's 1st problem solved on the Caramel syntax for the λ-calculus:

    euler1 = (sum (filter (either (mod 3) (mod 5)) (range 1000)))


I would think that Simplicity would also have to include 'readability'. In other words Simple for humans Write and Read.

You give a great example of Euler's 1st problem (https://projecteuler.net/problem=1) but if someone wasn't given the context of the problem, or even if they were are unfamiliar with the syntax you used, they would not call you solution 'simple'.

That being said transfer of knowledge is a key component when reading. Going to your point about the decimal system (which I believe you were talking about the arabic numberals (https://en.wikipedia.org/wiki/Arabic_numerals)). Sure it is faster and shorter to use than Roman Numerals, but then again the knowledge transfer that you could do with Arabaric numerals is much greater than Roman.

I would say for programming languages, ever time we, programmers, innovate on one we are trying to make a process simpliar to the user (I believe 'abstraction' would be an appropriate word to use).


When you point out the importance of context, I would hasten to add that for me comments in programs provide context that even the best naming convention, etc fails to provide.


I would agree, but there also needs to be a balance. You can't solely rely upon comments when needing to change the code, whereas you can rely on comments to grasp what is happening in said code. But the same can go for self documenting variables. Sure they help you understand what the variable/function/etc. holds, but not what it does.

Almost like naming convention is looking at something through a telescope (very narrow point of view, but very concise) and comments (especially those at top of functions/Sprocs/algorithms that describe what is happening) are like looking with your bare eyes. You can get a jist of things, but you sometimes can't be sure that's accurate 100%.

(A backpacking saying is "never trust any sign you come across" Someone could have tampered with it since it was put up. Use it as a guideline, but not as a rule. I take a similar approach to comments in critical pieces of code. (Touching Credit Decision-ing for Auto Loans ... yep, gonna slow down and take it slow to make sure I don't screw anything up))


Roman numerals did not have a zero. It could only be used to represent counting numbers between 1 and 3999. As abstraction s go it failed to accommodate a large number of situations that Arabic numbers could.


I don't think that's right. Roman numerals allowed a bar over the number to indicate that it was multiplied by a thousand. One million, for example, was an M with a bar over it.

I agree about "counting numbers", though. So far as I know, it was impossible to represent fractions or decimals in Roman numerals.


They used `S` for "half", with dots for additional fractions of twelve.

https://en.wikipedia.org/wiki/Roman_numerals#Fractions

And here I thought I'd never need to know that.


Why Caramel? Why not just Lisp/Scheme? for the example.

Funny you should ask this question on HN. Have you read PG's essays on Lisp and the competitive advantage it granted his team in developing ViaWeb?

Your question might be about PLs, but in effect you are asking why somebody would prefer one abstraction over another.

Personally, I find it difficult to read and grok math. But if I write out stuff in Lisp s-exprs and use meaningful names for functions, etc, then I generally can understand a little bit better. Being able to "execute" such descriptions helps further.

Languages such as Lisp, Scheme, Smalltalk, Self (of the ones I'm familiar with) have simple syntax and powerful abstractions. They failed to gain "market share" due to perceived failings. However, they adhered to the philosophy of Occam's Razor.

I'll probably get flamed for saying this ... when you look at systems written in Lisp, the debates tend to boil down to people arguing over whether their abstraction is better than the other guy's. With a powerful language you can do anything in any way you choose. So the abstraction becomes the differentiating factor. Hence the emergence of not invented by me syndrome.


Specifically because Lisp/Scheme, as simple as they are, still add a lot of complexity on top of the λ-calculus that isn't needed at all. In fact, I think the λ-calculus has a shield against this very issue on Lisp/Scheme, which is the fact is is much easier to quantify what is the "best" abstraction for a given problem.


In your initial post, you said:

> The λ-calculus - a 70 year old system - already does everything that all those do, simpler and faster...

If you're saying that you can write programs faster in the λ-calculus than you can in Lisp/Scheme, I think you're kidding yourself. If you think they'll execute faster, I still seriously question your view. And if you think a medium-to-large program will be faster to understand if written in the λ-calculus, I think you're completely mistaken.


Of course I can, much faster. Maybe you do not see how high level the λ-calculus is... take a look on the Caramel syntax. I can translate line-by-line any Haskell program to Caramel. The λ-calculus, when given a decent syntax, is just Haskell without the types (but still has algebraic data structures identically, just no annotations). And I can be much more productive in Haskell than in Scheme, I think that goes without saying.

About the performance of the program itself, yes, λcalculus is faster than Scheme, by an order of magnitude, sometimes. For one, algorithms on church-encoded lists fuse by reduction, which means that the code below, in Caramel:

    map f (filter cond (zipWith (+) (map f a) (map f b)))
fuses to a single tight loop - i.e., it iterates through the lists `a` and `b` only once, and returns the result after that, creating no intermediate structure. Scheme would create 4 intermediate structures on this case. Since it is already 2~3x slower than the λ-calculus (running on GHC), that'd make it an order of magnitude slower in that case.


If you like Caramel, nobody here is going to tell you to use something else. Each to their own.

Agreed, λ-calculus is simple and clean. But what about the machine code being generated? Eventually, each concept in the abstraction has to be translated, often through several layers, to memory locations, register contents and the available instructions. Allowing for cache issues and out of order instruction issue. It is because of these and many other reasons that compilers, such as gcc, have gotten so big and complex.


Which complexities in particular do you find onerous?

Bear in mind that almost nothing I write is simple, self-contained, written in isolation, etc.


Macros (not necessary at all, just use regular functions and enable laziness), ints/strings/bools/lists/etc and all their hardcoded features (you can encode all that neatly on the λ-calculus). Every single addition that Scheme makes on top of λ-calculus is harmful in some sense - algorithms on list, for example, don't fuse because of that, making Scheme less performant than the λ-calculus; multi-argument functions make the whole language segmented and are much less convenient than curried functions... etc., etc.

R5RS, the simplest used spec of Scheme, takes dozens of page to merely describe the language. The λ-calculus can be described and implemented in a paragraph. That makes it much easier to create new backends, for example.


* IMO macros are occasionally useful, but YMMV. * "Hardcoded features" like?

I'm all for purity, but so far, I haven't seen anything IRL that backs up your claims/arguments.


https://mobile.twitter.com/wm/status/7206700352?lang=en

I love programming, but in the context of building great products. Languages are just a choose-your-compromise adventure, except JavaScript was chosen for you (it's fun!).

If Lisp powered Salesforce, I'm not sure anyone would describe that sausage as elegant. I'd love to see it consume a SOAP API... Or talk to a Mainframe (lol).

I use a lot of languages in every project and it's great. Purity is boring.


Boring? I don't want my languages to be exciting, I want what they produce to be exciting. I want my languages to be as simplistic as possible, and to allow the abstractions my problem domain require.


Surely binary is simpler than decimal, and yet humans rarely use it. Purity is nice, but there's a tradeoff with needing to get stuff done so you can pay the rent.


Decimal is easier for humans. But for computers it was a stumbling block until they decided to move from BCD to binary.

That is the power of abstractions, let humans have decimal and computers binary - letting the latter convert between them as required.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: