{"id":23091437,"url":"https://github.com/famished-tiger/skeem","last_synced_at":"2025-04-03T18:18:08.402Z","repository":{"id":56896010,"uuid":"146031909","full_name":"famished-tiger/Skeem","owner":"famished-tiger","description":"A Ruby implementation of the Scheme language (a subset of)","archived":false,"fork":false,"pushed_at":"2025-03-30T15:53:24.000Z","size":276,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T16:31:48.100Z","etag":null,"topics":["interpreter","r7rs","ruby","scheme","scheme-programming-language"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","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/famished-tiger.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-24T19:28:09.000Z","updated_at":"2025-03-30T15:53:27.000Z","dependencies_parsed_at":"2022-08-21T01:50:22.363Z","dependency_job_id":null,"html_url":"https://github.com/famished-tiger/Skeem","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/famished-tiger%2FSkeem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/famished-tiger%2FSkeem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/famished-tiger%2FSkeem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/famished-tiger%2FSkeem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/famished-tiger","download_url":"https://codeload.github.com/famished-tiger/Skeem/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247052620,"owners_count":20875685,"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":["interpreter","r7rs","ruby","scheme","scheme-programming-language"],"created_at":"2024-12-16T21:18:22.335Z","updated_at":"2025-04-03T18:18:08.379Z","avatar_url":"https://github.com/famished-tiger.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skeem\n|Linux|Windows|  \n|:-:|:-:|  \n|[![Linux Build Status](https://travis-ci.org/famished-tiger/Skeem.svg?branch=master)](https://travis-ci.org/famished-tiger/Skeem)|[![Windows Build Status](https://ci.appveyor.com/api/projects/status/qs19wn6o6bpo8lm6?svg=true)](https://ci.appveyor.com/project/famished-tiger/skeem)|\n\n[![Gem Version](https://badge.fury.io/rb/skeem.svg)](https://badge.fury.io/rb/skeem)\n[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/famished-tiger/Skeem/blob/master/LICENSE.txt)\n\n__Skeem__ is a Scheme language interpreter written in Ruby.\n\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'skeem'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install skeem\n\n\nThe __Skeem__ project is WIP and currently the gem supports a subset of the __Scheme__ language.  \nIf you're not familiar to Scheme, the section [About Scheme](#about-scheme) contains a number of interesting pointers.\n\n\n## Usage\nOnce the gem is installed, the `skeem` executable can be used.\nIt allows to run the interpreter from a REPL console or from the command line.\nAnother way to interact with the Skeem interpreter is to embed it in your Ruby code.\n\n### Launching a REPL session\nTo start a REPL (Read-Eval-Print-Loop) session, just type:\n```\n  skeem\n```\n\nSkeem displays a greeting, a prompt and then waits for your input:\n```\nWelcome to Skeem 0.2.16.\n\u003e\n```\n\nNow that we know that `Skeem` is well alive, let's kick it...\nWe begin with the ritual 'Hello world' example, by typing after the __\u003e__ prompt:\n```\n(display \"Hello, world\")\n```\n\nSkeem then replies:\n```\nHello, world\nSkeem::SkmUndefined\n```\n\nThis works as expected except, maybe, for the last line. It can be easily explained if one knows\nthat the return value of the `display` procedure is undefined in standard Scheme.  \nInternally Skeem, implements such undefined result as a `Skeem::Undefined`instance.\n\nTo give some taste of things, here is an excerpt from a REPL session:\n```\n\u003e (+ 4 (* 5 6))\n34\n\u003e (define x 6)\n6\n\u003e (+ (* 5 x x) (* 4 x) 3)\n207\n\u003e (/ 21 5)\n21/5\n\u003e (/ 21.0 5)\n21/5\n```\n\n#### Terminating a REPL session\nTo exit a REPL session, call the `exit` procedure as follows:\n```\n(exit)\n```\n\n### Running a Skeem file\nTo run a Scheme file:\n\n```\n  skeem path/to/some-file.skm\n```\n\nBy the way, the `/bin` folder of the `skeem` gem contains a couple of Skeem sample files.\n\n## Embed Skeem in your Ruby app\nThis is the third way for Rubyists to interact with Skeem by integrating it directly in their Ruby code.\n\n### Example 1 (Variable definition)\n\n```ruby\n  require 'skeem'\n\n  schemer = Skeem::Interpreter.new\n\n  scheme_code =\u003c\u003c-SKEEM\n    ; This heredoc consists of Scheme code...\n    ; Let's define a Scheme variable\n    (define foobar (* 2 3 7))\n\n    ; Now test its value against a lower value\n    (if (\u003e foobar 40) #true #false)\n  SKEEM\n\n  # Ask Ruby to execute Scheme code\n  result = schemer.run(scheme_code)\n  puts result.value # =\u003e true\n\n  # The interpreter object keeps the bindings of variable\n  # Let's test that...\n  scheme_code = '(* foobar foobar)'\n  result = schemer.run(scheme_code)\n  puts result.value # =\u003e 1764\n```\n\n### Example 2 (Defining a function)\n\n```ruby\n  require 'skeem'\n\n  schemer = Skeem::Interpreter.new\n\n  scheme_code =\u003c\u003c-SKEEM\n    ; Let's implement the 'min' function\n    (define min (lambda (x y) (if (\u003c x y) x y)))\n\n    ; What is the minimum of 2 and 3?\n    (min 2 3)\n  SKEEM\n\n  # Ask Ruby to execute Scheme code\n  result = schemer.run(scheme_code)\n  puts result.value # =\u003e 2\n\n  # Let's retry with other values\n  scheme_code = '(min 42 3)'\n  result = schemer.run(scheme_code)\n  puts result.value # =\u003e 3\n```\n### Example 3 (Defining a recursive function)\n```ruby\n  require 'skeem'\n\n  schemer = Skeem::Interpreter.new\n  scheme_code = \u003c\u003c-SKEEM\n    ; Compute the factorial of 100\n    (define fact (lambda (n)\n      (if (\u003c= n 1) 1 (* n (fact (- n 1))))))\n    (fact 100)\n  SKEEM\n\n  result = schemer.run(scheme_code)\n  puts result.value # =\u003e 9332621544394415268169923885626670049071596826438162146859296389521759999322991560894146397615651828625369792082722375825118521091686400000000000000000000000\n```\n### Example 4 (Defining a procedure that holds its own environment)\n```ruby\n  require 'skeem'\n\n  schemer = Skeem::Interpreter.new\n  scheme_code = \u003c\u003c-SKEEM\n  (define make-counter\n    ;; create a procedure that will bind count and\n    ;; return a new procedure that will iself increment the\n    ;; variable and return its newest value\n    (lambda ()\n       (let ((count 0))\n          (lambda ()\n             (set! count (+ count 1))\n             count))))\n\n  (define c1 (make-counter))\n  (define c2 (make-counter))\n  (define c3 (make-counter))\n\n  ;; Notice how each procedure keeps track of its \"own\" counter.\n  (c1) ; =\u003e 1\n  (c2) ; =\u003e 1\n  (c1) ; =\u003e 2\n  (c3) ; =\u003e 1\n  (c1) ; =\u003e 3\n  SKEEM\n\n  result = schemer.run(scheme_code)\n  puts result.last.value # =\u003e 3\n```\n\n### Example 5 (Conditional branching)\n\n```ruby\n  require 'skeem'\n\n  schemer = Skeem::Interpreter.new\n\n  scheme_code =\u003c\u003c-SKEEM\n    ; Let's implement the 'signum' function\n    (define signum (lambda (x)\n       (cond\n         ((positive? x) 1)\n         ((zero? x) 0)\n         (else -1))))\n\n    (signum -3)\n  SKEEM\n\n  result = schemer.run(scheme_code)\n  puts result.value # =\u003e -1\n```\n\n\n## Currently implemented R7RS features\n### Comments\n- Semi-colon delimited comments: `; This comment stops at the end of line`\n- Block `#| ... |#` comments\n\n### Data type literals\n- Booleans: `#t`, `#true`, `#f`, `#false`  \n- Characters: `#\\a`, `#\\newline`, `#\\x3BB`\n- Of the number hierarchy:  \n  `real` (e.g. 2.718, 6.671e-11),  \n  `rational` (e.g. 22/7, 1/137, -13/41)  \n  `integer` (42, -3 also in hexadecimal notation: #x3af)\n- Lists (quoted) : '(1 two \"three\")\n- Strings: `\"Hello, world.\"`\n- Identifiers (symbols): `really-cool-procedure`\n- Vectors: `#(1 2 \"three\")`\n\n### Scheme Expressions\n- Constant literals\n- Quotations\n- Quasiquotation (without unquote-splicing)\n- Variable references\n- Procedure calls\n- Lambda expressions\n- Conditionals (`if`, `cond`)\n- Definitions\n- Assignments\n- Iteration (`do`)\n- Control procedures\n\n### Standard library\nThis section lists the procedures following closely the official [Revised7 Report on the Algorithmic Language](https://bitbucket.org/cowan/r7rs/src/draft-10/rnrs/r7rs.pdf) standard.\n\n#### Equivalence predicates\n* `eqv?`, `equal?`\n\n#### Boolean procedures\n* `boolean?`, `boolean=?`, `and`, `or`,  `not`\n\n#### Character procedures\n* `char?` `char-\u003einteger`, `char=?`, `char\u003c?`, `char\u003e?`,`char\u003c=?`, `char\u003e=?`\n\n#### Numerical operations\n* Number-level: `number?`, `complex?`, `real?`, `rational?`, `integer?`, `zero?`,  \n`exact?`, `inexact?`, `exact-integer?` , `+`, `-`, `*`, `/`, `=`, `square`, `number-\u003estring`\n* Real-level: `positive?`, `negative?`, `\u003c`, `\u003e`, `\u003c=`, `\u003e=`, `abs`, `max`, `min`,  \n `floor/`, `floor-quotient`, `floor-remainder`, `truncate/`, `truncate-quotient`,  \n`truncate-remainder`, `quotient`, `remainder`, `modulo`, `gcd`, `lcm`, `numerator`,  \n`denominator`, `floor`, `ceiling`, `truncate`, `round`\n* Integer-level: `even?`, `odd?`, `integer-\u003echar`\n\n#### List procedures\n* `list?`, `null?`, `pair?`, `append`, `car`, `cdr`, `caar`, `cadr`, `cdar`, `cddr`,  \n`cons`,  `make-list`, `length`, `list`, `list-copy`, `list-\u003evector`, `reverse`,  \n`set-car!`, `set-cdr!`, `assq`, `assv`\n\n#### String procedures\n* `string?`, `string=?`, `string`, `make-string`, `string-append`, `string-length`, `string-\u003esymbol`\n\n#### Symbol procedures\n* `symbol?`, `symbol=?`, `symbol-\u003estring`\n\n#### Vector procedures\n* `vector?`, `make-vector`, `vector`, `vector-length`, `vector-set!`, `vector-\u003elist`\n\n#### Control procedures\n* `procedure?`, `apply`, `map`\n\n#### Input/output procedures\n* `display`, `newline`\n\n#### Non-standard procedures\n* `assert`\n\n\n### Standard syntactic forms\n#### define  \n__Purpose:__ Create a new variable and bind an expression/value to it.  \n__Syntax:__   \n* (define \u003cidentifier\\\u003e \u003cexpression\\\u003e)  \n* (define (\u003cvariable\\\u003e \u003cformals\\\u003e) \u003cbody\\\u003e)\n\n#### if  \n__Purpose:__ Conditional evaluation based on a test expression.  \n__Syntax:__   \n* (if \u003ctest\\\u003e \u003cconsequent\\\u003e)  \n* (if \u003ctest\\\u003e \u003cconsequent\\\u003e \u003calternate\\\u003e)  \n\n\n#### lambda  \n__Purpose:__ Definition of a procedure.  \n__Syntax:__   \n* (lambda \u003cformals\\\u003e \u003cbody\\\u003e)\n\n#### quote  \n__Purpose:__ Quoting an expression (leave it unevaluated).  \n__Syntax:__   \n* (quote \u003cdatum\\\u003e)\n* '\u003cdatum\\\u003e\n\n#### set!  \n__Purpose:__ Assign to an existing variable an expression/value to it.  \n__Syntax:__   \n* (set! \u003cidentifier\\\u003e \u003cexpression\\\u003e)  \n\n### Derived expressions\n#### cond  \n__Purpose:__ Define one or more branchings.  \n__Syntax:__   \n* (cond (\u003ctest\\\u003e \u003cconsequent\\\u003e)\\+)  \n* (cond (\u003ctest\\\u003e\u003cconsequent\\\u003e)* (else \u003calternate\\\u003e))\n\n#### do\n__Purpose:__ Sequential iteration  \n__Example__\n```scheme\n(do (\n    (vec (make-vector 5))\n    (i 0 (+ i 1)))\n  ((= i 5) vec)\n  (vector-set! vec i i)) ; =\u003e #(0 1 2 3 4)\n```\n\n#### let  \n__Purpose:__ Define one or more variable local to the block.  \n__Syntax:__   \n* (let (\u003cbinding_spec\\*\\\u003e) \u003cbody\\\u003e)\n\n\n#### let*  \n__Purpose:__ Define one or more variable local to the block.  \n__Syntax:__   \n* (let* (\u003cbinding_spec\\*\\\u003e) \u003cbody\\\u003e)\n\n\n## Roadmap\n- Implement an equivalent of [lis.py](http://www.norvig.com/lispy.html)\n- Implement an equivalent of [lispy](http://norvig.com/lispy2.html)\n- Make it pass the test suite\n- Extend the language in order to support [Minikanren](https://github.com/TheReasonedSchemer2ndEd/CodeFromTheReasonedSchemer2ndEd)\n- Make it pass all examples from the [Reasoned Schemer](https://mitpress.mit.edu/books/reasoned-schemer-second-edition) book.\n\n## About Scheme\n\nThe Scheme programming language is a Lisp dialect that supports multiple paradigms, including functional programming and imperative programming.\n\n### Resources on Scheme  \nHere are a few pointers for the Scheme programming language:  \n- Wikipedia article on [Scheme](https://en.m.wikipedia.org/wiki/Scheme_\\(programming_language\\))\n- Latest official Scheme standard: [R7RS](https://bitbucket.org/cowan/r7rs-wg1-infra/src/default/R7RSHomePage.md)\n#### Online tutorials and books:\n- [The Scheme Programming Language, 4th Edition](https://www.scheme.com/tspl4/) by Kent Dybvig. A complete, introductory textbook on Scheme based on the older R5RS standard.\n- [Teach Yourself Scheme in Fixnum Days](http://ds26gte.github.io/tyscheme/index.html) by Dorai Sitaram\n- [Yet Another Scheme Tutorial](http://www.shido.info/lisp/idx_scm_e.html) by Shido Takafumi\n- [An Introduction to Scheme and its Implementation](http://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v14/schintro_toc.html) by Paul R. Wilson\n\n\n## Other Scheme implementations in Ruby\n__Skeem__ isn't the sole implementation of the Scheme language in Ruby.  \nHere are a few other ones:  \n- [Heist gem](https://rubygems.org/gems/heist) -- Probably one of best Scheme implementation in Ruby. Really worth a try. Alas, the [project](https://github.com/jcoglan/heist) seems to be dormant for several years.\n- [Schemerald gem](https://rubygems.org/gems/schemerald). The last commit for the [project](https://github.com/vntzy/schemerald) is October 2017.\n\n- [rubic gem](https://rubygems.org/gems/rubic). The last commit for the [project](https://github.com/notozeki/rubic) is June 2015.\n\n- [RLisp](https://github.com/davydovanton/rlisp) ...Simple scheme interpreter written in ruby\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/famished-tiger/Skeem.\nThis project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the\n[Contributor Covenant](http://contributor-covenant.org) code of conduct.\n\n## License\n\nCopyright\n---------\nCopyright (c) 2018-2021, Dimitri Geshef.  \n__Skeem__ is released under the MIT License see [LICENSE.txt](https://github.com/famished-tiger/Skeem/blob/master/LICENSE.txt) for details.\n\n## Code of Conduct\n\nEveryone interacting in the Skeem project’s codebases, issue trackers,\nchat rooms and mailing lists is expected to follow the\n[code of conduct](https://github.com/famished-tiger/Skeem/blob/master/CODE_OF_CONDUCT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffamished-tiger%2Fskeem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffamished-tiger%2Fskeem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffamished-tiger%2Fskeem/lists"}