Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The article does not mention Smalltalk's uncommon syntax as a deal breaker. Not many langs with uncommon (not C-like) syntaxes have managed to become widely used. I think that that is known to those who ordered investment in Java and C#.

To me Smalltalk feels too integrated, which is a problem for me. I like a language that's small in it's (open source) core, with lots of (competing) integrations (IDE, testing, profiling) available. It helps me not to feel locked-in to an ecosystem.



I had that same reaction towards lisp. Not sure which flavor it was, but when I first saw it 10 years ago or so, the syntax put me off so hard that I wrote the whole thing off. Didn't look at another lisp for a few years, until I came across Clojure.

The syntax was again "ugly" but some people were so excited about the language that I had to look into it, which is when I learned why the syntax looks the way it does, and how powerful it is because it looks that way.

Needless to say, I felt monumentally stupid, not just for having done myself the disservice of not looking into lisps earlier, but for having the audacity to write things off out of "ewww" feelings. A perfect exhibit of programming being a pop culture and me being a mindless consumer.

Thankfully I learned my lesson, which came in handy when I came across Smalltalk. The syntax is powerful [0], and good luck getting that kind of power out of any conventional syntax language.

[0] among many other aspects.


Great comment.

At the same time, after 35 years as a programmer (mostly in C++), it is rare these days that I find myself ever thinking that my inability to get "power out of [...] syntax" is a problem when I'm working.

The problems I feel I face these days, working on a mid-size (700k LOC or so) complex, native, multithreaded, realtime, creative software project, are mostly just caused by the fact that what we need to do is hard, no matter what the language is.

I feel as though attempts to elide those difficulties through syntax really do almost nothing to address the underlying hardness of the problems. One example: it is true that there are quite a few places in the codebase where using lambdas/anonymous local functions would be handy. We wouldn't have to create actual named methods to tidy things up, even though we only use them once. But none of this relates to the actually hard stuff: managing UX and responding to changing and expanding user expectations.


Never blame the user for the problems of the system. Lisp fans know the syntax is a huge problem. It has been for decades. Their solution is to blame the user. This approach is absolutely doomed.

Clojure actually fixes quite a few of the syntax problems with previous lips, but doesn't go nearly far enough so they still have the same problem.


What happened is that "better syntax" turned out to universally fail in practice. It's not that we decided to blame the user. But there's 60 years of empirical data that points to M-expressions being irrelevant and waste of time. And people who don't have experience with other languages tend to pick it up just fine, even if the formatting is sometimes atrocious (AutoLISP community is an example).


M-expressions did fail. Their greatest failure is that they persist as a universal strawman that's useful for killing any conversation about evolving lisp's syntax.

M-expressions didn't just fail because they were unnecessary; they also failed because they just weren't a very good syntax. They were more cluttered and less readable than S-expressions, while adding no real practical value.

