{"id":13546546,"url":"https://github.com/carlosdagos/bonlang","last_synced_at":"2025-04-09T18:52:47.962Z","repository":{"id":76103264,"uuid":"64082366","full_name":"carlosdagos/bonlang","owner":"carlosdagos","description":"Minimalist language created at ZuriHac 2016 in Zurich, CH","archived":false,"fork":false,"pushed_at":"2016-10-16T19:56:44.000Z","size":333,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-23T20:51:18.473Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carlosdagos.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}},"created_at":"2016-07-24T19:37:18.000Z","updated_at":"2023-07-31T07:32:55.000Z","dependencies_parsed_at":"2024-01-19T06:38:17.183Z","dependency_job_id":"be94f3e1-f00f-4ead-88d4-251c6b3c74fb","html_url":"https://github.com/carlosdagos/bonlang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosdagos%2Fbonlang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosdagos%2Fbonlang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosdagos%2Fbonlang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosdagos%2Fbonlang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carlosdagos","download_url":"https://codeload.github.com/carlosdagos/bonlang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248093178,"owners_count":21046635,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-08-01T12:00:39.945Z","updated_at":"2025-04-09T18:52:47.937Z","avatar_url":"https://github.com/carlosdagos.png","language":"Haskell","funding_links":[],"categories":["Haskell"],"sub_categories":[],"readme":"README\n======\n\n![doc/images/bonlang_logo.png](doc/images/bonlang_logo.png)\n\n## Introduction\n\nIt's a programming language! A minimalist (functional) programming language.\n\nI wrote about the whys and the whats [here](https://cdagostino.io/posts/2016-08-16-bonlang-experimenting-languages.html).\n\n## First steps\n\nHead over to the [examples](test/examples/) folder for some good stuff.\nBasically, your basic `hello-world` looks like this:\n\n```\n/*\n * file: main.bl\n *\n * This is where I tell you things\n */\n\nmodule Main where\n\ndef main [] = {\n    print $ \"Hello World!\";\n}\n```\n\nYou need to always have a `Main` module with a `main` method defined. This\nis what the runtime looks for in order to start the program.\n\n## Other examples\n\n### Lazy evaluation\n\nThe language is lazy, so this yields \"Lazy Hello\" but not \"Hello World\"\n\n```\nmodule Main where\n\ndef main [] = {\n    val sayHello = puts-ln $ \"Hello World!\";\n    puts-ln $ \"Lazy Hello!\";\n}\n```\n\nThose curly braces indicate \"Instruction blocks\". The runtime will try go\nthrough semicolon-separated expressions, reducing where necessary.\n\nSo this **will** produce output\n\n```\nmodule Main where\n\ndef main [] = {\n    val print' = print $ \"Hello World!\";\n    print'; // Needs evaluation to happen\n}\n```\n\n### Functional\n\nThe language is functional, so you can treat functions as\n[first class citizens](https://en.wikipedia.org/wiki/First-class_function).\n\n```\ndef flip [f, x, y] = f $ y x\n\n// Prints out 0.5\ndef main [] = {\n  val flipDiv = flip $ (/);  // flip the order of the division\n  puts-ln $ (flipDiv $ 8 4); // 4 / 8 = 0.5\n}\n```\n\nThis is the `flip` function\n[found in Haskell (for example)](http://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude.html#v:flip).\n\nYou can read more about `flip`\n[here](http://learnyouahaskell.com/higher-order-functions).\n\n### Automatic currying\n\nThe language supports automatic currying:\n\n```\nmodule Main where\n\n/**\n * Adds two values\n */\ndef addValues [x, y] = + $ x y\n\ndef main [] = {\n    val add2 = addValues $ 2;\n    val four = add2 $ 2;\n\n    // Will output '4'\n    puts-ln $ four;\n}\n```\n\nOr using higher order functions with curried functions\n\n```\nmodule Main where\n\n\ndef main [] = {\n    val addFive    = + $ 5;\n    val printArray = map $ puts-ln;\n\n    printArray $ (map $ addFive [0, 5, 10, 15]);\n}\n```\n\n### Function application\n\nFunction application is done with the `$` operator after an expression. If\nthe expression is a function, it will be applied. The runtime will throw an\nerror otherwise.\n\nYou should be familiar with Polish notation.\n\n### Lambda support\n\nThe language supports lambdas (closures)\n\n```\nmodule Main where\n\n/**\n * Will output '4' twice in new lines\n */\ndef main [] = {\n    val λ1 = lambda [x, y] =\u003e + $ x y;\n    val λ2 = lambda [y] =\u003e λ1 $ 2 y;\n\n    puts-ln $ (λ1 $ 2 2);\n    puts-ln $ (λ2 $ 2);\n}\n```\n\nIt also supports simple pattern matching on scalars and lists\n\n```\ndef is-zero [num] =\n  match num {\n    0 -\u003e true;\n    _ -\u003e false;\n  }\n```\n\nWill only return `true` for `is-zero $ 0`\n\n```\ndef is-single-element [list] =\n  match list {\n    [_] -\u003e true;\n    _   -\u003e false;\n  }\n```\n\nWill only return true for lists with one item, of whatever type and value.\n\nA more advanced usage example would be\n\nChecking a static prefix:\n```\ndef list-starts-with-one? [list] =\n  match list {\n    [ 1 | _ ] -\u003e true;\n    _         -\u003e false;\n  }\n```\n\nWill return true for lists like\n`[1], [1, 2], [1, 2, 3], [1, \"a\"], [1, 4], [1,-1]`, but never for lists that\ndon't start with a `1`.\n\n\nOr\n\n```\ndef list-has-one-a-wildcard-and-three? [list] =\n  match list {\n    [ 1, _, 3 | _ ] -\u003e true;\n    _               -\u003e false;\n  }\n```\n\nWill return true for a list like `[1, 3, 3]` or `[1, -1, 3, 4, 5]`.\n\nAnd of course some classic examples using pattern matching\n\n```\n// Gets first element of a given list\n// Example: (list-head $ [1, 2, 3]) =\u003e 1\ndef list-head [list] =\n  match list {\n    []        -\u003e error $ \"Empty list\";\n    [ x | _ ] -\u003e x;\n  }\n\n// Discards the first element of a list and returns the rest\n// Example: (list-tail $ [1, 2, 3]) =\u003e [2, 3]\ndef list-tail [list] =\n  match list {\n    []         -\u003e error $ \"Empty list\";\n    [ _ | xs ] -\u003e xs;\n  }\n\n// Reverses a list\n// Example: (list-reverse $ [1, 2, 3, 4]) =\u003e [4, 3, 2, 1]\ndef list-reverse [list] =\n  match list {\n    []         -\u003e [];\n    [ x | xs ] -\u003e concat-lists $ (list-reverse $ xs) [x];\n  }\n\n// Gets a list of successive pairs for a given list\n// Example: (list-to-pairs $ [1, 2, 3, 4]) =\u003e [[1, 2], [3, 4]]\ndef list-to-pairs [list] =\n  match list {\n    []            -\u003e [];\n    [_]           -\u003e error $ \"Uneven number of elements!\";\n    [ x, y | xs ] -\u003e concat-lists $ [[x, y]] (list-to-pairs $ xs);\n  }\n```\n\n## Motivations\n\nThis is developed in Haskell, I wanted to\ntest [`stack`](https://docs.haskellstack.org/en/stable/README/)\nand [`parsec`](https://hackage.haskell.org/package/parsec),\nand that eventually turned into this.\n\nI first read (and actually this contains code from)\n[Write Yourself a Scheme in 48 Hours](https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours).\nThat prompted me to design this. It has elements from Haskell, Scala, and Lisp.\n\nIt's fun.\n\n## Brought to you by\n\nCarlos D'Agostino.\n\nYou can visit my blog here https://cdagostino.io\n\n[Disclaimer](doc/images/noidea.png).\n\n[About my fixation with the number 4](https://xkcd.com/221/).\n\n## LICENSE\n\nSee [LICENSE](LICENSE) file in this repo.\n\n## TODOS\n\nSee [TODO](TODO.md) file in this repo.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlosdagos%2Fbonlang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarlosdagos%2Fbonlang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlosdagos%2Fbonlang/lists"}