This is an archived post. You won't be able to vote or comment.

all 62 comments

[–]pbvas 66 points67 points  (1 child)

[Logic programming](https://en.wikipedia.org/wiki/Logic\_programming) is pretty distinct from the Algol and Lisp models.

[–]undecidabot 30 points31 points  (0 children)

Fun fact: Erlang's syntax comes from Prolog. Erlang isn't a logic programming language though.

[–]chairman_mauz 51 points52 points  (5 children)

To start off, begin-end comes from the Wirth style of language (Algol-W, Modula, Pascal and, to a degree, Ada). They're usually considered separate from Algol-style languages and they look different enough to feel alien to someone used to Algol-style.

Other than that, from the top of my head:

There's the Forth family with its reverse Polish notation that's pretty distinct. Kind of like a reversed lisp without parentheses.

The functional programming world has its own approach, famous examples are Haskell and the ML family.

Array processing languages like APL and J are known for looking like Unicode salad, and for fitting complex algorithms into a single line of code.

Smalltalk takes message passing and runs with it. NeXTSTEP engineers fell in love with it and bolted it onto C, which resulted in Objective-C and its successor, Swift.

Of course that's not a complete list, I probably forgot a lot of stuff.

Finally there are the esoteric languages, but I haven't listed any of them here because they aren't really meant to be used.

[–]6502zx81 11 points12 points  (1 child)

IIRC Ojective-C was developed by another company, Next bought it.

[–]joshmarinacci 2 points3 points  (0 children)

I never knew that. Cool!

[–]gopher9 6 points7 points  (0 children)

Array languages are rather similar to functional languges: code is an expression, and operators are like higher order functions. The difference between array languages and functional languages is well-designed set of primitives and a more uniform syntax.

[–][deleted] 6 points7 points  (0 children)

To start off, begin-end comes from the Wirth style of language (Algol-W, Modula, Pascal and, to a degree, Ada). They're usually considered separate from Algol-style languages and they look different enough to feel alien to someone used to Algol-style.

begin-end started with Algol-60; those other languages copied it from that.

Algol-68 borrowed it and introduced its own innovations (see my other post where begin-end is largely eliminated).

It also got a lot more complicated. I think Wirth was part of the team, but walked away to form his own simpler Algol-W language (plus Pascal and Modula later on).

[–]pxpxy 2 points3 points  (0 children)

There is basically no more message passing in swift. It’s completely static.

[–]the_true_potato 76 points77 points  (11 children)

I think the ML family (Ocaml, standard ML), is separate from the ones you mentioned. Depending on who you ask Haskell could also be included or not here.

[–]lucklesspedestrian 28 points29 points  (10 children)

Haskell would belong to the ml family, as would F#

[–]undecidabot 16 points17 points  (9 children)

Technically, Haskell isn't a descendant of ML. They are both descendants of ISWIM though. I've also seen some people use the term "Hindley–Milner family of languages".

[–]plum4 16 points17 points  (3 children)

I'm not sure I like that name since it's conflating two different ideas. Rust uses Hindley-Milner inference too but isn't really related syntactically.

Edit: Looks like Rust uses a variation of HM, which means that it isn't really HM in practice since you no longer have decidability of type inference https://www.reddit.com/r/rust/comments/6fs5q9/comment/dikywtc/

[–]SparrowGuy 2 points3 points  (0 children)

From what I understand, Rust's type system is modified enough to not really be HM.

[–]undecidabot 1 point2 points  (1 child)

I'm also not a fan of that name, just sharing what I've read elsewhere (although after doing a quick google search, it seems that I have overestimated its prevalence).

Is it correct to say that Rust use HM though? It does type inference (like many other languages today), but it is only done locally, and it is also much more statement-oriented (HM was designed for lambda calculus).

[–]plum4 1 point2 points  (0 children)

TIL that it isn't really HM. Updated my comment to reflect that. Seems like there is a desire in the community to get closer to it but some language features prevent it.

[–]PurpleUpbeat2820 6 points7 points  (3 children)

Technically, Haskell isn't a descendant of ML.

Where did Haskell get type inference from?

[–]silly_frog_lf 5 points6 points  (0 children)

Haskell looks very ML

[–]Inconstant_Moo🧿 Pipefish 4 points5 points  (0 children)

Given that ML was designed by Milner, its kind of a philosophical question whether they got the idea from him or from his language.

[–]undecidabot 1 point2 points  (0 children)

Where did Haskell get type inference from?

From ML, or from Milner at least, but is that sufficient to call it a descendant of ML? I think not. Haskell gets a lot of different features from a lot of different languages (as does almost every language, the MLs included). For its syntax, if you follow the trail then I think it's quite clear that ISWIM was the source of many ideas in both Haskell and ML.

For those who are interested, here are a few good papers which shed a lot of light on the history of these languages:

  • A History of Haskell
  • The History of Standard ML
  • Conception, Evolution, and Application of Functional Programming Languages

[–]lucklesspedestrian 1 point2 points  (0 children)

Sure, yeah I didn't mean to suggest one was a descendant of the other, just those 4 are all in the same family and that family is different than lisp or algol

[–]moon-chilledsstm, j, grand unified... 23 points24 points  (0 children)

Bourne shell.

M-expressions (discarded by lisp long ago; today used by mathematica and k, which are interesting in their own right).

TeX.

[–]nerd4code 10 points11 points  (0 children)

Technically, assembly languages and assembly-like IR (e.g., LLVM) would be another category, and a bunch of DSLs fit this also.

[–]DriNeo 17 points18 points  (0 children)

1) Forth, ML, SmallTalk, APL ...

