Show HN: I created a language called AntiLang – breaking all the conventions

siruscodes.github.io

135 points by SirusCodes 5 days ago

AntiLang 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.

susam 2 days ago

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!

  • SirusCodes 2 days ago

    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 :(

    • baq 2 days ago

      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 ;)

      • SirusCodes 2 days ago

        It looks like cat ran over the keyboard ( + _ + )

    • albrewer a day ago

      The solution is not to stick strictly to prefix, postifx, or infix notation. Instead, all three should be valid.

      All these should be equivalent:

        + a b + c d + 
        + + + a b c d
        a + b + c + d
        a b c d + + +
      
      More insidiously, these should be equivalent:

        x = a + b
        = + x a b
        x a b = +
        + x = a b
        x = a b +
        x a + b =
    • mkingston 2 days ago

      Don't be disappointed. That's cool! You've independently discovered something.

      • susam a day ago

        >>> 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>.

drpixie 2 days ago

> 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 ;)

  • andrelaszlo a day ago

    This is so evil it has already been implemented by Microsoft (Excel sheets...)

    • Jotalea a day ago

      No surprise to see that coming from microsoft.

    • gryn a day ago

      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.

  • seafoamteal 2 days ago

    Good idea, but I suggest swapping . and , regions keeping with the spirit of the language.

  • bayindirh a day ago

    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.

  • SirusCodes 2 days ago

    Is that true? I thought for all languages only "." is defacto decimal point in all languages. Never knew it changes with locale.

    • plopilop 2 days ago

      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

      • johncoltrane a day ago

        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.

        • bayindirh a day ago

          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 ).

    • ninalanyon a day ago

      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.

          ISO 31-0 (after Amendment 2) specifies that "the decimal sign is either the comma on the line or the point on the line". This follows resolution 10[1] of the 22nd CGPM, 2003.[2]
      
          For example, one divided by two (one half) may be written as 0.5 or 0,5.
    • jiehong 2 days ago

      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_...

      • koliber 2 days ago

        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

      • rob74 a day ago

        > 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.

    • spacechild1 2 days ago

      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").

    • kolinko 2 days ago

      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.

    • yxhuvud 2 days ago

      No. Some languages use . for thousand (or even hundred) separators.

rjmill 2 days ago

I love it. I want a python-esque version that's whitespace sensitive. But only for trailing whitespace.

  • daotoad a day ago

    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.

        for ( foo in somearray )
      doStuff(foo)
        end
    
    becomes

          for ( foo in somearray )
        if ( condition )
      doStuff(foo)
        end
          end
    
    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.

        start
      doStuff(foo)
        for( foo in somearray )
    
    
    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 -

      White space should be balanced.  If you need 4 spaces indent, you also need 4 spaces on the end of the string.
  • jedberg 2 days ago

    You're a demon living in hell, aren't you? No one on Earth could be this evil.

  • donatj a day ago

    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?

  • LoganDark 2 days ago

    Why need it be trailing at all? Just use Whitespace (esolang)

  • SirusCodes 2 days ago

    That is something I might do... Seems pretty horrible

gaff33 2 days ago

Everyone knows 'goto' is bad, so a language like this needs 'comefrom'

  • jezzamon a day ago

    INTERCAL already has this in its language

  • SirusCodes a day ago

    Interesting thought... But how will that work? The statement would be executed only it comes from that line?

    • movpasd a day ago

      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.

    • GuB-42 a day ago

      It is like a regular goto, but with the label and statement reversed.

      So instead of

        label: 
        do_something
        goto label
      
      You have

        comefrom label
        do_something
        label:
      
      Really, that's just syntax. Declare your labels with "comefrom", and ":" means "jump". But it looks a lot more confusing this way.
      • TeMPOraL a day ago

        It's just syntax until you decide to support both.

        • kbelder a day ago

          Ok, so:

            comefrom label
            goto label
            label:
          
          A brand new way to lock up your machine.
    • immibis a day ago

      It is reverse GOTO. After (or before - your choice) that line is executed, execution jumps to the comefrom.

semolinapudding 2 days ago

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.

  • schoen 2 days ago

    > 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.

    • schoen 2 days ago

      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!

  • susam 2 days ago

    Even in modern mathematics, the postfix notation is used in some places. One example I can recall is permutations.

    Consider the following permutation:

      f = (1 2 3 4)
          (1 4 2 3)
    
    This is typically written in cycle-notation like this:

      f = (1)(243)
    
    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

      (3 4 2 1)f
    
    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:

      (3 4 2 1)f = (3 4 2 1)(1)(243) = (2 3 4 1)
    • wging 2 days ago

      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.

      • twnettytwo 2 days ago

        Was it perhaps 'A course on Group Theory' by John S. Rose?

        • wging a day ago

          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.

          • JadeNB an hour ago

            > 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.

            Herstein does it.

  • JadeNB an hour ago

    > 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.

    Herstein's Topics in algebra uses that notation for function application. It's surely not a coincidence that he was Polish, and that that reminds one of RPN.

knome 2 days ago

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.

  • drdec 2 days ago

    Is COME FROM significantly different from an event-driven architecture?

  • meta-level 2 days ago

    also you can set the probability of a command to be executed at all!

  • SirusCodes 2 days ago

    Sure I will take a look at it

