Rye Language

What’s Rye? Dynamic programming language focused on fluid expressions, still in development.

What’s it for? It was made for backend/server-side/CLI jobs, but also got GUI frameworks recently.

<

About Rye

Rye is a high level, homoiconic dynamic programming language based on ideas from Rebol, flavored by Factor, Linux shell and Go. It's still in development, but we are focused on making it useful as soon as possible.

It's written in Go and could also be seen as Go's scripting companion as Go's libraries are very easy to integrate, and Rye can be embedded into Go programs as a scripting or a config language.

I believe that as a language becomes higher level it starts bridging the gap towards user interfaces. Rye has great emphasis on interactive use where we intend to also explore that.

Rye console (REPL) features many interesting syntax highlighting, history, tab completition and many console specific functions that help you navigate and introspect the language and environment you are shaping

Short Rye examples

Change Hello World to Hello Mars and print it.
"Hello World" .replace "World" "Mars" |print
; prints "Hello Mars"
Find the Sum of unique numbers in a string.
"12 8 12 16 8 6" .load .unique .sum
; returns 42
Use switch function to get the sound of the animal.
switch 'cow { dog { "woof" } cow { "mooo" } cat { "meow" } }
; returns mooo
Extract combination of one number and one letter from string.
regexp "([0-9][a-z])" |submatch? "-7--x3--0k-r--"
; returns 0k
Print out names starting with A.
{ "Anne" "Joan" "Adam" } |filter { .first = "A" }
|for { .print } 

IO, Spreadsheet, HTTP client