But Clojure has arguably demonstrated that you can evolve on Lisp syntax without going to M-expressions, or even changing S-expressions all that much, just by adding a few new bits of literal syntax and sprinkling some clever macros into the standard library. (A macro invocation may not technically be syntax from the parser's perspective, but it sure feels like syntactic sugar from a user experience perspective.)

And, while I haven't actually tried them at all, I've at least been intrigued by t-expressions. They seem to achieve some nice things like git-friendliness and easier visual scannability without sacrificing on macro-ability.


M-expressions happen to be catch-all name for various non-Sexp syntax forms.

As for Clojure, TBQH I'm not too convinced that few sigils make all that difference in writing, in plus or in minus. But I am far from my 10k hours in Clojure so YMMV


> M-expressions happen to be catch-all name

They're that, but it's also used to describe a specific syntax. IMO, the more general definition is not particularly valuable and should be discarded. Because it's just not useful to paint m-expressions, i-expressions, t-expressions, etc. with the same brush like that. Doing so just muddies the waters. If you want a general-purpose term for alternative lisp syntax, why not "alternative lisp syntax?"


Smalltalk and C were developed around the same time, which renders any argument to the effect of, "Smalltalk didn't get popular because it didn't use the C-style syntax that everyone knows and loves," uncompelling by virtue of being anachronistic.


Except that C-style syntax existed before C.


The earliest language I know of with syntax that really looks like C's is B, which is a whole three years older than C.


I remember people using the phrase Algol style, but that has faded out.


People overestimate C syntax importance, especially earlier on - when a lot of development was in non-C languages.


I agree. From my perspective, C syntax was just another syntax... Pascal, Lisp, BASIC, dBase, Fortran, DOS BAT, unix shell, and various assemblers.

That changed once C/C++ look over, but until then it wasn't something large proportions of programmers knew and had an affinity for.


so which language besides python is really really successful and doesn't bave C syntax?


Fortran, Cobol, Algol, Pascal, Basic, Rexx, Ruby and Lisp have all experienced success relative to the size of the software industry during their peaks - perhaps most notably Visual Basic and Turbo Pascal.


Fortran, COBOL, BASIC, Algol, and Lisp peaked well before C was popular (in some cases peaked before C existed), and Algol (obviously), Pascal, Python, and Ruby, are all languages in the Algol-derived syntax family, like C.

Visual Basic is probably the biggest success of a non-Algol-derived general purpose language after the dominance of C as anything other than mostly-legacy.

There are some others (Erlang, some Lisp-family languages [recently Clojure], some ML family languages) but languages with Algol-derived syntax are still far and away dominant.

There's also lots of not-general-purpose languages without Algol syntax (SQL, for instance.)


SQL


Depends what you mean by successful.

If you're willing to accept heavily entrenched ("a lot of development" as in the parent), then languages like Fortran and COBOL are highly successful. They underlie an enormous amount of infrastructure in the world.


I think it might be even simpler and worse: ecosystems are important, languages aren't. The "bitter lesson," if you will, of languages.


Smalltalk is really quite small. All syntax is described in here: https://gist.github.com/jacaetevha/3795784


Python is one of the most widely used languages out there and doesn't have C-like syntax really


Python is not exceptionally C-like, but a typical python script is readily understood by someone familiar with C. Smalltalk, on the other hand is not. This LOC is from the wikipedia example page:

#($a #a "a" 1 1.0)

There's no way a C programmer can know what that means without looking it up.


This comment makes me feel a little bit sad.

It doesn't take too much breadth of knowledge to recognize those all as different kinds of literal syntax, even if you don't know the exact details. #(...) for some sort of collection, probably a list or vector, $a and #a for different kinds of atomic value, even if it's hard to guess whether any one of them represents a symbol, a character literal, a perl-style variable reference, or something else.

If such prosaic syntax is really so unfamiliar-looking nowadays, it really speaks to a major gap in how people are taught about programming. Comparable to if it were common for younger mechanical engineers to not even recognize a slide rule when they see one.


If said C programmer has truly never seen or heard of anything but C, I'm sure a similar line of Python (and the end result) would seem quite confusing as well; ['a', ({1j}, {1: 1.0})]


Is that a typical line of smalltalk? I mean if this is representative I can understand why C-like syntax won. Surely a language with descriptive names, and a call syntax resembling:

    subject.verb(arguments)
Is more intuitive than the example you've given.

Of course it's also quite possible to write an equally cryptic line of C code.


No, this is not a typical line of Smalltalk. That would be considered a very sloppy array indeed. I think it's just there to demonstrate the different literal notations in the language.

Smalltalk is actually quite readable in practice, though the keyword syntax seems to throw off experienced programmers from other languages. It's worth noting that the language was originally tested on children, so it was also designed to be easy to read and learn.

The equivalent of your C code above could be something like:

    MyObject doSomethingWith: anArgument


aka Objective C

:)))


Python, like C, has basically Algol-derived syntax (it's not far from the Pascal-inspired pseudocode that was dominant form of pseudocode for a long time); Smalltalk does not.

It's not a direct linear descendant of C the way C++, Java, C#, and lots of other relatively recent languages are, but it's still a lot closer to C than Smalltalk is.


There's not many examples beyond this though... it does seem to be the case that people either choose C syntax for successful languages, or those languages are successful possibly because of C.

Why did Rust move from an ML syntax to a C syntax?


We wanted to cater to an audience of systems programmers, so we tried to stick to a familiar syntax where possible.


I know this opinion will not be received well, but I'm really sorry this extended to things like semicolons, snake_case, and the overloading of the term vector to refer to variable length arrays. I'm a big fan of many of the decisions made in Rust, but those are things which I wish we could have let die in the systems programming language of the last decades.


It's cool. I strongly prefer those things. That's why no single language will ever rule them all.


To each his own, but out of curiosity what do you like about using the term Vec for dynamically-sized arrays? To me it just seems that it's an inaccurate usage of a term with a precise mathematical meaning (what is a vector of strings exactly?), and as somebody who works with linear algebra a lot in code, it's a frequent point of consternation to have this built into two of the most relevant languages for achieving high performance.


Meaning is inherently contextual, so different things meaning different things in different contexts is the norm, not the exception. Do I get upset that a "string" isn't made of "thread"s?

It is true that mathematics is closer to programming than tailoring is, but you can't escape this issue. So I don't get particularly worked up about it.

(This context is why this matters too; "vector" as a term for this is established, just like the linear algebra term is established.)

(I do like to joke about getting worked up about this though, but I pick on String, which should be StrBuf, instead of vectors.)


So I generally agree with your point, and I'm not trying to say this is some giant issue which makes Rust and C++ unusable - on the contrary I think it's a minor annoyance at worst when trying to carve out a naming scheme for my own components.

But for the sake of internet pedantry, you seem to be saying that calling it vector is acceptable because it's established, not that there are any inherent advantages to this right? Because I would argue that we can and should take the opportunity to turn the page on imprecise terms of art which only exist for historical reasons.

Even looking at Rust, I'm very glad that char|short|int|long has been replaced with i8|i16|i32|i64 even if the former are terms of art which everyone can understand.


I am at least saying something similar to what you're saying. The inherent advantage is familiarity. You may not consider that inherent. That's okay too :)

