"Every active component in Rye is a function (if, loop, for, fn, return, extends, context). No keywords, no special forms."
It should make the language much simpler than other languages.
The challenge of programming is dealing with copmplexity in code, and if the language takes away much of that complexity it should be a good thing.
Thanks, that comes from it's REBOL base ideas, but maybe it's even more pronounced in Rye where also operators are just "op-word" functions, and any function can be op-word/pipe-word (also the ones above if loop for ...).
Yes ... Rye is syntax-wise in similar camp than Lisps, only without parenthesis. Some say Lisp has no syntax (which is debatable), but has a point that there are no syntax rules. There are multiple token types and they always combine / apply in the same ways, there are no special forms like "how to define a function" or "how to write and if else". In Rye calling if or eihter (if/else) is no different than calling any other function.
Carl Sassenrath, the creator of the Amiga OS, created REBOL after he did Amiga Logo. Logo is what REBOL's syntax was based on. Logo is often called, 'Lisp without parentheses'.
> There are multiple token types and they always combine / apply in the same ways, there are no special forms like "how to define a function" or "how to write and if else". In Rye calling if or eihter (if/else) is no different than calling any other function.
Not in Lisp. In Lisp IF, COND, ... are either special operators or macros which expand to more primitive special operators. They are not functions.
(cond ((> x 1) (print 'larger) 1)
((= x 1) (print 'equal) 1)
(t (print 'smaller)))
COND is not a function. It is a macro. In a function call all arguments would be evaluated. But COND does not work that way.
COND has a list of clauses. During evaluation, the first clause is looked at. It's first subform then is evaluated, here (> x 1). If that is true, then the following subforms are evaluated left to right and the values of the last form is returned. If the first subform form was not evaluated to true, the evaluation goes to the next form and repeats the process on the subform.
* COND is not a function
* COND has a special syntax
* COND has a special evaluation rule
The same is the case for defining functions. In Lisp the operator to define a global function is called DEFUN. DEFUN is a macro, not a function. It has special syntax (for example the second element in a DEFUN form needs to be an unevaluated function name, which usually (I omit some detail) needs to be a symbol (which will not be evaluated)...
Again, DEFUN is not a function, it has special syntax and special semantics with side effects during compilation.
Yes, you are correct. I wasn't exact e nough about it, the end result syntax wise is similar, but there are macros involved in Lisps case.
I wrote multiple times right about this difference between Rebol-s and Lisp-s. The main difference being that Lisps evaluate lists by default and you have to quote them to not be evaluated and Rebols don't evaluate blocks by default and you have to "do" them to evaluate them. That's why Rebol's can have if/loop/fn as ordinary functions and Lisps use Macros for them.
If in rebol would be more like (if (> x 1) '(print 'larger)) I think.
Thanks for making this clear ... it was a nice read.
There is Lisps with so called f-expressions[0] which do not have special forms. That would be similar to the Rebol approach I think, I am a bit fuzzy on that.
The general consensus in the lisp community is that having a few special forms is worth it as it makes the compiler's job much easier. Basically it is a trap because yes it is much more elegant but practically it isn't worth the trouble, or at least some people see it that way. I also heard that Smalltalk is considered hard to compile for its lack of special forms.
But more complicated doesn't mean it is necessary impossible to still have a efficient compiler. It is definitely an interesting topic. Definitely would love to hear if you had any trouble on that front. If you already that far that you are thinking about optimization that is.
And your new languages looks amazing. Definitely going to check it out.
That's a reasonably common feature in hobby languages, at least for basic flow control. I've seen it a few times before. You could say TCL works like this too in the most horrible way possible.
REBOL-family languages (including Logo) don't eagerly evaluate expressions like a Lisp, and therefore can use ordinary functions/operators in places that would otherwise need to be special forms and/or macros.
Rye as Rebol (that it derives from) doesn't use parenthesis in general. In Rebol you can use them optionally for explicitly defining evaluation priority. But not in the same form as in Algol based languages:
print(inc(x))
But like Lisps. I've used them when I wanted to be very certain about evaluation, but not in general.
(print(inc x))
In Rebol (or Rye) this is usually just:
print inc x
That's why all function in Rebol/Rye have fixed arity and yes, you generally have to know it or deduce it from the code, which is a minus.
Rye currently doesn't have parenthesis option, but it might get it at the end. It does have op and pipe words, an optional left to right flow, which can also better hint about the structure than pure polish notation of Rebol I think. For better of worse, these Rye expressions all do the same :) --
print inc x
print x .inc
x .inc .print
inc x |print
Ha, I'm the opposite. Every time I'm writing python I have to stop and think "is it response.json or response.json()?" And then I think about how Ruby (I think nicely) solved the attribute/method decision problem.
Yes, and IDE that would know the arity of functions (which is not totally simple, because of the very dynamic nature of the language) would be able to display the "parenthesis" or the grouping of function calls. I plan to make sort of visual editor for it too as an experiment so that could be a first demo of it.
I hope we see this kind of exploration with Unison, which is stored as an AST in a database and not as text.
Of course you could just take existing text from a codebase and reformat it for viewing, but then there's this ambiguity about which version is real that you'd have to deal with.
In Unison it's understood that none of the text is real, it's only the resulting AST and its hash that matters, so if you're seeing text at all you know it's just for your benefit in that moment. It's such a cool idea.
Q for Rye's author: Since Rye is heavily inspired by Rebol, I wonder if you had a chance to take a look at Red [1] and what are your thoughts about it. Red looks really cool and capable, but it feels so niche/obscure and has such a small community that feels unpractical to use.
I was/am a Rebol developer, and all Rebol developers know about Red as it was/is the next of Re(d|bol) languages, after we came to terms that the Rebol 3 which was about to concretely improve on Rebol 2, and be open source just won't happen.
Red also improved on Rebol 2 a lot and is a proper Rebol successor. It was started by a very productive and prominent Rebol developer, that I greatly appreciate. The only problem I see with it is that maybe they were too ambitious. They started with their own low level language (compiler) Red/system, and out of that built Red interpreter. They are really doing things as they should be done I think, but it's taking quite a lot of time.
Red, like in a way Rebol has a lot of focus on GUI and I needed a language for backend development. I was waiting for their "IO branch" for years, it was hard for me to contribute in a concrete way, since their approach was quite low level and at around 2018 started making a simple Rebol like interpreter in Go, because Go is great on the backend and I just wanted something that works, hence the higher level language than C/C++, that's now Rye.
Red is still moving forward, their community is mostly on gitter I think. It is small, but so was Rebol's and it's much bigger than Rye's, which doesn't really have a community yet :).
btw, can you talk a bit more about how you came in touch with Rebol, what do you and other people use Rebol for, and if you are already using Rye for production apps?
Cool because I'd like to think if someone made a Netflix tech drama loosely based around Bell Labs in the early 80's, this would language would appear in that series. A language created by some Nordic computer scientist who angrily shakes his fist at the world because it doesn't get adopted due to it's weird syntax. Of course instead we get Awk.
A similar language is Joker (https://github.com/candid82/joker), Go based, Clojure syntax. I've been using it for years as a general purpose scripting language and Clojure code linter and formatter - it's exceptional.
It doesn't integrate non-Joker Go code as far as I know.
I don't often get excited when I see a new language, but this is really neat! It's not just another lisp or forth variant, but seems to be in a class of its own (if anything it reminds me of smalltalk, but claims to not be object oriented). I'm quite interested to see where this project goes!
There are few conventions with Rye language. Variations of functions use \ character. Like. print , print\csv or read , read\lines ... these are separate functions, with similar goal, but most of the time different arguments.
There is a sub-convention that word\ just means like word(more), which usually means one (most obvious) additional argument. function `ls` lists current context and `ls\` accepts string, in this case "prin" and list all arguments that match it.
Rye (similar to Rebol) relies on multiple types of words to replace syntax (if that makes sense) and these types of words are denoted by specific characters at the start or the end usually.
.word is and op-word and takes first argument from the left
|word is a pipe-word and is similar to op-word, but with different priority (more on that you can see on the website)
'word is lit-word (literal-word) ... quoted word in lisp terms (I suspect)
? at the end is a convention for "get" ... so noun? would mean get-noun ... so height? is convention for get-height. This is temporary "in testing" convention but so far it seems to function OK.
Hint: the "interactive" demos are scrollable by dragging the bottom. (Sadly, you don't have any access to the terminal window's scrollbar, so you can't just scroll to the end of the "video.")
I still think a non-animated transcript of a terminal session is better.
Maybe that my wording is off. This are not interactive demos, but more like demos of interactive use in console ... "animated interaction demos". These use asciinema, which is a nice tool and I think it's good to display interesting interactions compactly. But yes, for deeper look it moves too fast for one, so something what you describe could be better. I could have these animations for getting attention and then linking to transcripted, detailed document. Do you have any example of a good way of displaying such console session statically?
Rye is Go based, and Go has a great number of well done libraries. Integrating Go libraries into Rye by hand is very simple and I was able to add plenty of them, at least at proof of concept level just on my own.
Rye-front is also an experiment of how you can externally extend Rye, by adding Rye to your code/library. In this case the main focus is Go GUI library Fyne.
Now a colleague is writing a tool that auto-generates Fyne bindings and has already made great progress (Fyne has couple of 1000 functions/structs/... If we will be able to generalize this to any Go library, this will be really exciting.
I know about Rye package manager since last year. I've made a rye(lang) blogspot and github repository in 2020. I try to use term ryelang in general so there is a distinction. Otherwise, what can I do. I have no spare name and reason to rename right now, at the end, a name is just a name ...
Can’t wait for the “10 yeass of experience in Rye Lang [in 2026]” job posts from clueless recruiters