revo, the programming language

revo, the programming language

revo, the programming language docs | github revo is a dynamic language made for the joy of programming, a 1mb toolkit with a ton of focus on ergonomics. revo 编程语言文档 | GitHub revo 是一门为编程乐趣而生的动态语言,它是一个专注于人体工程学(易用性)、体积仅 1MB 的工具包。


Pipes (管道)

Clean data flow without nesting; things flow from top to bottom. 清晰的数据流,无需嵌套;数据从上到下流动。

"hello!!" 
|> string.upper 
|> string.sub(0, 4) 
|> fn(s) s + ", world!" 
|> inspect

# or with placeholders
"hello!!" 
|> _:upper() # obj:method() == obj.method(obj)
|> _:sub(0, 4)
|> do # you can even put any expression here
      # even do-end blocks
      _ + ", world!" 
   end 
|> print

Errors-as-values (错误即值)

Nil and booleans are replaced by atoms. You can’t use a value without handling an error. All crashes are explicit (WIP), aided massively by pattern matching, ?, orelse, and :unwrap(). Nil 和布尔值被原子(atoms)取代。如果不处理错误,你就无法使用该值。所有的崩溃都是显式的(开发中),并得到了模式匹配、?orelse:unwrap() 的极大辅助。

# f might be (:ok, "file-contents") or (:err, :IoError)
const f = fs.open({path = "./readme.md"}) 

# `?` unwraps :ok and panics on :err at top-level
const f2 = fs.open({path = "./readme.md"})? 

# crashes if :err
const f = fs.open({path = "./readme.md"}):unwrap()

Everything is an expression (一切皆表达式)

No statements, everything (really) always returns a value… but the code still looks procedural. 没有语句,一切(真的)总是返回一个值……但代码看起来仍然是过程式的。

let x = 10 # this line evaluates to 10
let label = if x > 0 "positive" else "zero"
let a = let b = 5 # this whole line evaluates to 5

fn is_true() 5 + 5 == 10 
# both x and is_true are the same function

const x = fn is_true() do # do-end is one too
    # return and break are special
    return 5 + 5 == 10 
end

Comp (编译时执行)

Execute any (really) expression at compile time. Any script can be compiled into bytecode and get any value baked in. 在编译时执行任何(真的)表达式。任何脚本都可以编译成字节码,并将任何值预先植入。

# asks for a line of input at build-time
# then keeps the result at run-time
const x = comp read() 

const long = do 
    let t = 0 
    for x in 0..100 t += x 
    t # similar to rust's {}, revo do-end blocks return the last value
end

Procedural Macros (过程宏)

Along with an AST-substituting macro system, this lets you just get an iterator over the raw AST tokens, run any code to transform them, then return back a table of the new AST. 除了 AST 替换宏系统外,这还允许你获取原始 AST 标记的迭代器,运行任何代码来转换它们,然后返回一个新的 AST 表。

# > num, num, num -> Sigma^4_n=1(a * b + c)
proc cmul!(iter) do 
    let a = 10 + (iter:next_of(:number))
    let b = iter:next_of(:number)
    let c = iter:next_of(:number)
    let acc = 0 
    for i in 1..5 do acc += a * b + c end 
    {(:number, acc)} 
end

Pattern Matching (模式匹配)

Destructure and branch in place. You will be using atoms and tuples; they are beautiful solutions to their problems. 原地解构和分支。你将使用原子和元组;它们是解决各自问题的优雅方案。

const response = match "hello!" 
    | "hello!" => "hi!" 
    | x when (x:len() > 10) => "" 
    | x when string?(x) => x + " to you too!" 
    | _ => ":("

Fibers (纤程)

I made all your blocking code become non-blocking by just adding a spawn before it. 我通过在阻塞代码前添加 spawn,使你所有的阻塞代码都变成了非阻塞代码。

fn serve(peer, message) do peer:send(message)? end

while :true do 
    # accept the next connection; if none is ready, this fiber parks
    let conn = server:accept()? 
    # the only thing you have to do to make it async is to add `spawn` here!
    spawn serve(conn, port - 1) 
end

Tables (表)

Represent everything: used for module exports, arrays, and maps. 代表一切:用于模块导出、数组和映射。

let t = {1, 2, 3, key = "value"}
let rec = {name = "revo", version = 1}
rec.name 
t[0]

Convenient Typing (便捷的类型系统)

The type system is optional, but very well-integrated. Untyped code works just fine, but typed code is faster and gets optimized better (and ensures code correctness at compile-time!). 类型系统是可选的,但集成得非常好。无类型代码运行良好,但有类型代码运行更快且优化更好(并确保编译时的代码正确性!)。

type Result = (:ok, any) | (:err, atom)

struct User { 
    name: string = "me", 
    age: int = 21, 
    fn get_age(self) -> Result (:ok, self.age), 
}

# type is inferred
let user = User{} 
print(user:get_age())