Read a file, print the number of lines and the last 5 lines.
read\lines %data.txt |with
{ .length? .print , .tail 5 |print }
Load a CSV, get average score of all players of level 7.
load\csv %ryebots.csv |where-equal 'level 7
|column? 'score |avg
Load a webpage, save it to a file, print out all the links.
get https://ryelang.org |write* %page.html
|reader |parse-html { <a> [ .attr? 'href |print ] }

HTTP, SMTP server

Serve folder over HTTP
http-server ":8082"
|handle "/" new-static-handler %public_html
|serve
Web server that responds with current time.
http-server ":8081"
|handle "/time" fn { w r } { .write to-string now }
|serve
Start smtp server and print notification on new email.
handler: fn { mail from to origin } {
printv from "new mail from {}" }
smtp-server ":25" |serve ?handler "demo"
      

Dialects

Validation dialect
dict { name: "anakin" } |validate { 
   name: required calc { .capitalize } 
   score: optional 0 integer }
; returns { name: "Anakin" score: 0 }	  
Math dialect.
; Rye like Rebol or Lisp has no operator precedence.
; But it has Math dialect which has it and more.
math { 2 + 2 * sqrt ( 12 + ( 24 / 3 ) ) }
; returns 42
SQL dialect.
rye .args .first :id
open sqlite://data.db
|query { select * from operator where id = ?id }

GUI

See the Cookbook for many more GUI Examples.
do\in fyne {
	  
	lab: label "I'm Waiting ..."
	btn: button "Click here" does { lab .set-text "Finally ..." }
	box: v-box [ lab layout-spacer btn ]
	
	with app .window "Button" {
		.resize size 200.0 100.0 ,
		.set-content box ,
		.show-and-run
	}
}
See the Cookbook for many more GUI Examples.
 
do\in fyne {
  app .window "Percentage Clock" :win
  
  cont: v-box [
    label "This Year [days]" :ly
    progress-bar :py
    label "This month [days]"
    progress-bar :pM
    label "Today [hours]"
    progress-bar :ph
    label "This hour [minutes]"
    progress-bar :pm
    label "This minute [seconds]"
    progress-bar :ps
  ]
  
  m-of: ?multiple-of
  is-leap-year: fn { y } { all { y .m-of 4  not y .m-of 100  not y .m-of 400 } }
  days-in: fn { y } { .is-leap-year .either { 366 } { 365 } }

  go fn\par { } current {
    forever {
      with n:: now {
        .year? ::y |concat* "Year " |set-text* ly ,
        .year-day? / days-in y  |set-value* py ,
        .day? / days-in-month? n |set-value* pM ,
        .hour?     / 24 |set-value* ph ,
        .minute?   / 60 |set-value* pm ,
        .second?   / 60 |set-value* ps
        sleep 500
      }
    }
  }
  win |resize size 300.0 200.0 |set-content cont |show-and-run
}
 

Delve deeper

If examples above made you interested, you can delve deeper into the Rye language and Rye runtime. You have two sources for that, both are still work-in-progress, so check back later for more and better content:

Meet RyeFocuses on Rye language, it's basics, concepts and components
Rye CookbookFocuses on practical uses and specific technologies
Function referenceBasic documentation and simple examples for many core functions

Where

Rye can run on Linux, Mac OS or Windows. Rye also runs in a web-browser (Wasm) and Docker. Rye could be compiled for mobile (Android and OSx).

You can try a (work in progress) browser-based Rye console right now by clicking a button on top-right of this page.

Get Ryelang

x86 64arm 64arm v6wasm
Linuxv0.0.26 v0.0.26 v0.0.26
Mac OSv0.0.26 v0.0.26-
Windowsv0.0.26 v0.0.26-
/v0.0.26
Homebrewbrew install ryelang
Dockerdocker pull ghcr.io/refaktor/rye:latest

Development

Rye's Github repository is where everything happens. You are welcome to visit it, read it, star it, post issues, contribute ...

Since Rye uses Go, building it from source is very simple. Follow instructions in the README.

Bateries included

Rye's main binary comes with core language functions and also a lot of bindings and technologies already included. At least in a very basic level. Below are some examples of already included technologies:

AWS Bcrypt BSON Crypto FT search Goroutines HTML parser HTTP servers JSON MySQL Psql Postmark Regexp SMTP server SXML SQLite

Sub-projects

Rye can be extended internally or externally. Two bigger external extension are developed in their own repositories:

Fyne GUI frameworkRye-fyne repository Download: Linux MacOS Windows
Gio UI frameworkRye-gio repository
Ebitengine game engineRye-ebitengine repository
RyegenRyegen repository

Related sites

Github Blog Reddit Old blog Asciinema Youtube

Rye concepts

  • Expressions not statements
    Everything in Rye is an expression, returns a value. In general, Rye always returns vs. changes values in-place.
  • Code is data / data is code
    Rye is fully runtime homoiconic. Rye code consists of Rye data. Rye data can be interpreted.
  • First class everything
    All language constructs in Rye, from literals, blocks, functions and contexts (scopes), are Rye values.
  • Everything a function
    Every active component in Rye is a function (if, loop, for, fn, return, extends, context). No keywords, no special forms.
  • Separation of state and functionality
    Rye is not an object-oriented language, it's also not purely functional, maybe practically functional.
  • Code flow = information flow
    Rye code tries to reduce the use of state and emphasize the flow of information, fewer variables - more flows!
  • Strict about effects
    Rye has no syntax to directly change a value in its parent or child context (scope), all communication between contexts requires function calls. Furthermore, by convention, a limited number of functions, that change state in-place, end with an exclamation mark (append!, set!, change!, ...).
  • No nil, null, none
    Rye functions return a result (succes) or failure. There is no third state, no so called 'billion dollar mistake'.
  • Failures can be handeled, code errors can only be fixed
    Rye distinguishes between a failure of a function to produce a result, which can be handled nicely, without breaking a flow. Or a code Error, which means an unknown state, so the program should generally stop and Error should be fixed in code. An unhandled failure is also a code Error.
  • Explicit value validation
    Rye has a validation dialect that makes validation declarative, visible and explicit instead of sprinkled around your business logic. Same with conversion.
  • Spreadsheet datatype
    You can't achieve a higher level language with the same old value types. Many human data is tabular and a list of dictionaries doesn't cut it. Rye's Spreadsheet datatype and declarative approach can absurdly cut the code amount.
  • Words-in-context oriented
    Rye tries to avoid too computer-specific or computational paradigms (procedural, OO, functional) terminology. Its vocabulary tries to focus more on information manipulation itself and the end-users, people. Programs are organized around contexts and words (which are bound to functions or other values), not classes, objects, modules, ...

Rye dualities

Rye tries to explore some maybe absurd dualities:

  • Language vs User interface
    Is UI just uncomposable, unscriptable, static but very problem-specialized language or is language at high enough level just UI?
  • Flexibility vs Predictability
    Can you make a wildly flexible multi-language, but with a environment and state interactions that promote and even improve predictability?
  • Interactive use vs Code
    The same language should be able to be good at interactive (console) use and coding (scripts) and the knowledge and code should be transferable between the two
  • Library vs App
    Could it be in some cases simpler to use a library to construct a simple application for exactly what you need, versus installing and configuring a bigger app to do that?

Website updates

• New sections were added to the Cookbook: Deployment and Improving Rye [2024-10-27]

• First version of Rye-Gio posted on Github Gioui is a Golang immediate mode UI library [2024-10-07]

• Added Cookbook > Rye binary showing commands and flags that make Rye binary much more versatile [2024-10-03]

• Binaries for GUI library Rye-Fyne available on Releases page [2024-10-01]

Thank you

Thank you for visiting this site and reading to the end. If you see any potential here, don't be a stranger, join, star or subscribe us on github, reddit, youtube, ... or just send me an email!

Especially github is usually updated every few days! If you want to contribute in any way, even better, there are always open tasks to complete, from docs, tests, examples, to Go coding.