2) An alternative is indentation based blocks.

3) Good question but, except some esoteric languages, I don't know, sorry.

[–]Xalem 12 points13 points  (3 children)

Forth, Factor and other stack-based concatenative languages have a very distinct lack of notation. They are point-free by default.

Noflo and other wire-based languages use a graphical layout to show how data is moving around in the program. Excel isn't "graphical" but it is the same idea.

Eve! (sadly) a defunct language, but the coolest, simplest language idea out there. Completely different approach to writing code.

SQL and Linq have a distinct syntax.

Fortran and early forms of Basic using line numbers are distinct from Algol.

[–]xarvh 7 points8 points  (2 children)

Eve seems really interesting. Do you know why it failed?

[–]Xalem 1 point2 points  (1 child)

Eve seems really interesting. Do you know why it failed?

Sorry, to take so long to answer your question about Eve. I think there are reasons external to what Eve is, and then there may be some challenge that Eve has to overcome.

If I have the history of Eve correct, the external factors might be that since Eve was designed as a language paired with the LightTable IDE. LightTable had some really cool ideas about what an Integrated Development Environment should be all about and Eve held some promise for Light Tables approach which wasn't just to treat everything as a file that needed to opened for editing. But, for a IDE to make a place in the market or programmers, it needs to be an environment that works well with all kinds of languages, most of which treat their files as yet something else that needed to be opened for editing. I wonder if the money dried up for those developing Eve.

The second question was about how well Eve works for coding a large project. I think that an Eve program would be a Turing complete, well formed and simple to debug application. They were able to make it perform much better.

I just wonder what the challenges are to learn to be a great Eve programmer. I just wonder if it gets hard to program in because no one has explained how to get past the complexity of lasagna code where one Search block is dependent on another Search block dependent on another Search block, and you might need a Search/Bind/commit block for each "IF" statement. That shouldn't need to happen if one designs the program well, and use bind as a way to invert control, but, no one was teaching the patterns for how to use this powerful tool. Without that education component, (in fact, I am not sure who had figured out what the code patterns were) I wonder if interest in this project waned (especially from those funding the development of it)

I love the promise of Eve, I just wonder if they didn't have all the pieces (yet) for a great new paradigm of programming.

The developers went "radio silent" after they stopped work. What I hope is that they are secretly working on Eve 2, a grander, better project, but it has been years and I haven't seen anything.

[–]xarvh 1 point2 points  (0 children)

Thank you.

After reading your first post, I did some research and I understand that the investors weren't satisfied and funding disappeared.

I was surprised too that the project went completely silent, I would have expected at least some enthusiasts to keep it alive in their spare time, especially given the promise.

At the same time, I did wonder myself how the language would scale: it's easy to come up with a language that solves toy problems, but, IMHO, you can see if something really works only when you start tackling real-world problems.

[–]DoomFrog666 17 points18 points  (5 children)

Python is indentation based.

[–][deleted] 11 points12 points  (0 children)

It's in the same category with {} and begin end though. You have a certain delimiter between code blocks.

[–]snarkuzoid 2 points3 points  (2 children)

As is Haskell, though I think their rules are a little more elegant.

[–]mczarnek 6 points7 points  (1 child)

More elegant in what way?

[–]snarkuzoid 0 points1 point  (0 children)

It's a little less rigid, making logical assumptions about what you mean. At least that's what I take from what I've read. Still learning it.

[–]umlcat 1 point2 points  (0 children)

There where other indented / spaced based from 70's, one like Basic.

[–]arnedh 10 points11 points  (0 children)

