{"id":40050286,"url":"https://github.com/akalenuk/the_namingless_programming_language","last_synced_at":"2026-01-19T06:05:02.483Z","repository":{"id":222367222,"uuid":"757077684","full_name":"akalenuk/the_namingless_programming_language","owner":"akalenuk","description":"Naming is hard. How far can we go without?","archived":false,"fork":false,"pushed_at":"2024-04-04T17:21:20.000Z","size":159,"stargazers_count":137,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-04T18:36:16.708Z","etag":null,"topics":["array-oriented-language","postfix-notation","programming-language","stack-oriented","tacit"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akalenuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-13T19:32:46.000Z","updated_at":"2024-04-03T13:48:13.000Z","dependencies_parsed_at":"2024-02-20T07:30:00.310Z","dependency_job_id":"4da37f87-62ca-4759-8f39-d7ae1adfb9eb","html_url":"https://github.com/akalenuk/the_namingless_programming_language","commit_stats":null,"previous_names":["akalenuk/the_namingless_programming_language"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/akalenuk/the_namingless_programming_language","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akalenuk%2Fthe_namingless_programming_language","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akalenuk%2Fthe_namingless_programming_language/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akalenuk%2Fthe_namingless_programming_language/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akalenuk%2Fthe_namingless_programming_language/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akalenuk","download_url":"https://codeload.github.com/akalenuk/the_namingless_programming_language/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akalenuk%2Fthe_namingless_programming_language/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28562254,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T03:31:16.861Z","status":"ssl_error","status_checked_at":"2026-01-19T03:31:15.069Z","response_time":67,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["array-oriented-language","postfix-notation","programming-language","stack-oriented","tacit"],"created_at":"2026-01-19T06:04:58.226Z","updated_at":"2026-01-19T06:05:02.475Z","avatar_url":"https://github.com/akalenuk.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The namingless programming language\r\n\r\nNaming is hard. Let's see how far can we go without.\r\n\r\n\r\n## What's this?\r\n\r\nThis is a programming language based on three paradigms:\r\n\r\n- [Tacit programming](https://en.wikipedia.org/wiki/Tacit_programming)\r\n- [Stack-oriented programming](https://en.wikipedia.org/wiki/Stack-oriented_programming)\r\n- [Array programming](https://en.wikipedia.org/wiki/Array_programming)\r\n\r\nThe main feature of the language is its avoidance of any naming of any sort. True to this maxim, the language itself doesn't have a name. \"The namingless programming language\" is a definition. \r\n\r\nSince there is only one such language in existence, *it doesn't need a name*.\r\n\r\n\r\n## What it's for?\r\n\r\nFun. Mostly fun. This is a language for recreational programming.\r\n\r\nWell, of course, you can also use it as a teaching tool to showcase tacit, stack-oriented, or array programming. Or use it for punishment in a BDSM play. I don't judge.\r\n\r\n\r\n## How does the code in this language look like?\r\n\r\nLike this:\r\n\r\n    i_^_b_H_i_cpp^_)_V_b_v_J_^_E_H_leafL_==^_)_V_H_Z_Z_^_)_V_H_I_^_E_1^_2^_#_G_Z_Z_^_E_1^_2^_#_H_$_L_-^_G_m_G_\u0026_\u0026_\r\n\r\n\r\n## Holy shit!\r\n\r\nYes.\r\n\r\nSorry.\r\n\r\n\r\n## What are the main concepts?\r\n\r\n### Data structures\r\n\r\nThere is one and only one data structure. Since there is only one, *it doesn't need a name*.\r\n\r\nSo the data structure is a tree of chars. Every node is either a leaf containing a char, or a branch containing a dynamic array of the data structures. The array may also be empty. An empty branch is still a branch.\r\n\r\nA string is a branch where every subbranch is a leaf.\r\n\r\nA number is a string. Yes. The language supports decimal arithmetics on strings. Go COBOL!\r\n\r\nAn array is a branch where every subbranch is a string.\r\n\r\nA matrix is a branch where every subbranch is an array.\r\n\r\nPlease note that none of these terms are names for anything language-specific. They are widely known data structures that are implementable in the language's data structure.\r\n\r\n### Operations\r\n\r\nThere is also the operation. Not \"an operation\" but \"the operation\" since there is only one operation in the language. Since there is only one, *it doesn't need a name* either.\r\n\r\nThe operation is spelled `_` and it takes the last element from the branch before it and acts accordingly. So essentially the semantics of the operation is set by the pair of a prefix - a symbol before the operation - and the operation itself.\r\n\r\nE. g. to add 2 and 2, you need to:\r\n\r\n1. put a char 2 as a string. The pair for that is `^` and `_`.\r\n\r\n    2^_\r\n\r\n2. then you need another 2 as a string. You can do the same `2^_` thing but you can also duplicate the last element in the current branch with a `H` and `_` pair.\r\n\r\n    H_\r\n\r\n3. finally, you need to perform the addition itself. That's easy, that's `+` and `_`.\r\n\r\n    +_\r\n\r\nSo the final program will look like this:\r\n\r\n    2^_H_+_\r\n\r\nAnd when run, it will result in:\r\n\r\n    4\r\n\r\n### Ok but the program you write in the namingless language should have a name right?\r\n\r\nTo avoid the naming problem for the programs you write, the language uses the name of the executable as the source code.\r\n\r\nLet that sink in.\r\n\r\nYou get the executable interpreter for the language and rename it with the valid code in the language. This way, the file you run doesn't have a name per se but the program itself is the name of the executable you run.\r\n\r\nSo to run the scary program from above you do this:\r\n\r\n\t./build.sh\r\n\tmv the_namingless_programming_language i_^_b_H_i_cpp^_)_V_b_v_J_^_E_H_leafL_==^_)_V_H_Z_Z_^_)_V_H_I_^_E_1^_2^_#_G_Z_Z_^_E_1^_2^_#_H_$_L_-^_G_m_G_\u0026_\u0026_\r\n\t./i_^_b_H_i_cpp^_)_V_b_v_J_^_E_H_leafL_==^_)_V_H_Z_Z_^_)_V_H_I_^_E_1^_2^_#_G_Z_Z_^_E_1^_2^_#_H_$_L_-^_G_m_G_\u0026_\u0026_\r\n\r\nOf course, you can just copy and tweak the program you already have. In fact, that's what we normally do with Python, shell, or Perl scripts anyway.\r\n\r\n### What operation pairs are available?\r\n\r\nHere is the full list of the operation pair prefixes.\r\n\r\n- . - exit\r\n- U - underscore\r\n- Z - slash\r\n- N - backslash\r\n- J - line break\r\n- i - dot\r\n- L - space\r\n- I - single quote\r\n- Y - double quote\r\n- ^ - elevate all the last elements of the same rank\r\n- | - put an element of the current branch on top by index\r\n- \\# - remove all but the targeted by index element for the selected depth\r\n- m - replicate an item multiple times\r\n- H - duplicate the last element\r\n- X - drop the last element\r\n- G - swap the last two elements\r\n- A - elevate an empty element\r\n- $ - count\r\n- v - deelevate last element\r\n- \\+ - addition\r\n- \\- - subtraction\r\n- x - multiplication\r\n- z - division\r\n- = - equal?\r\n- % - numerically equal?\r\n- \u003c - less?\r\n- \\\u003e - greater?\r\n- ( - substring?\r\n- ) - superstring?\r\n- \\[ - string starts with?\r\n- \\] - string ends with?\r\n- T - Boolean not\r\n- W - Boolean and\r\n- M - Boolean or\r\n- C - interpret as number if possible, 0 otherwise\r\n- \u0026 - concatenate strings\r\n- E - split a string\r\n- D - join strings\r\n- V - filter by a logical value\r\n- b - load from file\r\n- p - save to file\r\n- o - delete file\r\n- e - help\r\n\r\nBy the way, the list is automatically generated from the source code by the `i_^_b_H_i_cpp^_)_V_b_v_J_^_E_H_leafL_==^_)_V_H_Z_Z_^_)_V_H_I_^_E_1^_2^_#_G_Z_Z_^_E_1^_2^_#_H_$_L_-^_G_m_G_\u0026_\u0026_`.\r\n\r\n\r\n### The most important operation pair\r\n\r\n#### Exit\r\n\r\nSince the source code for the language comes from the name of the executable, and on Windows, a dot separates the file name from its extension, the dot was chosen as a prefix that stops the execution. You can also use it to separate code from comments like this:\r\n\r\n    i_^_b_H_i_cpp^_)_V_b_v_J_^_E_H_leafL_==^_)_V_H_Z_Z_^_)_V_H_I_^_E_1^_2^_#_G_Z_Z_^_E_1^_2^_#_H_$_L_-^_G_m_G_\u0026_\u0026_._list of operation prefixes\r\n\r\n\r\n### Escape sequences\r\n\r\n#### Underscore\r\n\r\nSince `_` is the command, you can't use it in arbitrary strings as it is. So the escape for the underscore is `U_`. \r\n\r\n\"U\" has been chosen since it kind of contains the underscore in its bottom part. This is the recurring pattern. A grapheme that substitutes a symbol is usually a symbol with something else.\r\n\r\n\r\n#### Slash\r\n\r\nYou can't usually use slashes in the file names. And even when you can it wouldn't be a good idea. Trust me. So there is an escape pair that puts `/` into the current data structure, and it is `Z_`.\r\n\r\nLike with \"U\", \"Z\" is a slash plus two extra lines.\r\n\r\n\r\n#### Backslash\r\n\r\nBy the same logic, the backslash is a `N_` pair. \"\\\\\" plus two extra lines.\r\n\r\n\r\n#### Line break\r\n\r\n\"J\" looks like a bit like a return sign \"⏎\". So the pair for the line break is `J_`.\r\n\r\n\r\n#### Dot\r\n\r\nSince a dot is used as a name-extension separator on Windows, we can use `i_` as a dot substitute just not to mess with the way file managers prefer to show stuff.\r\n\r\n\r\n#### Space\r\n\r\nAlthough there is nothing wrong with putting space in the file name, sometimes it makes routine UI operations like copying things harder so we can avoid spaces by `L_` substitution.\r\n\r\n\"L\" is a horizontal line representing the space itself, and a vertical line that serves no purpose.\r\n\r\n\r\n#### Single quote\r\n\r\n`I_` stands for the single quote. You probably wouldn't get it until you see the double-quote pair.\r\n\r\n\r\n#### Double quote\r\n\r\n`Y_` is the double quote. \"I\" and \"Y\", single and double. Does it make sense now?\r\n\r\n\r\n### Data handling\r\n\r\n#### Elevate all the last elements of the same rank\r\n\r\nI see your confusion. This prefix doesn't have a coherent name. Well, naming *is* hard, that's why I started the whole thing to begin with. \r\n\r\nWhat it does *usually* is it turns a piece of string into a subbranch containing the piece of string.\r\n\r\nE. g. you want to add 12 and 23 together. In a normal language, you have literals, syntaxis, and operators, so `12 + 23` is the common way to do that. In this language, you only have a string of chars as input, so to add two numbers together, you need to segregate one from another first.\r\n\r\nWhen you enter `12`, you only enter char `1` followed by char `2`. Your current branch contains two leaf elements.\r\n\r\n    leaf(1) leaf(2)\r\n\r\nNow you elevate all the elements of the same rank making these two into a subbranch with two leaves inside.\r\n\r\n    12^_\r\n\r\n...results in...\r\n\r\n    branch(leaf(1) leaf(2))\r\n\r\nNow you add two more chars:\r\n\r\n    12^_34\r\n\r\n    branch(leaf(1) leaf(2)) leaf(3) leaf(4)\r\n\r\nAnd then you elevate the last elements until they are of the same rank resulting in this:\r\n\r\n    12^_34^_\r\n\r\n    branch(leaf(1) leaf(2)) branch(leaf(3) leaf(4))\r\n\r\nAnd only now, when you have two branches with what are essentially strings inside, you can use another operation pair to add them up.\r\n\r\n    12^_34^_+_\r\n\r\nThis now results in a new branch containing the following:\r\n\r\n    branch(leaf(4) leaf(6))\r\n\r\nThis outputs to a tab and `46`. You can deelevate it back with the `v_` pair, and then you'll get `46` without any tabs, but that's a completely different story.\r\n\r\n\r\n#### Put an element of the current branch on top by index\r\n\r\nThis is something like `[]` in normal languages. A way to access an array.\r\n\r\nLet's say our branch is filled like this:\r\n\r\n    leaf(1) leaf(2) leaf(4) leaf(8)\r\n\r\nSince we might even know how many leaves there are, we start counting indices from the end. And for... reasons, we also start from 0.\r\n\r\nSo doing `2^_|_` to our subbranch picks the *third* element from the right, and copies it to the rightmost position in the branch.\r\n\r\n    leaf(1) leaf(2) leaf(4) leaf(8) leaf(2)\r\n\r\n\r\n#### Remove all but the targeted by index element for the selected depth\r\n\r\nThis is a way to access all the elements in a matrix, or a tensor, or a tree that lies on a certain depth, and in a certain position too.\r\n\r\nTake this program for example:\r\n\r\n    1^_2^_3^_^_4^_5^_6^_^_^_2^_2^_#_\r\n\r\nFirst, we elevate 3 chars so they become strings (or in terms of the language, branches that only contain leaves).\r\n\r\n    branch(leaf(1)) branch(leaf(2)) branch(leaf(3))\r\n\r\nThen we elevate the strings, yes, all three of them, so they now constitute an array of strings (or, in terms of the language again, a branch where all the branches are the branches that only contain leaves).\r\n\r\n    branch(branch(leaf(1)) branch(leaf(2)) branch(leaf(3)))\r\n\r\nThen we add three more strings and elevate them as well.\r\n\r\n    branch(branch(leaf(1)) branch(leaf(2)) branch(leaf(3))) branch(branch(leaf(4)) branch(leaf(5)) branch(leaf(6)))\r\n\r\nThen we evaluate the two branches making a matrix of strings (or in terms of the language, oh boy, a branch that contains several branches with an equal number of branches that only contain leaves each).\r\n\r\n    branch(branch(branch(leaf(1)) branch(leaf(2)) branch(leaf(3))) branch(branch(leaf(4)) branch(leaf(5)) branch(leaf(6))))\r\n\r\nOr in more conventional notation:\r\n\r\n    1 2 3\r\n    4 5 6\r\n\r\nNow we do this:\r\n\r\n2^_2^_#_\r\n\r\nThe first `2` is the index. And it also enumerates elements starting from 0, so `2` actually means \"the third\".\r\n\r\nThe second `2` is the depth. Also starting from 0. `2` and `2` means that we want the third element from the branch on the third level of embededness. That's `leaf(3)` and `leaf(6)` but also packed in a branch so it's more like `branch(leaf(3) leaf(6))`.\r\n\r\nThis operation prefix may also pick from the 0-th deepness level so, for instance, this program:\r\n\r\n    1^_2^_3^_2^_0^_#_\r\n\r\nResults in `3`.\r\n\r\n\r\n#### Replicate an item multiple times\r\n\r\nWell, that's easy. If there is an element in the current branch, it can be multiplicated. For example, `3` times by doing `3^_m_`:\r\n\r\n    test^_3^_m_\r\n\r\nresults in:\r\n\r\n    test\r\n    test\r\n    test\r\n\r\n\r\n#### Duplicate the last element\r\n\r\nThis is the abbreviated version of replication. It always adds exactly 1 copy of the last element.\r\n\r\n    test^_H_\r\n\r\nresults in:\r\n\r\n    test\r\n    test\r\n\r\n\r\n#### Drop the last element\r\n\r\nThe last element can also be easily removed.\r\n\r\n    1^_2^_3^_X_\r\n\r\nresults in:\r\n\r\n    1\r\n    2\r\n\r\n\r\n#### Swap the last two elements\r\n\r\nOr swapped with the previous element.\r\n\r\n    1^_2^_3^_G_\r\n\r\nresults in:\r\n\r\n    1\r\n    3\r\n    2\r\n\r\n\r\n#### Elevate an empty element\r\n\r\nSometimes you need an empty string, an empty array, or an empty matrix. You can't elevate an empty element with `^_` because it elevates all the consequent elements of the same rank starting from the last one. So there is a dedicated prefix that elevates an empty element out of the blue.\r\n\r\n    A_\r\n\r\nresults in\r\n\r\n    branch()\r\n\r\n\r\n#### Count\r\n\r\nThis simply returns the amount of subbranches in the last element of the current branch.\r\n\r\n    1^_2^_3^_^_$_\r\n\r\nresults in:\r\n\r\n    3\r\n\r\n\r\n#### Deelevate the last element\r\n\r\nJust like several subbranches can be elevated into one branch containing them all, the last element in the branch can be deelevated, putting all its contents in the current branch.\r\n\r\n    1^_2^_3^_^_v_\r\n\r\nresults, unsurprisingly, in:\r\n\r\n    1\r\n    2\r\n    3\r\n\r\nThe symbol pairs the grapheme for the \"elevate\" by the way. Isn't that sweet?\r\n\r\n\r\n### Arithmetics\r\n\r\nI love floating-point numbers. I wrote several tutorials on them:\r\n\r\n-[Yet another floating-point tutorial](https://wordsandbuttons.online/yet_another_floating_point_tutorial.html)\r\n\r\n-[Estimating floating-point error the easy way](https://wordsandbuttons.online/estimating_floating_point_error_th-e_easy_way.html)\r\n\r\n-[Why is it ok to divide by 0.0? ](https://wordsandbuttons.online/why_is_it_ok_to_divide_by_0_0.html)\r\n\r\nI even wrote a whole book on [Geometry for Programmers](https://www.amazon.com/Geometry-Programmers-Oleksandr-Kaleniuk/dp/1633439607) and it's half symbolic computations, half numeric so at least half of the book is concerned with floating-point numbers too.\r\n\r\nBut for this particular language, I wanted to avoid introducing another type so much, that I do all the arithmetics on decimal strings. Like in COBOL.\r\n\r\nThere is one unorthodox rule: the precision of the result is the maximum precision of the argument. The rule means that `1/3` and `1.00/3` result in different numbers. The former is `0`, and the latter - `0.33`. The rest is business as usual.\r\n\r\nExcept, of course, this time the expressions are in postfix notation, they propagate to tensors, and instead of operators we have prefix+operation pairs.\r\n\r\n\r\n#### Addition\r\n\r\nThe prefix for addition is `+`.\r\n\r\n    2^_2^_+_\r\n\r\n    4\r\n\r\nIn case you're wondering what the \"they propagate to tensors\" statement from above means, that means that you can add a number to an array:\r\n\r\n    1^_2^_^_3^_+_\r\n\r\n    4\r\n    5\r\n\r\nOr add elements in a pair of arrays together:\r\n\r\n    1^_2^_^_3^_4^_^_+_\r\n\r\n    4\r\n    6\r\n\r\nYou can also add matrices or even arbitrary trees as long as they are of equal rank, size, and configuration. All with a single operation. You don't need `for`s in this language.\r\n\r\n\r\n#### Subtraction\r\n\r\nThe prefix for subtraction is `-`.\r\n\r\n    4^_2^_-_\r\n\r\n    2\r\n\r\n\r\n#### Multiplication\r\n\r\nSince we wouldn't use `*` for multiplication, remember, that the source code comes from the file name, the prefix for the multiplication would be `x`.\r\n\r\n    2^_2^_x_\r\n\r\n    4\r\n\r\n\r\n#### Division\r\n\r\nJust like that, we wouldn't use `/` for division either. The prefix for the division is `z`.\r\n\r\n    4^_2^_z_\r\n\r\n    4\r\n\r\n\r\n### Logic\r\n\r\nLogical operations in this language work pretty much like arithmetics. They work on strings and propagate to tensors and trees. It's just the result of a comparison cast on a pair of trees is a tree of `0` and `1`s.\r\n\r\n\r\n#### Equal?\r\n\r\nThis compares two strings. Strings may or may not be numbers.\r\n\r\n    2^_2^_=_\r\n\r\n    1\r\n\r\n\r\n#### Numerically equal?\r\n\r\nThis compares two strings. Strings are expected to be numbers but they may have trailing zeroes.\r\n\r\n    2^_2.00^_=_\r\n\r\n    1\r\n\r\n\r\n#### Less?\r\n\r\nExpects numbers. Returns `1` if the former is less than the latter. `0` otherwise:\r\n\r\n    2^_3^_\u003c_\r\n\r\n    1\r\n\r\n\r\n#### Greater?\r\n\r\nAlso expects numbers. Returns `1` if the former is greater than the latter. `0` otherwise:\r\n\r\n    3^_2^_\u003e_\r\n\r\n    1\r\n\r\n\r\n#### Substring?\r\n\r\nExpects strings. Returns `1` if the former is a substring of the latter. `0` otherwise:\r\n\r\n    bob^_notabobbutcontainsone^_(_\r\n\r\n    1\r\n\r\n\r\n#### Superstring?\r\n\r\nSymmetrical to the \"substring?\" operation pair. Returns `1` if the former is a superstring of the latter. `0` otherwise:\r\n\r\n    notabobbutcontainsone^_bob^_)_\r\n\r\n    1\r\n\r\n\r\n#### String starts with?\r\n\r\nExpects strings. Returns `1` if the latter is what a former starts with. `0` otherwise:\r\n\r\n    bobbutcontainsone^_bob^_\\[_\r\n\r\n    1\r\n\r\n\r\n#### String ends with?\r\n\r\nExpects strings. Returns `1` if the latter is what a former finishes with. `0` otherwise:\r\n\r\n    notabob^_bob^_\\]_\r\n\r\n    1\r\n\r\n\r\n#### Boolean not\r\n\r\nExpects a string of `0` and `1` only. Inverts the values in a tree.\r\n\r\n    1^_T_\r\n\r\n    0\r\n\r\n\r\n#### Boolean and\r\n\r\nAlso expects strings of `0` and `1` only. Does the Boolean \"and\".\r\n\r\n    1^_1^_W_\r\n\r\n    1\r\n\r\n\r\n#### Boolean or\r\n\r\nYou guessed it, also expects strings of `0` and `1` only. Does the Boolean \"or\".\r\n\r\n    0^_1^_M_\r\n\r\n    1\r\n\r\n\r\n### Strings\r\n\r\n\r\n#### Interpret as a number if possible, 0 otherwise\r\n\r\nIn this language, numbers are strings that can be interpreted as numbers. So ten digits, one optional dot, and an optional minus sign. Some strings are obviously not numbers but we might wish they were. For this scenario, a special prefix exists and it's `C`. It turns all the non-numbers into `0`,\r\n\r\n    123^_not123^_^_C_\r\n\r\n    123\r\n    0\r\n\r\n\r\n#### Concatenate strings\r\n\r\nVery simple operation that glues two strings together.\r\n\r\n    2^_2^_\u0026_\r\n\r\n    22\r\n\r\n\r\n#### Split a string\r\n\r\nSplits a string by a delimiter (also a string).\r\n\r\n    pre,the,post^_,^_E_\r\n\r\n    pre\r\n    the\r\n    post\r\n\r\n\r\n#### Join strings\r\n\r\nJoins string back into a single string with a delimiter.\r\n\r\n    pre^_the^_post^_^_-^D_\r\n\r\n    pre-the-post\r\n\r\n\r\n#### Replace\r\n\r\nGot you! There is no \"replace a string with a string\" operation pair in the language. To do the replace, you do a split-then-join idiom.\r\n\r\n    pre,the,post^_,^_E_-^_D_\r\n\r\n    pre-the-post\r\n\r\nOne symbol spared for something else.\r\n\r\n\r\n### Filter\r\n\r\nThere is only one filter operation so far, and it is:\r\n\r\n\r\n#### Filter by a logical value\r\n\r\nIt expects two trees of the same configuration. One with strings the other with, well, also strings but only `1`s and `0`s. The filter goes through the first tree and removes every element that is not `1` in the corresponding tree.\r\n\r\n    pre,the,post^_,^_E_H_p^_)_V_\r\n\r\nSo this program\r\n\r\n1. elevates a string \"pre,the,post\",\r\n2. splits it by the `,` getting an array `pre the post`,\r\n3. duplicates the split string `pre the post`,\r\n4. applies the \"is a superstring of `p`\" for the last split tree resulting in array `1 0 1`.\r\n5. and, finally, applies the filter `1 0 1` to the `pre the post` array resulting in a smaller array with strings where the letter `p` occurs:\r\n\r\n    pre\r\n    post\r\n\r\n\r\n### Files\r\n\r\nIn this language, a grapheme for a file is a small circle `o`. There are exactly 3 operation prefixes that work with files, all of them have a small circle in them.\r\n\r\n\r\n#### Load from file\r\n\r\nThe grapheme is `b` so it's like a file goes up from slow persistent memory to the fast operational.\r\n\r\n    somefilei_txt^_b_\r\n\r\nresults in... whatever there is in the `somefile.txt`. The result will be delivered as a string - a branch where every subbranch is a leaf containing a character value.\r\n\r\nAlso, this operation pair doubles as a 'list directory' command. If the argument for the `b_` is a directory name, then the result will be not a string but a list of strings each containing a file or a directory name.\r\n\r\n\r\n#### Save to file\r\n\r\nThe grapheme is inverse to the one for the \"load from file\" it's `p`. So a file going down closer to earth.\r\n\r\n    somethingL_toL_putL_inL_aL_file^_somefilei_txt^_p_\r\n\r\nresults in a string \"something to put in a file\" being put in a file \"somefile.txt\"\r\n\r\n\r\n#### Delete a file\r\n\r\nThe grapheme now is just a circle `o`. Well, it might not make too much sense but it shows that the operation is a pure side effect with no effect on the current branch. Well, except for the file name being consumed.\r\n\r\n    somefilei_txt^_o_\r\n\r\ndeletes the \"somefile.txt\" file if there is one.\r\n\r\n\r\n### Help\r\n\r\nLast but not least, the grapheme for the help message explaining what the hell this thing does is `e`. The reasoning for this choice is simple. When you build the thing, the resulting file name is `the_namingless_programming_language`. So when you run it as it is, the first operation pair the interpreter meets is `e_` from `the_...`.\r\n\r\n\r\n### Ok, I get it now. I love it! But there is not much the interpreter can do at the moment. Can I contribute?\r\n\r\nSure! To add an operation pair to the language you might want to do three things.\r\n\r\n1. Invent a meaningful program that wouldn't run unless you add your thing. \r\n2. Add your thing so the program will run and be meaningful.\r\n3. Prepare the pull request with the changes in the code and your program added to the list of meaningful programs.\r\n\r\nI'll start.\r\n\r\n\r\n### The list of meaningful programs\r\n\r\n#### Parse the source code and list the operation pairs that are currently in the language\r\n\r\n    i_^_b_H_i_cpp^_)_V_b_v_J_^_E_H_leafL_==^_)_V_H_Z_Z_^_)_V_H_I_^_E_1^_2^_#_G_Z_Z_^_E_1^_2^_#_H_$_L_-^_G_m_G_\u0026_\u0026_\r\n\r\nThis program parses the `.cpp` files in the current directory looking for a string like this:\r\n\r\n    } else if(right.branches.back().leaf == 'e') { // help\r\n\r\nSuch strings are then processed to extract the operation prefix, `e` in the example, and the comment, ` help` in the example.\r\n\r\nThe prefixes and comments are then glued together with a dash ` -`.\r\n\r\nThe resulting array is the list of operation prefixes this language supports with brief explanations of them taken from the comments:\r\n\r\n                . - exit\r\n                U - underscore\r\n                Z - slash\r\n                N - backslash\r\n                J - line break\r\n                i - dot\r\n                L - space\r\n                I - single quote\r\n                Y - double quote\r\n                ^ - elevate all the last elements of the same rank\r\n                | - put an element of the current branch on top by index\r\n                \\# - remove all but the targeted by index element for the selected depth\r\n                m - replicate an item multiple times\r\n                H - duplicate the last element\r\n                X - drop the last element\r\n                G - swap the last two elements\r\n                A - elevate an empty element\r\n                $ - count\r\n                v - deelevate last element\r\n                \\+ - addition\r\n                \\- - subtraction\r\n                x - multiplication\r\n                z - division\r\n                = - equal?\r\n                % - numerically equal?\r\n                \u003c - less?\r\n                \\\u003e - greater?\r\n                ( - substring?\r\n                ) - superstring?\r\n                \\[ - string starts with?\r\n                \\] - string ends with?\r\n                T - Boolean not\r\n                W - Boolean and\r\n                M - Boolean or\r\n                C - interpret as number if possible, 0 otherwise\r\n                \u0026 - concatenate strings\r\n                E - split a string\r\n                D - join strings\r\n                V - filter by a logical value\r\n                b - load from file\r\n                p - save to file\r\n                o - delete file\r\n                e - help\r\n\r\n## P. S.\r\n\r\nNot so long ago I published this namingless programming language to get it out of my system and it was a great success. I mean, I did get it out of my system successfully, and I somehow don't feel like playing with it anymore. Which is a shame since it really deserves a couple of new features.\r\n\r\nFirst of all, the language lacks operators. In a mathematical sense, so functions that work on functions. It would be really simple to add one since the input for an interpreter is a string, and a branch with 1-char leaves is a string itself.\r\n\r\nSo the very first operator I would have added would have been the thing that does iterations. It takes a string as an argument, and evaluates the string continuously until the last argument in the subbranch is `1`. \r\n\r\nWe can normally avoid doing loops and ifs with filtering, but an iteration is something that implies side effects or a consequent state change, you can't run iterations in parallel, they should run consequently. Currently, the language has no facilities for that.\r\n\r\nDon't know what a fitting grapheme should be. I would have probably taken `G` from the element swap and gave that the `S` instead.\r\n\r\nAlso, I've heard that the language is not entirely namingless as prefixes work like names, so I want to challenge that a little too. A one-char prefix is just one possible way to guide the operation. There can just as well be multiple-char prefixes and, of course, one and only one no-char one.\r\n\r\nSo the other feature I would have added would be a prefixless rank operation. If the prefix of the operation is not a leaf with a single char, then the operation treats the prefix as a tensor and returns its rank.\r\n\r\nI wish I could add these two features myself, they would have improved the language quite a bit, but I don't want to. It was really fun working on an esoteric language for a while, but I think as for today, I burned out. However, if you feel like picking the baton, please do. \r\n\r\nI promise it will be fun. For a while.\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakalenuk%2Fthe_namingless_programming_language","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakalenuk%2Fthe_namingless_programming_language","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakalenuk%2Fthe_namingless_programming_language/lists"}