What

Rye takes concepts from REBOL (words, blocks, code is data), adds few unix shell-isms (pipes), some concatenative (Factor lang) ideas, some FP ideas and some of my own stuff.

It's initial "practical" focus is on shell / backend scripts.

Current status

It's an work-in-progress experimental *toy* language.

Implementation

Interpreter in Go. There is also Javascript implementation which will be synced with golang version at 0.01.

Anything practical

I'm making ryk, an awk like tool with Rye language and JSON processing support.

Javascript version is used as an embeded langauage at some of my webapps.

License

Will be open source.

Updates

14.apr.2019 Added experimental support for currying.

02.jun.2019 Added first version of generic functions. Lit-words, genwords ...

27.sep.2019 Started adding a tree based co-language Spruce.

General concept

Like Rebol, Rye is basically a data language (think JSON, but more) but this data can also be executed by any number of dialects. Default dialect being the DO dialect or what one would call basic Rye languge.

Examples

Rebol-like code works in Rye too

debug: 1
print-if: fn [ cond x ] [ if cond [ print x ] ]
print-if positive? debug "debug mode"
Differences compared to REBOL

both [] and {} denote blocks. {} is default.

print-if: fn { cond x } { if cond [ print x ] }

functions, words and pipewords

add 2 3    // is the same as 
2 |add 3   // or in this case
2 .add 3

opwords vs. pipewords

subtract 10 add 2 3   // returns 5 (subtract 10 (add 2 3))
10 .subtract 2 .add 3 // returns 5
10 .subtract 2 |add 3 // returns 11

hypotethical pipewords example

get-links-to: fn [ url to ] {
  read url |html->xml
  |xml-reduce 'o {} [ on <a> 'x { join o x .attr 'href } ]
  |filter 'x [ found? find x to ]
}

get-links-to http://www.cebelca.biz "www.ajpes.si"

optional expression guards

a: subtract 10 add 2 3 add a 50   // returns 55
a: subtract 10 add 2 3 , add a 50 // returns 55
a: subtract 10 add 2 , 3 add a 50 // error

function currying

add5: add 5 _ add5 50                    // returns 55 
second: nth _ 2 , { 11 22 33 } .second   // returns 22

clojure inspired recur(-if) - just experimenting

factorial: fn { n a } { positive? n |recur-if-2  n - 1  n * a , a } 
loop 100000 { factorial 12 1 }

first clumsy version of generic functions

// function "generic" takes a word determining kind, 
// word to bind to
// and a user or a builtin function
// function "fn" creates and returns a function
generic 'integer 'Add fn { a b } { a + b }

// "join" is a builtin function, 
// get-word "?join" returns the builtin without evaluating it
generic 'string 'Add ?join 

Add 100 11           // returns 111
Add "woof" "woof"    // returns "woofwoof"

// later it might look more like this
gfn 'Add { 'integer a b } { a + b }

The plan is that generic functions will be default and all builtins will be generic functions, so this will change. Ordinary functions will only be used for smaller local utility functions.

.

There are many more differences, some are still being thought about.

Rye for example currently doesn't plan on having refinements.

Rye values (current)
integer
1
string
"string"
word
name
set-word
name:
op-word
.add
pipe-word
|stream
lit-word
'litteral
gen-word
Generic
get-word
?somefunc
comma
,
void
_
function
fn { x } { inc x }
block
{ word 1 2 , name: "jim" }
with do dialect
integers, strings, blocks
return themselves
words
return (rye) values they are bound to
set-words
bind values to words
op-words, pipe-words
evaluate functions it's bound to in infix manner
get-words
return value of word without evaluation (like function or builtin)
lit-words
literal words, return the word itself
gen-words
generic words, return function or builtin based on kind of first argument
comma
produces error, if not between block-level expression
void
returns itself, when passed as an argument to a function it curries it
function
executes, consuming arguments next to it
Links
Subscribe for updates

What's next

tuples/objects with it's validation dialect, kinds and generic functions dispatching on them.

What is it

Not sure if it can be called a programming language. It's main building block is a tree of Rye values.

I think this gives us new oportunities for creating interesting programming, exploration and user experiences.

Status

in ideas stage

Why

Could be interesting way to "script", manipulate code, maybe more accessible to non-programmers and non keyboard devices.

License

Will be open source.

Example
build spruce {
 give
  me
   five
    { add 3 2 }
  your
   name
    { capitalize "spruce" }
}

give me five
. returns 5

give me your name
. returns Spruce
Bigger theoretical example
. this is a builder dialect. It builds / adds to the spruce tree.

build spruce {
 when
  email
   is 
    received 
     do
      {todo:block}
      [ on-event 'email-received { 'it 'email } todo ]
 if
  {cond:boolean}
   do
    {todo:block}
    [ core/if cond todo ]
 its
  {key:string}
  [ core/at It key ]
 {a:boolean}
  and
   {b:boolean}
   [ core/and a b ]
 {val:string}
  includes
   text
    {text:string}
  is
   from
    domain
     {domain:string}
}

. below is the user dialect

when email is received do {

	if its 'title includes text 'offer do {
		flag it 'commercial
		forward it
	}

	If its 'sender is from domain 'nlb.si 
	and it's 'title includes text "izpisek" do {
		add its 'title to log
		archive it under "nlb izpiski"
	}
}
	
Status

in development

Why

I love awk. It's used a lot in interactive, ad-hoc manner so I see this as a good practical case with which in mind Rye can be developed in this early stage.

Potential forte

A concrete programming language, but with possible specific dialects. I also plan to add a functionality for stream-processing CSV and JSON files.

License

Will be open source.

Examples

basic example

$ cat > peers.txt
1   SI  janko
2   US  jim
3   SI  luka
$ cat peers.txt | ryk '/SI/ { _1 + 100 , _3 .capitalize }'
101  Janko
103  Luka