33 comments

[ 2.5 ms ] story [ 102 ms ] thread
What if my name is "anonymous user"?

Anyway, primitive types in java is one of the reasons, why java has success. Try to do image processing or fast networking, while each byte is represented as an object.

An object is an interface, nothing precludes optimising representations either specifically (tagged pointers, unboxed values) or generally (collection strategies and JIT unboxing). The former being what C# does, its primitive types can still be interacted with as objects, you can even add new methods on `int`.
I have an experimental and somewhat half-baked programming language where all types are anonymous; type names always refer to interfaces. It then does global type inference to decide whether the thing you're referring to is a primitive type or an object for the actual implementation.

What this means is that at the semantic level, the language doesn't distinguish between objects and scalars, so avoiding the horrible schizophrenia that languages like C++ and Java do --- you can subclass an integer just as easily as you can anything else. Performance is really good, too, mostly.

The downside is somewhat unpredictable behaviour due to invisible boxing and unboxing. e.g.:

    function complexExpression(x: int) {
      // do something expensive with x
    }

    complexExpression(4);
    complexExpression(numberlikeObject);
The type inference will see that complexExpression() is being called by both a scalar and an object, which means that x needs to be implemented as an object pointer, and the literal 4 needs to be boxed. This means the calculations inside complexExpression() will end up being a lot more expensive due to boxing and unboxing overhead.

I should readdress this at some point; it was a really nice thing to write code for.

http://cowlark.com/cowbel/example.html

You could specialize for primitives, e.g. under the hood generate complexExpression_int() and complexExpression_ref(). It wouldn't be too bad in terms of code size, because you only have to specialize primitives, and all reference types can share the same implementation.
Yes, that'd be the obvious thing to do, but I think right now it doesn't (I could be wrong; I haven't looked at the code for ages).

I did at one point try to specialise everything. The results were hilarious...

    var a = cons(cons(cons(cons(empty, 1), 2), 3), 4);
As the left-hand-side of each cons was a slightly different type, it ended up generating four different versions of the cons function!
Try to do anything where each struct is represented as an Object... oh wait, in Java, it is!
(comment deleted)
Little known fact: you can't have objects all the way down. At some level you need to add machine integers together. For that you need the internal representations of two different objects at once, not just their responses to a bunch of methods. If your language is objects all the way down, that's fundamentally impossible.

In fact, Smalltalk's VM has special code that detects when you try to add two small integers. That's similar to "abstract data types" in ML or "class-based encapsulation" in Java, as opposed to "object-based encapsulation" which is the cornerstone of Smalltalk.

> At some level you need to add actual integers together. For that you need to access the internal representation of both integers at once

Not necessarily.

https://en.wikipedia.org/wiki/Church_encoding

Yeah, fair enough. Updated my comment to say "machine integers" :-)
In a language without machine integers exposed to the programmer, there may be no way within that language to see any machine integers. There is a further "way down", but not from within the language.

A proposition about an implementation aspect of the language you're working in is testable in that language if a program in that language can produce output which is different based on whether or not that proposition is true. If the proposition isn't testable in that language, then it doesn't lie on the "all the way down" path which begins inside the language.

This is not necessarily true.

There has been several Lisp dialects (3-Lisp and T project) based on infinite tower of interpreters. You can build a language where the point where the rubber of abstraction hits the road of reality is nowhere to be found.

Very interesting! I've started reading the 3-Lisp paper [1] and it's a lot of fun.

I'm not sure if it's really a counterexample, though. Does 3-Lisp claim that you can only interact with values by calling their methods, or something like that? For example, can you impersonate a cons cell?

[1] http://cs.au.dk/~hosc/local/LaSC-1-1-pp11-37.pdf

Everything has to resolve to an image/representation at the hardware level.

> For that you need the internal representations of two different objects at once, not just their responses to a bunch of methods. If your language is objects all the way down, that's fundamentally impossible.

?

The machine instructions that operate on images are register based. You load the operand image into register(s) and invoke semantic (e.g. addition unsigned 32-bit), storing the result in registers.

Given that fact, your line of thinking would generalize to "there are no object oriented languages", since even getting the length of an array of Ducks must resolve to logical and/or mathematical ops at the machine level.

> .. special code detects ..

That sounds like an optimization to deal with the reality of contemporary hardware.

Amending it to say machine integers doesn't help. There's a neat trick used by at least one language implementation (unfortunately the name escapes me) where the language is fully semantically defined in itself, but where the implementation then "cheats" by recognising certain patterns in the definition and replacing them with lower level machine representations.

So you can have objects all the way down if you like. You just need something (such as an interpreter or compiler) that recognises your own self-consistent definition and swaps out pieces of it for a more reasonable implementation.

Admittedly it might be seen as a bit of a cheat, but I quite like it because it treats the mapping from a logically "pure" model to machine as an implementation issue. I'm working on a Ruby implementation and took the opposite model of having a lower level representation that I can "escape" into to implement the low level details, but I'm tempted to re-implement the small parts of the core that I can't do in pure Ruby to work the same way, as a experiment (though I better actually find some time to finish making it self-hosted first)

You can have objects all the way down --- when "all the way down" means, down to the "no user-serviceable parts" panel kept firmly in place with security screws.
Well there are version control tools in Smalltalk land. The primary one that ships with Pharo is called, Monticello [0].