Please excuse my WIP CSS, but I wrote a longer bit about this over at https://steveklabnik.com/writing/the-language-strangeness-bu... . I think that, for languages that intend to be adopted broadly, you have to choose carefully where you diverge from existing practice. Sometimes, you have to change, after all, that's how progress even happens in the first place! And sometimes, you're forced to change, because you don't truly have an analogous situation.


So I agree with the thrust of the point of your article as well - I guess my only point of disagreement would be where I would have placed something like naming vectors in terms of the trade-off between progress and familiarity, which admittedly probably has a lot to do with my particular domains of programming. However it does seem like a bit of a missed opportunity given the overlap between people who care about performance, and people who are working a lot with linear algebra in fields like computer graphics, simulation and ML. But I do understand that the line has to be drawn somewhere.

(On a side note, the CSS is perfectly fine, and I've been looking for a static alternative to Ghost for blogging, so I might give next.js a try)


Totally, 100% get it :)

Ah so, next is a way to make websites in general; the template linked is a good one for a blog though. I've had pretty positive experiences with next so far; I just re-did my blog in a hurry over the weekend for unrelated reasons, so it's pretty much just the template at the moment.


> what is a vector of strings exactly?

You can have a vector of integers, a vector of real-numbers, why do you think a vector of strings doesn't make any sense? Strings can be given a well-defined ordering. You can think about strings as a points along a string-line, if you want to.

For example - Java often names packages using co-ordinates (vectors) in an n-dimensional string space. Seems to make sense to me?


Maybe in some technical way this is correct, but when I'm pushing a string onto a vector of strings, I'm not thinking about conceptually adding a dimension to my vector in string space.

And how would you compute the cross product of <"foo", "bar", "baz"> and <"apple", "orange", "banana"> exactly?


> And how would you compute the cross product of <"foo", "bar", "baz"> and <"apple", "orange", "banana"> exactly?

Cross product isn't a well-defined operation. The wedge product[0] would be <a,b,c>~<x,y,z>=<<ay-bx,az-cx,bz-cy>>, assuming I didn't get the signs wrong again. That would require scalar multiplication and subtraction of strings, though, neither of which are generally well-defined.

If you substitute in string multiplication (ie concatentation) and addition of negatives (alternation and reversal, the latter of which is only vaguely justified by anticommutativity of multiplication), you get:

  << /fooorange|elpparab/ ,
     /foobanana|elppazab/ ,
     /barbanana|egnarozab/ >>
which frankly sounds to me like a pretty good argument that vectors of strings make no sense and shouldn't be supported, but maybe someone working on parsing algebras could come up a more useful interpretation.

0: http://en.wikipedia.org/wiki/Wedge_product

Edit: FWIW, wedge product of NaN makes perfect sense: <NaN,NaN,NaN> ~ <NaN,NaN,NaN> = <<NaN,NaN,NaN>>.


> And how would you compute the cross product of <"foo", "bar", "baz"> and <"apple", "orange", "banana"> exactly?

How would you compute the cross product of <NaN, NaN, NaN> and <NaN, NaN, NaN>?

Some vectors don't have a useful result for cross product, even if they contain 'numbers' and even if you can get some kind of result out.

Same with dot product of a string. Doesn't make much sense... so probably don't do it.


> even if they contain 'numbers'

Vectors don't 'contain' numbers, a vector is a multidimensional value. The fact that a C++ vector is conceptually a container for values more than anything else is a reason why 'vector' is a poor name for this component.


Yes they contain a number for each dimension. Not sure what you think the point of debating individual words like this? What practical problems do you think there are?


You're the one arguing from the extremely strained logic that because ordering rules exist for strings, this somehow means that C++ vectors have anything to do with mathematical vectors in the mind of the average programmer.

The practical problem is, when you do a lot of work with linear algebra, you would really like to have the term vector to use for its canonical mathematical meaning rather than having it reserved for a data structure which is not suitable for that purpose.


Well it makes sense to converge towards something right? Unless a programming language is using a radically different paradigm, like Lisp or Prolog, or if it is purely a syntax experiment, why not go with a C-like syntax and have every programmer in the world be able to instantly ready your code and basically understand what's going on.


> There's not many examples beyond this though...

Ruby, though still in the Algol-derived syntax family, is even less C-like than Python.


That's true, and that's probably why even though I have had to modify ruby code and write simple scripts at various points in my career, I never got to the point where I fully grep the syntax. Maybe that's why C-like syntax is so popular.


I'd say, no it is simplified C-like syntax in disguise.


I agree. Although Python is the best kinda counter example.

If you remove semicolons and use indentation over curlies in C it will look pretty pythonesque.




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

Search: