I used to think that flexible language is just that. Flexible, which I liked for certain jobs. But it is also unpredictable, maybe eventually too dynamic for its own good. And my experience confirmed that. REBOL was VERY flexible, but I could also change things I didn’t want in places I didn’t predict or think through all the way.
So when I returned after many years back to Python (and Java for mobile), I felt a sense of relief, that I’m back in a more boring, but safer world.
I returned to Rebol again after a couple of years, Python at the time forced me to think too imperatively. I then coded REBOL with more reserve (I avoided runtime code manipulation), created the validation and SQL dialects, some tools to prevent my local variables from “escaping”, etc …
Over the years I started seeing the difference. There is the language and there is the environment that language lives in and manipulates.
With Rye I try to increase language flexibility. I believe programming languages are nowhere as flexible as the languages we are all already used to, programmers or not. Imagine we would communicate just with nouns and verbs, no tenses, counts, …
But I also try to limit how you can modify the environment.
Rye imposes the folowing to make the changes you make more limited, explicit and visible:
Let’s see some examples.
Rye values on their own are immutable. I remember of using list.append(1)
in Python a lot. append
was a common function in Rebol too. I was
never really sure if I am changing the original list/block or the returnd value will have the item appended. In Rye we use +
or concat
to return a new block with a new element.
family = [ "Anne", "Bob" ]
family.append("Joey")
for p in family { print p }
In Rye we would do:
family: { "Anne" "Bob" }
family:: family .concat "Joey" ; or> family:: family + { "Joey" }
for family { .print }
If you need them, for performance reason, Rye has the option to change a block in place. You have to ref a block and the function that does it has a “!” on end. You can use this if you have a concrete reason, but you wouldn’t just be using this as default way to code. And in most cases you don’t need it.
family: ref { "Anne" "Bob" }
"Joey" .append! family
for family { .print }
Q Why is the order of arguments reversed? The active value is usually a first argument in Rye, so it can be passed down the pipe from previous operation