Images are also a huge advantage which the author has obviously not had time to exploit.

Knowing next to nothing about Smalltalk before the summer I checked out Pharo and wrote a small application to scrape the HN front page and display the links in a Painter window. I watched a few videos, read some tutorials, and eventually had a working Smalltalk program in a couple of days. It was actually a pleasant experience.

A typical workflow starts by writing a snippet of code in the playground that instantiates the program you want to run. You execute it and get dropped in the debugger. You slowly add the missing methods and tests, stepping through the debugger as you go, and eventually your program runs. If you ever need to take a break you can save your image -- debugging session and all -- and pick it up later. There's no need to load up your source code and try to rebuild your application state to get to the point you were at when you last left your work.

That's really powerful for interesting systems like the Moose platform [1].

Overall I think the author is too biased to his existing tools to appreciate what Smalltalk is really about.

[0] http://pharo.gemtalksystems.com/book/PharoTools/Monticello/ [1] http://moosetechnology.org/

Original author of the blog post here. I find it interesting that your takeaway from my blog post is that I am writing unfavorable over smalltalk. I quite liked it. I think I mentioned that I was checking out Smalltalk, didn't claim to summarize longer experience with it.

Moose looks interesting indeed.

It did come off that way. If you are interested you should definitely keep exploring. It's an interesting system.
Smalltalk is the future the GUI promised us. But something went wrong in the '80s and we got stuck with file systems, terminal emulators and command line arguments.

Isn't it absolutely crazy that we have laptops with 6-megapixel screens, and we use those capabilities to simulate a 40-year old video terminal that in turn simulates the behavior of an even older line-based Teletype machine? [1]

Programming today is fundamentally the same it was on a PDP-10 many decades ago, except that the unintuitive CLI interfaces have been propped up by fast web search: "Just google it, no big deal."

[1] http://www.linusakesson.net/programming/tty/

Lisp Machines possibly even more so, these were entire systems built in lisp from the ground up, extensively documented, introspectable and editable.
I'm sympathetic to the GUI dream, but do note that language is far richer than pictures: we graduate from picture-books to literature, and from pointing and grunting to speaking.

I do think that a Smalltalk future might have actually managed to be the best of both worlds, combining images and text into one coherent whole. But it never really came to fruition.

As things are, since I may not have both, I'll choose the power of text over the ease of pictures.

To me, the GUI dream isn't really about pictures -- it's about structure. Humans are much better at understanding visual and symbolic representations of structure than prose. Purely textual interfaces don't take advantage of that.

The structure that we currently have is file hierarchies and URLs (just another form of Unix-style path strings), and files containing sequences of text with no more structure than line breaks and indentations -- and after 40 years, we haven't even agreed on how to represent those in ASCII. The whole thing is barely removed from sectors on disk.

Smalltalk's class browser let you drill into a live hierarchy of objects and edit them in place. That's already much more advanced than our static blobs of text in a lifeless path hierarchy. And that was in 1975.

I've got to disagree, because representing everything as an object involves a serious amount of cognitive overhead. You're limiting yourself to things that can be represented as objects and still make sense, plus you've got to write the code to make your ideas fit into the object box (methods, interfaces, this, public private etc).

I've been working on some networking protocols, and I started by modeling each node as an object. Seemed to make sense. But there's a lot of overhead. Send, receive methods etc etc, and then you've got to instantiate them and then collect the data from the objects afterwards to see how the network did. I switched my code over to being a bunch of stateless functions that operate on a network graph and stuff got a lot less verbose.

This is not necessarily always the case, but I would hate working in an environment where I was forced to always use a very specific metaphor for my work.

The more high-level you are, the harder it is to be interoperable.
> Isn't it absolutely crazy that we have laptops with 6-megapixel screens, and we use those capabilities to simulate a 40-year old video terminal that in turn simulates the behavior of an even older line-based Teletype machine?

Nope!

The fonts are anti-aliased to hell and scalable; and just look at the breathtaking colors!

Moreover, many GUIs are like this: a smattering of miniature tele-types (called "edit boxes" or "input fields") that you must switch among to prepare input before clicking Submit, which is just a thinly-veiled carriage return (and in fact bound to that key).

... smattering of miniature tele-types (called "edit boxes" or "input fields") that you must switch among to prepare input before clicking Submit, which is just a thinly-veiled carriage return ...

Just like a "screen" on an IBM 3270:

"Using a technique known as 'read modified', a single transmission back to the mainframe can contain the changes from any number of formatted fields that have been modified, but without sending any unmodified fields or static data." (https://en.wikipedia.org/wiki/IBM_3270)

That was a 1971 design. We have barely made any progress.

"Overall I think the author is too biased to his existing tools to appreciate what Smalltalk is really about."

Agreed. The author is clueless.

(We detached this comment from https://news.ycombinator.com/item?id=10637544 and marked it off-topic.)

> The author is clueless

Maybe so, but since your comment is only name-calling [1], you shouldn't have posted it here.

Since you know enough about this fascinating topic to identify cluelessness, it would be much better to post a comment with real information that could teach readers something about it. If you don't have time to do that, posting nothing is always an option.

1. https://news.ycombinator.com/newsguidelines.html

(comment deleted)