croo 2 days ago

Nice! Feature request : conditional expressions should start with the "else" branch.

  • SirusCodes a day ago

    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.

Bolwin 3 days ago

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]

```

  • SirusCodes 3 days ago

    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)

    • dlcarrier 3 days ago

      Postfixes are easier to use, if you know how to use them. They're not only used in programming but also in spoken language:

          It is how, in this sentence, the verb works.
          
          It isn't how the verb works, in this sentence.
      
      Sentences that simple are equally understandable using the verb as a postfix or infix. When sentences get longer that changes, though:

          It is how, in this sentence, which now has an extra clause, the verb works.
          
          It isn't how the verb works, in this sentence, which now has an extra clause.
      
      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:

          ( 5 + 6 ) x ( 2 + 7 ) x ( 3 + 8 ) x ( 7 + 9 ) =
      
      With an RPN calculator, which has a postfix notation, it would only require these keypresses:

          5 Enter 6 + 2 Enter 7 + 3 Enter 8 + 7 Enter 9 + x x x
      
      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.

      • SirusCodes 2 days ago

        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.

        • youainti 2 days ago

          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.

    • nagaiaida 3 days ago

      apl-family languages also often read easier right to left

lambdaone 11 hours ago

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...

rf15 3 days ago

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.

  • SirusCodes 3 days ago

    I'm sorry to disappoint you, maybe next time I will have something more esoteric

another-dave 2 days ago

Think you should rename some of the keywords to more naturally suit their positioning.

Like, rather than

    [condition] if 
        <code> 
    [condition] else if 
        <code> 
    else 
        <code>
if you have

    [condition] then
        <code> 
    otherwise [condition] then
        <code> 
    otherwise 
(Though 'otherwise [condition] then' breaks your pure postfix style).

Similarly "while" could be "yields".

And "let" could be "over" (CB radio-style):

    10 = age over;
  • SirusCodes 2 days ago

    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.

    • wging 2 days ago

      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`)

      • SirusCodes 8 hours ago

        Makes sense; I need to think about which would be better.

quuxplusone 2 days ago

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?

dev-jayson 3 days ago

Thanks for reminding me how reading code feels when I just got started.

x3n0ph3n3 3 days ago

I wonder if this can be considered an info hazard. Nice job, but don't do it again.

  • SirusCodes 2 days ago

    I will try my best to resist the temptation ;)

saghm a day ago

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!

magnat a day ago

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.

  • Joker_vD a day ago

    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.

ale42 a day ago

Funny, some of the "reverseness" looks a bit like PostScript, which is a stack-based language, where you write code like:

  /Times-Roman findfont 12 scalefont setfont
  42 84 moveto (Hello world) show showpage
thezipcreator 2 days ago

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.

ufko_org a day ago

  )) 1 x (define (  
  )) "مرحبا، هذا ليسب!" (print (  
  )) x 2 + (print (
  • cluckindan a day ago

    You need to right-align this.

keyle a day ago

   ,fantastic pretty that's
   ,this about joke we
but 10-15% of the world reads rtl...
  • SirusCodes a day ago

    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

zombot a day ago

It doesn't break conventions, it just uses them backwards. Is it even a true postfix language?

ivan_gammel a day ago

Some more suggestions:

1. replace "while" with "go on" (yes, with space, because why not)

   { i < 10 } go on [ ... ]
2. add break statement in the form of "oh, come on!"

   { i < 10 } go on [ 
      ,1 += i
      { i > 5 } considered [ 
         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?

   {a < b } considered [ ... ], {a > b} on 2nd thought [ ... ], eigentlich [ ...]
4. add reverse array function with special syntax, because it is special:

   reverse{array}
5. add constants:

   ,$SCREAM!$ = SCREAM let it be
6. Add System.exit(<number>):

   ,{1}oh, no!
7. Add exceptions:

   {$Invalid user$}oh, my god!
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.

   ,{1; 0}divide = value let
   {exception is value} considered [ ,value print ] on 2nd thought [ ,1+= value ]
  • SirusCodes a day ago

    Thanks, those are some pretty nice suggestions!

Simon-curtis a day ago

You should start an If/else from the else case and use unless keyword. { return 1; } unless 8 == 3 { return 2 }

G_o_D a day ago

Make it like urdu language which is written in reverse

earth2mars a day ago

You should have called it "Tenet"

snovymgodym 2 days ago

This is what perl looks like to people who don't know it.

acosmism 3 days ago

I had fun, lost my mind, and a few friends.. probably. thanks!

betimsl a day ago

Reads nicely from right to left.

chuckadams 2 days ago

Shouldn’t the interactive mode be called `antilang lper`?

  • SirusCodes 2 days ago

    Good point, but repl is just fine in my opinion

changexd 3 days ago

a very good language this seems to me like

29athrowaway 2 days ago

This looks very readable compared to APL

sulam 2 days ago

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.

  • SirusCodes 2 days ago

    Didn't knew that it existed, I will take a look at it!

someothherguyy 2 days ago

jumbled seems like a better name

  • SirusCodes 2 days ago

    Someone suggested MirrorLang, that's fitting as well.

jwpapi 3 days ago

ugh I like it but I had to close the tab right away