Show HN: I created a language called AntiLang – breaking all the conventions
siruscodes.github.ioAntiLang is an interpreted programming language written in Go. The basic idea of this is to keep all the logical parts of a language same, but reverse the structure of it.
The idea for this project came when I was having a long midnight conversation with my friend and thought of writing such a weird language. The initial draft was far worse than the current implementation; we thought of reversing the brackets and the language would be read from bottom to top. I'm happy that I dropped that idea
Technical details: As the interpreter is written in Golang, I compiled it to WASM, and the whole interpreter is running in the browser. For the editor, I'm using Monaco, the same library that powers the text editor in VSCode. I learnt how to build it while reading "Write an Interpreter in Go" by Thorsten Ball.
The project is opensourced - https://github.com/SirusCodes/AntiLang - do give it a star if you like the project.
Maybe I've spent too much time with Forth, but the given example didn't look bad at all to me. Quite the contrary. The moment I reached line 2 (i.e., ",20 = count let"), I knew exactly what was happening. My mind immediately switched to postfix-mode. From there, everything made sense: logical, intuitive, even aesthetically pleasing!
A lot of people said this, why building this I had no idea of how these languages looked. Now that I know about them my project looks like a cheap imitation of them :(
Breaking conventions has been a thing for about as long as conventions themselves. No need to be hard on yourself. Next thing you should look at is Malbolge, very convention-breaking ;)
It looks like cat ran over the keyboard ( + _ + )
The solution is not to stick strictly to prefix, postifx, or infix notation. Instead, all three should be valid.
All these should be equivalent:
More insidiously, these should be equivalent:Don't be disappointed. That's cool! You've independently discovered something.
>>> Maybe I've spent too much time with Forth, but the given example didn't look bad at all to me. Quite the contrary. [...]
>> A lot of people said this, why building this I had no idea of how these languages looked. Now that I know about them my project looks like a cheap imitation of them :(
> Don't be disappointed. That's cool! You've independently discovered something.
I completely agree with mkingston's comment. Whether or not this project resembles other programming languages is beside the point. What truly matters is the joy you had building it. As Alan Perlis wisely said, "I think that it's extraordinarily important that we in computer science keep fun in computing."
This is a fascinating project, and in that same spirit of playful exploration, I'd like to share a minimalist, esoteric postfix language for drawing on a canvas that I built some time back: <https://susam.net/fxyt.html>.
you may want to browse https://codegolf.stackexchange.com for a while as well. There are all kinds of weird task-specific languages that can give you lots of ideas.
You can also look at this polyglot thread with 65 languages https://codegolf.stackexchange.com/questions/102370/add-a-la...
> Initially I thought to use , for float but ended use using . for floats.
Better - check the computer's region setting and use the local language convention, so decimal point is "." is English speaking regions, and "," is Euro regions, and who knows what else in other regions. That way code might work in one location but fail in another ;)
This is so evil it has already been implemented by Microsoft (Excel sheets...)
No surprise to see that coming from microsoft.
yeah, to keep it in spirit also add localization of function/operator names and make sure only the locale version works not all at the same time.
Good idea, but I suggest swapping . and , regions keeping with the spirit of the language.
This is on par with how Java WebStart locale reporting works between Windows and Linux.
AFAIR, Windows always reports US_EN for the locale, so you can write locale unaware code everywhere, but when running on Linux, you get the correct locale of the system (of course), and things break spectacularly.
I remember debugging an integer overflow, and I literally facepalmed following a "you didn't do THAT, did you!?".
The thing they did was parsing the date from the date string (formatted for system locale, without giving a specific locale) Java returned to them instead of fixing the locale and getting the date or getting the parts with relevant functions.
I have a relatively short fuse for people who doesn't read (or at least skim) the manual of the library they're using.
Is that true? I thought for all languages only "." is defacto decimal point in all languages. Never knew it changes with locale.
The hegemony of software only accepting . has de facto pushed the standard everywhere for computers, but here in France I still write with a comma, but type with a dot.
A few years ago Excel and some other softwares started to be locale dependent and I never wanted to burn my computer this much
French dev currently working for a French but global client, here. The UI of the timesheet app is in English but the fields only accept `,` as decimal point. It's so needlessly confusing.
That's one of the great boons of localization. The webapp knows you're in France, so it tries to do the right thing, while giving you a US English UI. I experience the same thing, but got used to it somehow.
Another good example is how "İ" is popping up everywhere, even in English, because of misconfigured locale settings and how changing case is affected by it. We (Turks) are responsible for that, sorry (We have ı,i,I,İ =D ).
Cyprus and Peru use , for decimal point for non-currency amounts and . for decimal point with currency amount. So it's not even consisent inside some languages.
See https://en.wikipedia.org/wiki/Decimal_separator#Hindu%E2%80%...
That's painful to think about
International standards say that either dot or comma is acceptable as decimal separator and thousand separators are optional spaces, typically a half space when properly typeset.
Very much so.
Dot is often used as thousands separator too.
I remember the first time I saw 10,000 as a price and thought: 10 bucks? So cheap. But also: who needs 3 decimal points for a price?
Looks like its more or less 50% of the world [0].
[0]: https://en.wikipedia.org/wiki/Decimal_separator#Conventions_...
To add to the complexity of the whole situation, some countries don't separate by thousands (every three zeroes). India uses a 2,2,3 system (crore, lakh, thousand).
10 million = 1,00,00,000
https://en.wikipedia.org/wiki/Lakh
> who needs 3 decimal points for a price?
Petrol stations... I have no idea how widespread this practice is, but at least in Germany fuel prices have 3 decimal points to better confuse motorists. The third number is usually displayed smaller and is of course always a nine. So, if you see the price for a litre of diesel at e.g. 1.62⁹ €, you might forget to round it up mentally.
For example, German speaking countries use a comma instead of a decimal point, whereas the latter is used as a group separator. The German word for decimal place is "Kommastelle" (= "comma place").
It’s “,” in Poland, and a dot(or apostrophe) as thousands separator.
That’s why in region settings on your computer you will find not only date/tome formatting, but also the number format.
No. Some languages use . for thousand (or even hundred) separators.
This is pure evil idea :)
I will implement this thing.
Raised issue - https://github.com/SirusCodes/AntiLang/issues/6
I love it. I want a python-esque version that's whitespace sensitive. But only for trailing whitespace.
If you used leading whitespace you could wind up with something like old basics where you had to number your lines. It was great, you'd always skip 10 between lines so if you had a bug you could stuff a patch in between existing lines at *5.
For the whitespace, you'd have to know how deeply to indent the outermost part of your code.
So if you add an if block to a for loop, every line of the code has to be indented and only the contents of the new if would be at indent of 0.
I am not going to write this pseudocode in AntiLang because I am not that much of a masochist.
becomes If you antilanged this the rest of the way, you could have a common `start` to indicate the start of a block and then replace the `end with the actual conditional. This gets horrible pretty quick. So as terrible as trailing line space is, leading line space is quite possibly worse.Which leads me to the ultimate conlusion -
This is some of the evilest idea I got on the post...
Raised issue for it - https://github.com/SirusCodes/AntiLang/issues/9
You're a demon living in hell, aren't you? No one on Earth could be this evil.
The idea of a trailing whitespace sensitive language is... amazing.
Get real torturous with it and make the amount of whitespace the line number, ala BASIC. 3 trailing spaces is line 3 for instance. Tab character counts as powers of ten separator? Space space space tab space space is line 32?
Why need it be trailing at all? Just use Whitespace (esolang)
Polyglottism
That is something I might do... Seems pretty horrible
Everyone knows 'goto' is bad, so a language like this needs 'comefrom'
INTERCAL already has this in its language
Interesting thought... But how will that work? The statement would be executed only it comes from that line?
The compiler inserts a goto to the statement following the comefrom statement into the line specified. :^)
If multiple comefroms to the same line are specified, the comefrom to jump to is selected randomly.
It is like a regular goto, but with the label and statement reversed.
So instead of
You have Really, that's just syntax. Declare your labels with "comefrom", and ":" means "jump". But it looks a lot more confusing this way.It's just syntax until you decide to support both.
Ok, so:
A brand new way to lock up your machine.It is reverse GOTO. After (or before - your choice) that line is executed, execution jumps to the comefrom.
I don't know how I'm going to implement it but seems pretty interesting flow.
Raised issue - https://github.com/SirusCodes/AntiLang/issues/7
I see no mention of INTERCAL in this thread, which implements COME FROM
If you don't know about it, you're in for a treat.
https://en.wikipedia.org/wiki/INTERCAL
The joke runs longer: https://en.wikipedia.org/wiki/COMEFROM
that's absolutely evil
This makes me wonder whether the usual order for function application is an artifact of the S-V-O sentence structure in western European languages. Maybe if Euler had been raised in a language with a S-O-V sentence structure, we would write (x)f instead.
Plus, reverse function application/composition works better with our tendency to write the domain of the function before its range. Given f : A -> B and g : B -> C, the composite function is written as g o f which is mildly annoying.
> Maybe if Euler had been raised in a language with a S-O-V sentence structure, we would write (x)f instead.
This is an interesting question but it's further complicated by how frequently Euler was writing in Latin, which usually prefers (but doesn't require) SOV order.
I just looked up a random text by Euler (https://scholarlycommons.pacific.edu/euler-works/298/) and I see
> Genus autem secundum eiusmodi problemata complectetur, ad quae soluenda coordinatae ad duo curuae puncta pertinentes simul considerari debent; cuiusmodi erat problema de traiectoriis reciprocis, illudque problema catoptricum, quod ante aliquot annos tractavi. Cum enim in his continuo bina curuae puncta inter se conferantur, et coordinatae ad ea pertinentes in computum ingrediantur; per principium continuitatis effici debet, ut bina haec puncta ad eandem lineam curuam referantur, sicque aequatio inter coordinatas unicum punctum spectantes eliciatur.
I put all of the clauses' main verbs in italics. All of them except for "erat" ('was') are at the ends of their respective clauses! So, Euler had quite a lot of experience writing SOV sentences in technical contexts.
I just had another thought about this.
Programmers are pretty accustomed to thinking of functions as verbs. In some programming styles, we're even explicitly encouraged to name our functions after verbs describing what they do.
Sometimes mathematicians think of functions more as expressing a complete (and sort of timeless) relationship between a domain and a range. That relationship, considered in its totality, can be thought of as a noun rather than a verb.
Earlier mathematicians might also have tended to think of functional notation as referring to individual specific instances of the result of the calculation that the function refers to, like "the sine of 1/2" being a specific number (the result of computing the sine of one half, or, alternatively, the output of the function given a specific input). So when writing something like sin(1/2) they might not be thinking "please [person or machine] perform this computation on the number 1/2 right now" so much as "[I am here indicating] the specific [timeless and inherent] number that is the sine of 1/2". That's a different way that a function could be seen as a noun, essentially seeing the function as merely a way of referring to its output.
Calculus and real analysis start to give stronger reasons for thinking of functions as abstract objects in their own right (e.g. because we can say something like "d/dx sin(x) = cos(x)" or even "the derivative of sin is cos" without thinking about specific values. Or questions like "can a function exist that is continuous but not differentiable?". Maybe computer science then starts to give reasons for thinking of functions as descriptions of how to perform them (like source code or even machine code punched on punch cards) as opposed to references to their specific results (like a printed book of function tables, which someone else calculated ahead of time so you wouldn't have to).
This is all to say basically that maybe it's more natural for us as programmers to think of functions as verbs, but maybe Euler didn't conceive of them that way at all!
Even in modern mathematics, the postfix notation is used in some places. One example I can recall is permutations.
Consider the following permutation:
This is typically written in cycle-notation like this: If we look at the cycle notation, f maps each symbol to the one on the right. For example, it maps 1 to 1, 2 to 4, 4 to 3, and 3 to 2.Now if we want to find out what happens to the sequence (4 3 2 1) when we apply f to it, we normally write it as
The argument comes first. The function name comes next. It makes it quite convenient to work with permutations, composition of permutations, etc. For example, the result for the above application is:You see it in some treatments of abstract algebra too. (Which are not unrelated to permutations in any case.) I think at least one book used in my undergrad used postfixes for function application, but I can't remember which.
Was it perhaps 'A course on Group Theory' by John S. Rose?
Definitely not. (He may do that, I just hadn't ever heard of that book before today.) I think it was one of Isaacs, Herstein, or Artin, but I'm a bit too lazy to dig through my old books at the moment.
Why limit your changes to syntax? Intercal's COME FROM would be a good addition, but you definitely also need SOLVE and PROVE statements to increase the power of the language.
Having IF TERMINATES and IF NOT TERMINATES predicates would be useful, too. Why limit yourself to everyday computable functions? And if you really wanted to, you could implement both SOLVE and PROVE in terms of them...
Yep, someone suggested it; I might add it.
ref: https://news.ycombinator.com/item?id=43192484
you may want to take a peek at INTERCAL. you think GOTO is bad? wait until you have to deal with COME FROM, especially in "Threaded INTERCAL" where arriving at the location that multiple active COME FROM statements are pointing to simply jumps to all of them simultaneously.
Is COME FROM significantly different from an event-driven architecture?
Not in the sense of flow of execution. But you'd explicitly fire off an event, no? COME FROM is registering invisible triggers at arbitrary locations.
C# has a new feature, interceptors, that is very COME FROM like.
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
Might implement this feature.
Raised an issue on GitHub - https://github.com/SirusCodes/AntiLang/issues/7
Does the language have continuations? If you're going for fun control flow features those are both much more useful and mind bending. They also fit the theme you have going since most languages don't have them and they're effectively the reverse of a function call.
also you can set the probability of a command to be executed at all!
Sure I will take a look at it
Nice! Feature request : conditional expressions should start with the "else" branch.
That's a good idea but the current flow is from top to bottom but this would change that, someone would be reading it from top to bottom then at the end read if case then go back to top to read else case. I don't want to do that.
The control flow is basically smalltalk funnily enough, since it has effectively no language level control flow, if/while etc are all just messages in the form of
```
[condition] whileTrue: [code]
(condition) ifTrue: [code] ifFalse: [code]
```
A lot of people at Reddit told me that it resembles SmallTalk, Factor, and Forth. Being someone who started coding in last decade I have only heard the names but never saw the syntax, but true it looks surprisingly similar. I can't really fathom that people actually built stuff in those language (probably better things that we build today)
Postfixes are easier to use, if you know how to use them. They're not only used in programming but also in spoken language:
Sentences that simple are equally understandable using the verb as a postfix or infix. When sentences get longer that changes, though: In the first sentence, it's clear that the extra clause is something the sentence has, not the verb. The second example has what is called a dangling modifier, which is a clause at the end of the sentence that ambiguously could be describing more than one thing, in this case it could mean that either the sentence has an extra clause or the verb has an extra clause.The lack of ambiguity also means it takes fewer commands to describe a single operation. For example, in an calculator with infix notation, which is what most people learn, calculating the multiple of four pairs of sums would require the following keypresses:
With an RPN calculator, which has a postfix notation, it would only require these keypresses: That's 24 in the first example and 19 in the latter, a reduction of over 20%.My grandma never really learned how to use a computer and was generally not very good at complex instructions. When she learned to use a calculator, RPN was just as common as postfix notation, and she was able to figure out how to use RPN, but had trouble figuring out postfix notation. Nowadays, schools usually only teach postfix notation, so most students aren't exposed to the easier method, and will have to do extra work, in the short term, to lean it, but it means calculations will require less work, once learned.
tl;dr: Postfix notation is the Dvorak keyboard to infix notation's Qwerty keyboard. The former is easier and faster, but everyone learns the latter. Putting in the extra work to learn the former will save you more time in the long run.
Thanks for the explanation. I don't agree with your point that postfix is easier; maybe it's because most people are not used to thinking in postfix. It can be faster and easier for computers, but we build software for people, and it increases cognitive load on the users.
It might be fewer keystrokes, but I feel for most people, the difference in keystrokes doesn't justify the cognitive load it adds.
I grew up using HP RPN calculators and it was actually easier in the long run. It isn't in the keystrokes either, but because when I was calculating an algebraic expression, I would have to setup a "query plan" in my head on how I would input all the values and then often I could simplify things as I entered them. I got rather good at manipulating algebraic expressions as a result, and it served me well in college.
Yes!! postfix gang
apl-family languages also often read easier right to left
Off topic, tongue in cheek - I thought we agreed that it's just PHP? There was an old meme about it:
- "PHP: a fractal of bad design": https://news.ycombinator.com/item?id=3820431
- An image of a double clawed hammer that someone actually made: https://c2.staticflickr.com/8/7226/7095238893_5000f6e57d.jpg
- And of course there were follow up images: https://imgur.com/CO1tv
A good effort and took me a minute to adjust to not knowing what's going on. Title made me hope for something more esotheric than just backwards code, though.
I'm sorry to disappoint you, maybe next time I will have something more esoteric
Think you should rename some of the keywords to more naturally suit their positioning.
Like, rather than
if you have (Though 'otherwise [condition] then' breaks your pure postfix style).Similarly "while" could be "yields".
And "let" could be "over" (CB radio-style):
Someone on X suggested to make it logically reverse, so true would be false and visa versa.
We can go ahead and make + behave as - and similarly for other operators.
Do you want to lie to your users, or do you just want to use unconventional operators? If the latter, you could consider using something like ruby's `unless`.
(the number of times I've noticed code that does `unless !some_condition`... which is of course just the same thing as `if some_condition`)
Makes sense; I need to think about which would be better.
More or less just writing each line backward (token by token).
Q1: How close could one get to a grammar that would basically recognize C with each line reversed character-by-character?
Q2: What would a language look like where instead of being oriented into right- or leftward-marching lines, it was oriented into downward-marching columns?
Thanks for reminding me how reading code feels when I just got started.
We all have been there
Reminds me of RPL
https://en.wikipedia.org/wiki/RPL_(programming_language)
I wouldnt discount your work. Someone who thinks a bit different might find it a workable onramp into coding where others have failed.
The best terrible (or worst, I guess!) idea I've ever had for a language is using fuzzy matching for variable names. No need to worry about typos, since something close enough will work, and as long as you've defined at least one variable, you'll never have an undefined error!
I wonder if this can be considered an info hazard. Nice job, but don't do it again.
I will try my best to resist the temptation ;)
C-like equality (==), inequality (!=) and assignment (=) is such a missed opportunity here. One could go with "=", "=/=" and "<-" here while both preserving some sanity and shock factor.
That's Algol/Pascal's equality operator, Erlang's inequality operator (Pascal used "<>") and Haskell's binding operator (or whatever it's actually named inside the do-notation). In fact, Algol designer's considered using "<-" for assignment.
That's a pretty good idea, I can do this.
Raised an issue for this - https://github.com/SirusCodes/AntiLang/issues/5
Funny, some of the "reverseness" looks a bit like PostScript, which is a stack-based language, where you write code like:
Good old Reverse Polish notation, reminds me of Robowar.
https://robowar.fandom.com/wiki/Introduction_to_RoboWar
Pretty interesting game, never heard about it. Thanks for sharing.
Honestly, it doesn't look that bad, I could get used to that syntax. It's not really objectively worse nor better than the normal syntax we have in programming languages now.
I think a true AntiLang would also break conventions of how programming itself works too. This just seems like a normal language with weird syntax.
You need to right-align this.
You should start an If/else from the else case and use unless keyword. { return 1; } unless 8 == 3 { return 2 }
I knew this, before posting here I thought all programming languages are ltr.
But now I know a lot of programming languages did rtl like forth, factor, postlang, etc
It doesn't break conventions, it just uses them backwards. Is it even a true postfix language?
Some more suggestions:
1. replace "while" with "go on" (yes, with space, because why not)
2. add break statement in the form of "oh, come on!" 3. replace "if" with "considered" and "if else" chain with "on <number> thought". Final "else" must be "eigentlich", because who said all keywords should be in English? 4. add reverse array function with special syntax, because it is special: 5. add constants: 6. Add System.exit(<number>): 7. Add exceptions: 8. Do not support catching exceptions in try blocks. They are exceptions. Every function must implicitly return an union type <ReturnValue|Exception>. If exception value is not handled, it pops up.Thanks, those are some pretty nice suggestions!
Make it like urdu language which is written in reverse
You should have called it "Tenet"
Reads nicely from right to left.
This is what perl looks like to people who don't know it.
I had fun, lost my mind, and a few friends.. probably. thanks!
Shouldn’t the interactive mode be called `antilang lper`?
Good point, but repl is just fine in my opinion
a very good language this seems to me like
This looks very readable compared to APL
Honestly, you have done the most superficial thing here. It’s fine, but K is much more interesting in terms of encoding ideas differently than ALGOL style languages, just as one easy example.
Didn't knew that it existed, I will take a look at it!
Missed gold. You should have had a new assignment operator and you could have used single equals sign for checking equality.
We can introduce a breaking change...
I have raised an issue for this - https://github.com/SirusCodes/AntiLang/issues/5
jumbled seems like a better name
Someone suggested MirrorLang, that's fitting as well.
ugh I like it but I had to close the tab right away
[dead]
[flagged]
Why so much hate for rust?
[flagged]