[HN Gopher] Rye: Homoiconic dynamic programming language with so...
       ___________________________________________________________________
        
       Rye: Homoiconic dynamic programming language with some new ideas
        
       Author : nnx
       Score  : 96 points
       Date   : 2024-03-21 04:25 UTC (2 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | gumby wrote:
       | > Rye is homoiconic, it has no keywords or special forms
       | (everything is a function call, everything is a value)
       | 
       | How does it implement _and_ , _or_ , or _if_?
        
         | chabons wrote:
         | Presumably as functions, the same way as excel?
         | 
         | and(x, y) -> bool
         | 
         | or(x, y) -> bool
         | 
         | if(cond, funcTrue, funcFalse) -> void
        
           | adrianmsmith wrote:
           | Yeah I did notice in the examples                   fac: fn {
           | x } { either x = 1 { 1 } { x * fac x - 1 } }         ;
           | function that calculates factorial
           | 
           | So presumably "either" is the "if" expression.
        
             | anamexis wrote:
             | "if" is the "if" expression -
             | https://ryelang.org/meet_rye/basics/if_either/
        
         | samatman wrote:
         | This is possible with fexprs or equivalent constructs
         | https://en.wikipedia.org/wiki/Fexpr
         | 
         | It looks like that's how Rye does it as well, blocks can be
         | conditionally evaluated:
         | https://ryelang.org/meet_rye/basics/if_either/
         | 
         | "In REBOL, contrary to Lisps, blocks or lists don't evaluate by
         | default. For better or for worse, this little difference is
         | what makes REBOL - REBOL."
         | https://ryelang.org/meet_rye/basics/doing_blocks/
         | 
         | It's difficult for a language with this semantics to be made
         | efficient, but efficiency isn't everything.
        
           | fuzztester wrote:
           | >programming language based on ideas from Rebol, flavored by
           | Factor, Linux shell and Go
           | 
           | That makes it potential interesting to me.
        
           | _nalply wrote:
           | Why is it difficult?
        
             | samatman wrote:
             | Since code-is-data, you can put that exact if statement
             | into several functions.
             | 
             | Since code-is-data, you can swap the if and else clauses
             | around. This applies to all the functions where you've
             | inserted the if statement.
             | 
             | This kind of thing makes it difficult to compile a function
             | to a fast set of machine instructions with the same effect.
             | Not impossible, but difficult.
        
           | andrewflnr wrote:
           | I mean, it's possible in lambda calculus. Anything above that
           | is sugar, right?
        
             | gumby wrote:
             | Yes, but with supposedly no special forms there cannot be a
             | lambda operator.
             | 
             | Turns out the language does have special forms, which is
             | OK; it's just weird to say there aren't (though it's an
             | understandable goal).
             | 
             | When I worked on 3Lisp (so many decades ago) it became
             | clear to me how many special forms there are (a small
             | number, but more than I thought) and, honestly, how few
             | there really are, so the "benefit" of a 3Lisp turns out to
             | be negligible in practice. Oddly enough I didn't really
             | notice that when _writing_ interpreters because I thought
             | of most special forms as simply compiler hacks (
             | "eventually we can get rid of this").
        
           | gumby wrote:
           | I know well what a FEXPR is (I was a Maclisp maintainer) but
           | they are special forms.
           | 
           | It is interesting to imagine inverting the sense of
           | execution, but as you say it's hard to do much optimization.
        
           | sctb wrote:
           | This is how Joy and Factor work as well, so I'd say this is
           | standard fare for concatenative languages.
        
         | justinpombrio wrote:
         | This took me a minute to get, even after looking at the page
         | about _if_ :
         | 
         | https://ryelang.org/meet_rye/basics/if_either/
         | 
         | The tricky thing about _if_ , _and_ , and _or_ --- the reason
         | you can 't implement them as functions in most languages --- is
         | that they need to not evaluate all their arguments immediately.
         | Otherwise:                   // Would print!         if(false,
         | print("oops!"))              // Would throw  an error if the
         | key is not present         and(my_hashmap.has_key("key"),
         | my_hashmap["key"])
         | 
         | The way that ryelang gets around this is that you pass the
         | arguments in a "code block" surrounded by "{}", which delays
         | its evaluation. So you write:                   // Does not
         | print, because *if* never runs its code block arg         if 0
         | { print("oops!") }              // There's no example of *and*
         | anywhere but my guess is you'd write this:         and {
         | my_hashmap.has_key("key") } { my_hashmap["key"] }
        
           | nerdponx wrote:
           | The R language has this feature as well. It's a whole lot of
           | fun to work with.
        
         | middayc wrote:
         | Yes, as samatman said, main reason is that blocks of (code or
         | data there is no difference) don't evaluate so they are passed
         | as function arguments and the function can potentially evaluate
         | them. So _if_ is a function that accepts two arguments, a
         | boolean and a block of code.
         | 
         |  _loop_ is a function that also accepts two, integer for number
         | of loops and again a block of code.
         | 
         | Even _fn_ that creates functions is a function that accepts two
         | blocks, first is a list of arguments and second is a block of
         | code. There is no big difference between function _fn_ and
         | function _print_ , they are both builtin functions defined in
         | same manner and there are multiple _fn_ s for special cases and
         | you can create your own on "library" level.
        
       | warvariuc wrote:
       | The blog entry titled "Less variables, more flows example vs
       | Python" is strange. ( https://ryelang.blogspot.com/2021/11/less-
       | variables-more-flo... )
       | 
       | The Python version uses intermediate variables so the author of
       | the code is to blame for verbosity, not the language.
        
         | middayc wrote:
         | This was written in 2021, maybe it's really not that great of a
         | blogpost. I wrote a lot of blogposts from many angles back
         | then, mostly to myself as there weren't many readers, trying to
         | see the language from the outside, to self-motivate, etc ...
         | 
         | I think I wrote a script I needed in Rye and I found it
         | interesting, then I went to Fiver and paid someone to write a
         | script in Python that does the same.
         | 
         | 2021 were different times, and I hope I've grown a little
         | too... and now I would ask ChatGPT or Gemini :)
        
       | carterschonwald wrote:
       | The detail about input validation is a really nice one that
       | hopefully the next generation of programming languages all do
       | standard.
        
       | artemonster wrote:
       | familiar with rebol, but evaluation rules with op and pipe words
       | gave me headache. would like to know more about context oriented
       | programming, tutorial had nothing in the section, unfortunately
        
         | middayc wrote:
         | Yes, op and pipe words are the biggest or the most visual
         | addition to Rebol's base idea. Without them if you replace { }
         | with [ ] it's basically just Rebol ... well, with some
         | different details around contexts (rebol's bindology), no
         | refinements, mandatory spacing around tokens, different error
         | handling logic and some other details.
         | 
         | I am still learning to explain or even name things, but various
         | examples of using contexts in different ways are currently what
         | excites me the most. I will write "Meet Rye" further and
         | contexts are one of next subjects to be written about.
        
       | leke wrote:
       | I played around with Rebol many years ago and enjoyed it. This
       | too looks like fun.
        
       ___________________________________________________________________
       (page generated 2024-03-23 23:00 UTC)