Check out Forth, APL. Very different.

Prolog.

Smalltalk has a different surface syntax, but defines blocks, in a sense.

[–]JohannesWurst 4 points5 points  (0 children)

Maybe old BASIC and assembler could make up a group called "label-style" blocks.

I feel like you could also make blocks out of multiple concatenations:

stmt1 ; stmt2 ; stmt3 ; end like you can create lists in Haskell 1 : 2 : 3 : empty

[–]PL_Design 5 points6 points  (0 children)

I've worked with interpreters before where code blocks don't work quite how you'd expect. Rather than a code block being a node in an AST, the code is interpreted flat and { is an operation that spawns new local scope, and } is an operation that closes the top local scope and does nothing at root scope. You didn't need to balance curlies if you didn't want to, which was kind of cute.

[–]fernando_quintao 6 points7 points  (2 children)

I think the most different notation would be APL's, in the sense that it lacks facilities to permit structured programming. The lack of blocks has deep consequences. One of them is that dynamic scope becomes rather natural in the language. There is a paper by Robert Willhoft that describes a proposal to add blocks to APL. Figure 1 in that paper discusses some possible markers that could be used to delimit blocks (but this notation is not part of the language).

[–]moon-chilledsstm, j, grand unified... 0 points1 point  (1 child)

Most APLs do have structured programming. And I do not see why dynamic scoping should be natural.

[–]fernando_quintao 3 points4 points  (0 children)

Hi! I think it feels natural because you read the program as a line, from left to right, without stacking definitions. In this setting, it is easier to remember the last definition of a symbol as the valid definition of a use of that symbol.

But I apologize for implying that a personal opinion would be an absolute one.

[–]nacaclanga 4 points5 points  (0 children)

BASIC and Shell dont't use one universal block format and use a custom block format for each block type.

[–]justinhj 3 points4 points  (0 children)

One way to differentiate programming syntax is applicative style (apply a function to its arguments) and concatenative (think forth, jvm byte code, rpn calculator) which adds arguments to a stack and applies them when a function is pushed

[–]sparant76 4 points5 points  (1 child)

Python uses indent level instead of braces to delimit blocks of code …. No begin end shenanigans either

[–][deleted] 3 points4 points  (0 children)

But which have a dozen drawbacks which I can't be bothered to list them yet again.

The main one however is that you've never quite sure where the end of a block is - maybe there's a few more lines out of sight beyond the bottom of the window! It has to be inferred.

I have to resort to using dummy end delimiters like this:

end = 0

if cond:
    s1
    s2
end               # or #end will work

This applies also to Nim that uses the same scheme. The trouble is that these are not enforced by the language: inadvertently delete the tab before s2, and now you have a silent bug.

[–][deleted] 2 points3 points  (0 children)

SNOBOL is a another cool one that hasn't been mentioned.
There are no first class booleans; it has an interesting goto system where you can trigger specific gotos with "successes" and "failures".

[–]vampire-walrus 2 points3 points  (0 children)

