Indeed. C is generally called a general-purpose programming language (the first sentance of it's wikipedia even says that), as are most things we today consider... well, general-purpose programming languages.
Wikipedia even has an article for "General-purpose (programming) language". This term is already taken and in use in computer science for decades, and used more broadly than apparently the OP would like.
> A general-purpose language is a computer language that is broadly applicable across application domains, and lacks specialized features for a particular domain. This is in contrast to a domain-specific language (DSL), which is specialized to a particular application domain. The line is not always sharp, as a language may have specialized features for a particular domain but be applicable more broadly, or conversely may in principle be capable of broad application but in practice used primarily for a specific domain
It's kind of odd to call C a general purpose programming language today. When it came out, it was, just as it was a "high level" language, but would not be considered so today. These terms tend to be relative to other commonly used languages.
I would probably say "While the goalposts are always moving as to what might be considered a 'general purpose programming language,' Objective S is, to my mind, the furthest in that direction so far."
Wordier, but should rub fewer people the wrong way.
Actually I have books that call it middle level language, because basic stuff like strings and arrays are Assembly like versus something like Modula-2.
I'm also unable to identify something unique about objecitve-S that makes it suitable for "well architected programs" compared to what we do in ST already. I learn languages for new ideas .. and I tried hard looking for one here. Sometimes such new ideas are hidden, as I discovered was the case with Julia - where multiple dispatch combined with just-ahead-of-time compilation opened up so many opportunities for fantastically collaborating libraries .. in a (for me) unexpected way.
Thanks for the feedback, and I am sorry that you couldn't find it. The site is both a bit slapped together (I didn't submit it) and lags behind the actual project, which itself is a work in progress. So what's documented on the site tends to be the more mundane stuff.
Another difficulty is that it is really different, but (or therefore) in unexpected places. Coming from Smalltalk background, I would be looking primarily at what it does with messaging and objects, and there Objective-S is almost completely unremarkable. It has HOM built in, but that would be easy to add, it uses {} instead of [] for blocks and has some actual syntax for defining methods and classes. Whatever. ¯\_(ツ)_/¯
The interesting stuff starts with the polymorphic identifiers, the URIs. Which, coming from a Smalltalk background I would probably note as being slightly funky, but then move on to get to the interesting bits, because identifiers in Smalltalk aren't particularly relevant.
However, URIs are foundational to the REST architectural style, which turns the Smalltalk idea on its head: interfaces are state-oriented (GET, PUT, DELETE as verbs + complex identifiers), computation is hidden. In Smalltalk, interfaces are "computational" (message-based) and state is hidden. With ObjS, you can easily express systems in an in-process REST architectural style. See the "Storage Combinators" paper linked from the site and the "In Process REST at the BBC" book chapter (https://link.springer.com/chapter/10.1007%2F978-1-4614-9299-...)
There are also what I call "property paths", which can be used in store definitions. They're kind of like the URL routes you find in frameworks like Flask, Sinatra, Rails, but generalized and integrated into the language. In-Process REST :). These I haven't put on the site at all yet, partly because I haven't gotten around to it, partly because they're not published yet.
Here is a short example, which adapts some introspection functionality as a store/scheme/in-process REST "server".
This can then be served via HTTP, plugged into a generic GUI browser (which also browses filesystems) or combined with other storage combinators. Again, the paper gives a lot more detail.
Another example is from some recent experimentation with a Raspi I just wrote about (https://news.ycombinator.com/item?id=27099738). With a simple store, I can use the following code to turn on a GPI pin (hooked up to an LED):
gpio:17 ← 1.
OK, sort of nice, but so what? Well, I can connect things up, so if I wanted to get the LED to blink, I would hook up the pin to a blinker object:
blinker → ref:gpio:17
The → is a generic "connect these two things" operator, so maybe the generic "connector". In this case, it is connecting two dataflow components: the blinker is a source that repeatedly outputs alternating ones and zeros, and the ref: is a reference to the variable in question, rather than the value itself, and any variable can act as a sink, writing to it just sets the value.
I could also connect the blinker to stdout:
blinker → stdout.
In which case it starts writing 01010101... to the console. I can also connect the blinker to a file:
blinker → ref:file/tmp/alternating.txt
In this case, the file contents will oscillate between 0 and 1. And so on and so forth for dataflow-ish types of architectures. Of course, that also works for connecting up UIs. Note
So that's three architectural styles that are supported naturally by having the required connectors at hand:
1. Standard call/return in the form of Smalltalk-style messaging, extended with HOM
2. (In-Process) REST with stores, storage-combinators and property paths, supported by polymorphic identifiers
3. Dataflow, also supported by PIs.
And it turns out that with PIs, dataflow and storage-combinators, you get dataflow constraints almost for free, so that would be (4). In addition, there are notification protocols, which adapt between messaging and implicit invocation (5).
This is useful! Thanks for writing this out. I find in-process REST intriguing as it stands a little in contrast with OOP techniques. One possibility I’ve found with in-process REST is that it seems to make live patches feasible - more feasible than in erlang. I use the idea as the core of Inai - https://github.com/imaginea/inai (post describing it https://labs.imaginea.com/inai-rest-in-the-small/) ... so am curious to play with that aspect of ObjS.
I assume (in good faith) that it isn’t meaning general purpose the way that I interpret the word “general purpose.” But still... it does indeed immediately give an adverse reaction. This phrasing should really be adjusted to prevent further bad first impressions...
Objective-S is an architecture-oriented programming language based loosely on Smalltalk and Objective-C. It currently runs on macOS, iOS and Linux, the latter using GNUstep.
By allowing general architectures, Objective-S is the first general purpose programming language.
What we currently call general purpose languages are actually domain specific languages for the domain of algorithms.
Which is an interesting premise, but it could use a lot more explanation on what makes this language actually "general purpose" and not itself a domain specific language for the domain of algorithms (in particular, representing something other than algorithms where this language excels).
As it stands, it looks exactly like a domain specific language for the domain of "algorithms that expect to be run on a system with Cocoa or some approximation thereof". But I'm probably missing something, in which case that something could use some explication in the introduction or on the "about" page.
To me at least “general purpose” describes almost all programming languages with the exception of “special purpose” or “domain specific” languages like SQL, Prolog or XSLT.
I think if I were to summarize what that page says, it is that objective S is attempting to be an omni-paradigm language. That’s what they mean when they claim “the first general purpose...”.
That still seems like over the top marketing hype.
Authors first language might not be English... I sort of read that and the following sentence and thought they maybe should have been connected together as a single thought.
> The last few weeks, I spent a little time getting Objective-S working well on the Raspberry Pi, specifically my Pi400. It's a really wonderful little machine, and the form factor
and price remind me very much of the early personal computers.
The Apple II I bought in grad school in 1980 was roughly $10,000 in current dollars. I'm not sure how the price of a Raspberry Pi could remind him of this.
Commodore VIC-20 sold for $300, Timex Sinclair $100. I didn't adjust for inflation, as computers also largely haven't, and I wrote "reminds me". Not "is the same" or even "is comparable".
The Apple ][ doesn't even have the "computer in keyboard" form-factor.
And yes, the Raspi is unimaginably more capable. In fact, I still want to do a "how it started" vs. "how it's going" putting the Raspi next to my >$10K NeXT cube. The Cube with the 256MB, slow, huge, washing-mashine-noisy optical drive that can "hold your universe" (no it couldn't), vs. the Raspi's equally removable but silent and infinitely more portable microSD with 16GB (or more after-market).
And both computers come/came with a copy of Mathematica. And I also still have the box for my copy of ParcPlace (!) Smalltalk for the NeXT. Maybe I should make a tiny box for ObjS just to have the side-by-side?
there were a lot cheaper personal computers. eg. trs 80 or comodore 64 both sold for around $600. still a lot more than a raspberry pi, but about the same factor cheaper than a real computer at the time.
It is hard to encapsulate what is unique about a language in a pithy one-liner. This one is the best I could come up with so far.
And yes, I am also annoyed by hyperbolic claims and titles, for example I remember a paper claiming a "Language for Cloud Services" (not sure whether they specifically mentioned AWS). Turned out to be a minimalistic FP language with rudimentary concurrency support. Applicability to cloud services was an obvious extension left to the reader. Grmph.
> Is it really true?
Yes, I believe it is true. It has taken me many years to figure this out, and I realise that it is highly non-obvious to the point of being startling and yes, seemingly over-the-top. The "About" explains it a little bit further:
> By allowing general architectures, Objective-S is the first general purpose programming language.
> What we currently call general purpose languages are actually domain specific languages for the domain of algorithms.
Maybe this should also go on the home page?
Anyway, a super short and also still pithy and incomplete justification: All current mainstream programming languages are descendants of ALGOL. The ALGOrithmic Language.
In short, we started using procedures to both compute results, which was what we used computers for in general when we started this CS thing, and then incidentally also to organise those programs. This worked out OK, because this organisational mechanism matched what we wanted our programs to do. It largely no longer does, but the idea that we must use procedural/functional abstraction to organise our programs is so deeply and unquestioningly entrenched as to justify the term "paradigmatic".
In fact, I would argue that the fact that we unironically refer to our "algorithm DSLs" as "general purpose programming languages" shows just how deeply entrenched the call/return architectural style is.
So yes, to answer some of the sibling comments, you obviously can use these "algorithm DSLs" to solve more general, non-algorithmic, problems, but only because of Turing completeness. And even that is based on the notion of Algorithm:
Dynamic interaction of clients and servers on the Internet, an infinite adaptation from evolutionary computation, and robots sensing and acting are some examples of areas that cannot be properly described using Turing Machines and algorithms.
Anyway, coming back to day-to-day programming, the examples abound once you are aware of the potential for mismatch. (It's almost like confirmation bias in that way: once you know about it, you can see it everywhere...) For example:
I've run into plenty of situations where a streaming approach would be faster. The complexity of it always necessitates making a slower conventional version. (wait for all the data to load into memory and the operate on it) the conventional approach is easier to debug and get working. 90% of the time, the gains from streaming aren't worth the added effort.
Why is the "conventional approach" easier to debug and get working? Because it is supported in the language. That's why it is conventional in the first place. And so we keep doing things that are not quite right, and the code piles on.
I am sure everyone who has programmed for a while has had this gut feeling: this is far too much drudgery and detail work for what we're doing. I've had this since University, but it really hit home when I was asked to help on Wunderlist architecture. It was an ungodly amount of code for the iOS/macOS clients, and we were doing a fracking To Do List! And as Eric said, it is a problem of architecture. And it is hard to get the architecture right when there is a mismatch between the architecture that the program needs and the architecture that your programming language proscribes!
Now that's obviously not the only problem. But it is a biggy.
I've read the paper and to be frank: I'm taken aback at how you brush away FRP in Chapter 9. And with an example in Java streams, of all languages/frameworks.
Having to implement Builder methods? No named components/difficult to encapsulate because lambdas??
No, what you show with that example is not the "gentle tyranny" of call/return, it's the "gentle tyranny" of Java (which OTOH I find a surprisingly fitting phrase :) ).
Thanks! And sorry, I guess, I am still figuring this out and so it's not as coherent as I would like.
>I'm taken aback at how you brush away FRP in Chapter 9
Sorry, page limit, I was simply out of space. I've done more thorough takedowns^H^H^H^H^H^H^H^H^H^H^Hanalyses of Rx elsewhere. (FRP is really something else, as Conal Eliot tirelessly keeps pointing out).
Mind you, bringing dataflow to mainstream programming is a Good Thing™, and in some ways Rx accomplishes that. But the hoops you have to jump through to get there are...oh boy.
> Java streams
Hmm...I found the issues in other frameworks to be very similar.
I would not call English a programming language. Programming languages, formal languages designed for instructing a computing device, are pretty different than natural human languages.
Actually, more like Akkadian (the dialect that the /Code of Hammurabi/ is written in) - it isn't the first, but is the best-preserved set of rules and instructions - while not a program (as the Law isn't exactly a monoid[1] of linear instructions that mutate state) it could be used the basis for one.
> Objective-S is the first general purpose programming language
Those kind of statements annoy me to be honest. Is it really true? Or is it over-the-top marketing hype?
For me – and I'm sure I'm not the only person who feels this way – it creates a negative first impression.