{"id":20177381,"url":"https://github.com/airsequel/airscript","last_synced_at":"2026-03-19T14:22:42.119Z","repository":{"id":228205739,"uuid":"773344071","full_name":"Airsequel/AirScript","owner":"Airsequel","description":"[WIP] A scripting language for spreadsheet formulas, CLI tools, ETL pipelines","archived":false,"fork":false,"pushed_at":"2024-03-17T15:11:46.000Z","size":13,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-03T19:54:07.668Z","etag":null,"topics":["formula","fp","functional","functional-programming","language","programming-language","scripting","scripting-language"],"latest_commit_sha":null,"homepage":"https://www.airsequel.com","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Airsequel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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},"funding":{"github":["Airsequel"]}},"created_at":"2024-03-17T12:17:18.000Z","updated_at":"2024-03-17T14:55:49.000Z","dependencies_parsed_at":"2024-03-17T16:37:48.595Z","dependency_job_id":null,"html_url":"https://github.com/Airsequel/AirScript","commit_stats":null,"previous_names":["airsequel/airscript"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Airsequel/AirScript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airsequel%2FAirScript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airsequel%2FAirScript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airsequel%2FAirScript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airsequel%2FAirScript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Airsequel","download_url":"https://codeload.github.com/Airsequel/AirScript/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airsequel%2FAirScript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29311358,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T17:48:59.043Z","status":"ssl_error","status_checked_at":"2026-02-10T17:45:37.240Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["formula","fp","functional","functional-programming","language","programming-language","scripting","scripting-language"],"created_at":"2024-11-14T02:15:28.300Z","updated_at":"2026-02-10T18:35:55.116Z","avatar_url":"https://github.com/Airsequel.png","language":null,"readme":"# AirScript\n\nA scripting language for spreadsheet formulas, CLI tools, ETL pipelines.\n\nAka can be used as transformers:\n- cells → script → cell\n- stdin | script | stdout\n- read query → script → write query\n\n\n## Ideas\n\n- No side-effects (external data is stored in vars on start)\n- Pure (and probably lazy)\n- No modules/packages (but extensive stdlib)\n- Hard resource constraints (runtime, memory, cycles)\n- Typed (but no type annotations, only inference)\n- No recursive functions (prevents endless loops)\n- No currying\n- JIT compiled (No overhead of managing both the source and the binary)\n- List of available files (file content) in frontmatter\n    - With support for globbing\n\n\n## Observations\n\n**Input data is untyped.**\n\n- It's a lot of effort to generate all the necessary types\n    to represent the data.\n    (As seen in Elm and Haskell.)\n- TypeScript shows how runtime type-checking can be very helpful here.\n\n\n## Syntax\n\n- Everything that starts with `$` (constants, variables, …)\n    or starts with a capital letter (types, namespaces, …)\n    is provided by the prelude (aka standard library)\n- Syntax sugar for `f(g(h(i(j()))))`\n    - Maybe `f@g@h@i@j()`\n- `when … is …`\n    - Syntax sugar for boolean:\n      ```py\n      when x is\n      true \"Good job!\"\n      false \"Try again!\"\n      ```\n- TODO: Maybe use `Yes`/`No` instead of `True`/`False`\n    `YesNo = Yes | No`\n\n\n### Types\n\n- Number\n    - `0`, `2`, …\n    - `3.14`, …\n    - TODO: Maybe `Rational` would be a better default\n- Text\n    - `\"With spaces\"`\n    - `'single` (Also called atoms)\n- Result (`Result ok = Ok(ok) | Error(Text)`)\n    - No support for custom Error types,\n      as one can use atoms and map them\n      to full error messsages at the end\n- Options (e.g. `Options['north, 'east, 'south, 'west]`)\n\n\n## Examples\n\nManipulating JSON:\n\n```py\n---\ndescription: Convert item prices from € to % of total price\ntags: [json]\n---\n\njson_result = $parse_json($input)\n\nitems_result = when json_result is\n  Null -\u003e Error(\"Provide an Array and not Null\")\n  Object(hash_map) -\u003e hash_map.items  # `.` on hash maps returns Result\n  Array(items) -\u003e Ok(items)\n  _ -\u003e Error(\"Provide an Array and not a primitive value\")\n\nitems_total_price = Result:map(items_result,\n    items -\u003e items\n      \u0026 List:map(item -\u003e item.price \u0026 Result:withDefault(0))\n      \u0026 List:sum\n  )\n\n# Final expression must be a `Result`\n# - `Error`: E.g. printed to stderr, shown as cell error, …\n# - `Ok`: E.g. printed to stdout (`Json` is automatically stringified),\n#         shown as cell content, …\nitems_result\n  \u0026 Result:map(items -\u003e\n      items \u0026 List:map(item -\u003e\n        item.price\n          \u0026 Result:map(price -\u003e price / items_total)\n      )\n    )\n```\n\n\nInstead of threading the errors through the whole program,\nthis can also be simplified to:\n\n```py\n---\ndescription: Convert item prices from € to % of total price\ntags: [json]\n---\n\njson_result = $parse_json($input)\n\nitems = when json_result is\n  Array(items) -\u003e items\n  Null -\u003e $stop(Error(\"Provide an Array and not Null\"))\n  Object(hash_map) -\u003e $stop_error(hash_map.items)  # `.x` returns Result\n  _ -\u003e stop(Error(\"Provide an Array and not a primitive value\"))\n\nitems_total_price = items\n  \u0026 List:map(item -\u003e item.price \u0026 Result:withDefault(0))\n  \u0026 List:sum\n\nOk(items \u0026 List:map(item -\u003e\n  item.price \u0026 Result:map(price -\u003e\n    price / items_total_price\n  )\n))\n```\n\n\n## Related\n\n### Alternative Programming Languages\n\nDeal-breakers are marked with a ✋.\n\n- [PRQL](https://prql-lang.org/)\n    - Pipelined Relational Query Language\n    - Compiles to SQL\n\n- [Numbat](https://numbat.dev) (Rust)\n    - Statically typed\n    - For scientific computations\n    - First class support for physical dimensions and units\n    - ✋ No support for including external data\n\n- [Roc](https://www.roc-lang.org) (Rust)\n    - Statically typed\n    - ✋ Side effects\n","funding_links":["https://github.com/sponsors/Airsequel"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairsequel%2Fairscript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fairsequel%2Fairscript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairsequel%2Fairscript/lists"}