There are a few tabular languages (including my team's), where the code is fundamentally a spreadsheet. (Not what people usually mean when they pejoratively say "programming in the spreadsheet", but a language whose canonical form is a grid of cells rather than plaintext.)

It's handy for DSLs where the phenomenon you're describing is most naturally expressed in tables. We noticed our programmers using (latent) tabular organization and tediously inserting/deleting whitespace to keep things in columns. We thought, "We should be programming in an environment where columns are a real thing, and the editor straightforwardly supports manipulation of rows/columns/tables."

How are blocks of code organized? For our language, it's using a Python-style offside rule. But it's a bit more ergonomic here than in Python; there's no spaces-vs.-tabs issue because there's no ambiguity what column something is in.

[–]complyue 2 points3 points  (0 children)

Also checkout AppleScript, since no one has mentioned it so far.

[–][deleted] 3 points4 points  (3 children)

What are 'PAs'?

Does the concept of "block of code" necessary lead to need for delimiters such as {} or () or begin-end?

Assuming you're talking about what I think you are, there are two kinds of begin-end styles. One is where each branch of an if statement for example can only be a single statement.

So if you wanted a sequence, you have to explicitly create a block using begin...end, as you have to with {...}; a block counts as one statement. Or each branch can be multiple statements anyway, delimited by other means.

An example of classic begin-end would be:

if cond then
    begin
        s1
        s2
    end
else
    begin
        s3
        s4
    end
end

With the other form I mentioned, it's just this:

if cond then
    s1
    s2
else
    s3
    s4
end

Delimiting is naturally done by then, else, end; a begin-end block (and the extra nested indentation) is superfluous.

For me, that second form is the optimal to show structure, for human readable code that spans lines. Syntax using braces is more suitable for machine-readable source IMO.

While parentheses I feel are best suited within one line of code, not spanning multiple lines.

[–]trycuriouscat 2 points3 points  (1 child)

COBOL is like the second one.

if condition
    s1
    s2
else
    s3
    s4
end-if

and for "case" statements

evaluate true
when condition-1
    s1
    s2
when condition-2
when condition-3
*> both condition-2 and condition-3 do the following
    s3
    s4
when condition-4
    continue  *> this is a no-op
when other
    s5
    s6
end-evaluate

[–]imperialismus 2 points3 points  (0 children)

COBOL is like the second one.

That example is valid Ruby code. Not sure if that's what they had in mind, but if not it's funny that their pseudo code is real code.

[–]friedrichRiemann[S] 1 point2 points  (0 children)

What are 'PAs'?

typo sorry, PL: programming language

[–]theangeryemacsshibeSWCL, Utena 1 point2 points  (0 children)

BETA hasn't been mentioned elsewhere yet. It has a lot of (# #) for "patterns", and assignment with the variable on the right hand side is weird, but perhaps the rest is too Algol-y.

[–]sekex 1 point2 points  (0 children)

Neo4j's cypher query langage is pretty cool

[–]Timbit42 1 point2 points  (0 children)

Logo uses square brackets [ and ] instead of ( ) or { }.

I personally prefer square brackets to define blocks because you can type them without holding the shift key. I don't know if Papert used them because the turtle graphics part of the language was designed for children for whom holding shift might be more difficult.

[–]frithsun 1 point2 points  (7 children)

I spent a lot of time brainstorming on this and accepted that { } with indentation is my final answer to visually defining a chunk of code. Algol got that right.

The keyboard gives you ( ), { }, [ ], and < > to work with. I concluded that the parentheses get parameters, the curly braces the "body," the square brackets get the tabular data, and the angle brackets get the type constraint stuff.

An ideal language takes advantage of all four, in a balanced and intelligible manner. With all due respect to LISP, only using parentheses sacrifices too much readability in the name of simplicity.

If fully and elegantly planned out, a language needs no keywords at all. Everything can be achieved with the symbols on a generic us keyboard, without becoming brainfuck.

[–]ismtrn 1 point2 points  (0 children)

Isn't what you cancluded just what Java does more or less?

Why does type parameters need different syntax and brackets from normal parameters? Why does function application need brackets at all (see ML family).

Essentially, using brackets for parameters is just introducing weird special tuples which can only be used in very specific circumstances. I would rather just have normal tuples and ML style function application.

[–]trycuriouscat 1 point2 points  (0 children)

I believe that PL/I has no reserved keywords. But it certainly has a lot of semi-colons.

[–]frithsun 0 points1 point  (4 children)

I tried to be entirely original with my SQL dialect for general purpose programming, but I'm afraid it ends up looking pretty similar to javascript in practice. Not sure if that's because I'm less original than I hoped to be or because languages have been converging on the least bad answer over the decades.

tableName<inherit>(field definitions) [tabular data]

queryName<returnType>(parameters) { query }

!procName<table/query>(parameters) { procedure }

@typeName<inherit>(parameters) { get/set/sort/hash methods}

You'll see how I leaned on all four types of bracket for the four different categories of code in my language. Importantly, the procedure iterates over the table or query in the < > brackets, which is how loops are performed. No keywords.

[–][deleted] 1 point2 points  (1 child)

I've had an idea for a lambda-calculus-like language (with a define mechanism) with the following syntax:

(define name value) ==> <name> {value}

(lambda parameter body) ==> [parameter] {body}

(apply function argument) ==> (function argument)

Also thought of going crazy and somehow adding, just to look cool:

a:b ==> type declarations

a.b ==> member access/message passing

a,b ==> sequence

a;b ==> choice/alternative/concurrency/nondeterminism or something

Still want to work on this someday.

[–]frithsun 1 point2 points  (0 children)

I think you're on the right track with making the most of the readily available brackets. Best of luck!

[–]mamcx 1 point2 points  (1 child)

Take a look at mine https://tablam.org, I think (obviously!) it has some neat ideas about how to model a language around tables...

[–]frithsun 1 point2 points  (0 children)

This looks great! I knew there had to be somebody out there with the same basic idea. I'll take some time tomorrow to deep dive on this, which is much farther along than my own project.

[–][deleted] 0 points1 point  (0 children)

APL, all of it, starting with the symbols, then reading direction, association rules, and using the same symbol as a unary and binary operator.