{"id":48749131,"url":"https://github.com/sapphire-project/sapphire","last_synced_at":"2026-05-08T06:24:40.959Z","repository":{"id":349284056,"uuid":"1201660630","full_name":"sapphire-project/sapphire","owner":"sapphire-project","description":"A small OOP language inspired by Ruby","archived":false,"fork":false,"pushed_at":"2026-05-03T04:51:37.000Z","size":1068,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-03T06:32:10.202Z","etag":null,"topics":["programming-language","ruby","rust"],"latest_commit_sha":null,"homepage":"https://sapphire-lang.dev/","language":"Rust","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/sapphire-project.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-05T01:24:26.000Z","updated_at":"2026-04-30T04:36:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"07c0ba8c-8494-4a7a-925e-25cb8e2755c2","html_url":"https://github.com/sapphire-project/sapphire","commit_stats":null,"previous_names":["nithinbekal/sapphire","sapphire-project/sapphire"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/sapphire-project/sapphire","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sapphire-project%2Fsapphire","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sapphire-project%2Fsapphire/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sapphire-project%2Fsapphire/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sapphire-project%2Fsapphire/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sapphire-project","download_url":"https://codeload.github.com/sapphire-project/sapphire/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sapphire-project%2Fsapphire/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32767929,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T02:36:36.067Z","status":"ssl_error","status_checked_at":"2026-05-08T02:36:07.210Z","response_time":54,"last_error":"SSL_read: 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":["programming-language","ruby","rust"],"created_at":"2026-04-12T15:55:46.109Z","updated_at":"2026-05-08T06:24:40.928Z","avatar_url":"https://github.com/sapphire-project.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sapphire\n\nA Ruby-inspired, gradually typed, object-oriented scripting language — everything is an object, types are optional, and the syntax stays out of your way.\n\n**[Website](https://sapphire-lang.dev/)** · **[Try it online](https://sapphire-lang.dev/try/)** · **[Tutorial](https://sapphire-lang.dev/tutorial/)**\n\n## Features\n\n- **Gradual typing** — annotate as much or as little as you like; types are checked at runtime when present\n- **Everything is an object** — `Int`, `Bool`, `String`, and other primitives have methods\n- **Classes with inheritance** — single inheritance, `attr` fields, private methods via `defp`, class methods\n- **Closures and blocks** — first-class functions, `yield`, and block-accepting methods\n- **Rich standard library** — `List`, `Map`, `Set`, `String`, `Regex`, `Math`, `Date`, `File`, and more\n- **Imports** — split code across files with `import`\n- **Mark-and-sweep GC** — handles cycles; no manual memory management\n\n## Quick look\n\n```ruby\nclass Shape {\n  attr color = \"red\"\n\n  def area() { 0 }\n\n  def describe() {\n    \"A #{self.color} shape with area #{self.area()}\"\n  }\n}\n\nclass Circle \u003c Shape {\n  attr radius: Float\n\n  def area() {\n    Math::PI * self.radius * self.radius\n  }\n}\n\nc = Circle.new(color: \"blue\", radius: 3.0)\nprint c.describe()\nprint c.is_a?(Shape)   # true\n```\n\n## Syntax\n\n### Variables and types\n\n```ruby\nx = 10\nname: String = \"alice\"\nflag = true\n```\n\n### Arithmetic and comparisons\n\n```ruby\n1 + 2 * 3\nx == 10\nx \u003e 0\n!flag\n```\n\n### Control flow\n\n```ruby\nif x \u003e 0 {\n  print x\n} elsif x == 0 {\n  print \"zero\"\n} else {\n  print \"negative\"\n}\n\nwhile x \u003c 10 {\n  x = x + 1\n}\n\n(1..5).each { |i| print i }\n```\n\n### Functions\n\n```ruby\ndef add(a: Int, b: Int) -\u003e Int {\n  a + b\n}\n\ndef clamp(value: Int, min: Int, max: Int) -\u003e Int {\n  return min if value \u003c min\n  return max if value \u003e max\n  value\n}\n```\n\nBlocks and `yield`:\n\n```ruby\ndef repeat(n: Int) {\n  i = 0\n  while i \u003c n {\n    yield(i)\n    i = i + 1\n  }\n}\n\nrepeat(3) { |i| print \"step #{i}\" }\n```\n\n### Classes\n\n```ruby\nclass BankAccount {\n  attr balance: Int = 0\n\n  def deposit(amount: Int) {\n    self.balance = self.balance + validate(amount)\n  }\n\n  def withdraw(amount: Int) {\n    self.balance = self.balance - validate(amount)\n  }\n\n  defp validate(amount: Int) -\u003e Int {\n    raise \"amount must be positive\" if amount \u003c= 0\n    amount\n  }\n}\n\naccount = BankAccount.new()\naccount.deposit(100)\naccount.withdraw(30)\nprint account.balance   # 70\n```\n\nClass methods use `self { }`:\n\n```ruby\nclass Color {\n  attr r: Int\n  attr g: Int\n  attr b: Int\n\n  self {\n    def red()   { Color.new(r: 255, g: 0, b: 0) }\n    def green() { Color.new(r: 0, g: 255, b: 0) }\n    def blue()  { Color.new(r: 0, g: 0, b: 255) }\n  }\n}\n\nc = Color.red()\n```\n\n### Collections\n\n```ruby\nnumbers = [3, 1, 4, 1, 5, 9]\n\ndoubled = numbers.map { |n| n * 2 }\nevens   = numbers.select { |n| n % 2 == 0 }\ntotal   = numbers.reduce(0) { |acc, n| acc + n }\n\nprint numbers.any? { |n| n \u003e 8 }   # true\nprint numbers.all? { |n| n \u003e 0 }   # true\n```\n\n```ruby\nscores = { alice: 95, bob: 82, carol: 91 }\nscores.each { |name, score| print \"#{name}: #{score}\" }\npassing = scores.select { |_, score| score \u003e= 90 }\n```\n\n### Imports\n\n```ruby\nimport \"./geometry/point\"\nimport \"./geometry/shapes\"\n\np = Point.new(x: 1.0, y: 2.0)\n```\n\n### Error handling\n\n```ruby\nbegin\n  result = risky_op()\nrescue e\n  print \"caught: #{e}\"\nelse\n  print \"ok: #{result}\"\nend\n```\n\nInline rescue inside a function:\n\n```ruby\ndef safe_div(a: Int, b: Int) -\u003e Int {\n  a / b\nrescue e\n  0\n}\n```\n\n## Running\n\n```\nsapphire run file.spr      # run a file\nsapphire test              # run *_test.spr files\nsapphire typecheck file.spr\nsapphire console           # start the REPL\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsapphire-project%2Fsapphire","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsapphire-project%2Fsapphire","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsapphire-project%2Fsapphire/lists"}