rusted

Rust like enum, Result and Option for javascript

Usage no npm install needed!

<script type="module">
  import rusted from 'https://cdn.skypack.dev/rusted';
</script>

README

npm version Coverage Status Build Status dependencies Code Climate

rusted

Rust's syntax features for javascript.

These features will help our functional programming.

Feature

  • enum
    • type checking
  • struct
    • type checking
    • mutable property
    • tuple struct
    • unit struct
  • impl
    • static method (associated function)
  • trait
  • iter
  • type alias
  • panic (not a macro)
  • match
  • Result
  • Option

Install

npm install --save rusted

Example

These examples require es6 transpiler like Babel.

enum

import {Enum} from 'rusted';

//enum Message {
//	Quit,
//	ChangeColor(i32,i32,i32),
//	Move {x:i32, y:i32},
//	Write(String)
//}
let Message=Enum({
    Quit:null, // no data
    ChangeColor:Array, // accepts if data.constructor==Array
    Move:'object', // accepts if typeof data=='object'
    Write:'string' // accepts if typeof data=='string'
});

// with data
let x=Message.Move({x:3,y:4}); // let x: Message = Message::Move { x: 3, y: 4 };
// without data
let y=Message.Quit; // let y: Message = Message::Quit;

struct

struct and enum checks type of property when instantiate.

  • 'any'
    • accepts any type
  • 'number','string','object'... (String)
    • compared to typeof value_of_prop
  • Object,Array,Number... (Constructor)
    • compared to value_of_prop.constructor
import {struct} from 'rusted';

let Position=struct({
    x:'number', // accepts if typeof x=="number"
    y:'number'  // accepts if typeof y=="number"
});

let Player=struct({
    name:'string', // accepts if typeof name=="string"
    position:Position, // accepts if position.constructor==Position
    items:Array, // accepts if items.constructor==Array
    memory:'any' // accepts any type
});

let player=Player({
    name:'foo',
    position:Position({
        x:0,y:0
    }),
    items:[],
    memory:{}
});

console.log(player.position.x); // > 0

impl

import {Enum,struct,match,impl} from 'rusted';

// For struct
let SomeStruct=struct({
    x:'number',y:'number'
});

impl(SomeStruct,{
    // You can define associated function (static method) by starting method name with "quot;.
    $new(x,y){
        return SomeStruct({x,y});
    },
    print(self){
        console.log(`(${x},${y})`);
    }
});

let some_struct=SomeStruct.new(2,3); // You don't need to attach "quot; at first. "quot; was removed at attaching proccess
some_struct.print(); // > (2,3)

// For enum
let SomeEnum=Enum({
    Foo:null,
    Bar:'number'
});

impl(SomeEnum,{
    unwrap(self){
        return match(self,{
            Foo:()=>'Foo!',
            Bar:x=>`Bar,${x}!`
        });
    }
});

let x=SomeEnum.Foo,y=SomeEnum.Bar(7);
console.log(x.unwrap()); // > Foo!
console.log(y.unwrap()); // > Bar,7!

// For ordinary constructor (javascript class)
let SomeConstructor=function(){
    this.name='foo';
};

impl(SomeConstructor,{
    create(){
        return new SomeConstructor();
    },
    greet(self){
        console.log(`Hello, ${self.name} !`);
    }
});

let some_constructor=SomeConstructor.create();
some_constructor.greet(); // > Hello, foo !

trait

import {struct,trait,impl} from 'rusted';

let Foo=struct({
    name:'string'
});

let BarTrait=trait({
    print(self){}, // empty body, need to implement on `impl`
    hello(self){ // has contents, not need to implement on `impl`
        console.log('hello');
    }
});

impl(BarTrait,Foo,{
    print(self){
        console.log(self.name);
    }
});
/* This would be error
impl(BarTrait,Foo,{});
*/

let foo=Foo({name:'Taro'});
foo.print(); // > Taro
foo.hello(); // > hello

Option

import {Some,None,match} from 'rusted';

let divide=(numerator,denominator)=>{
    return denominator==0
        ? None // represents there are no data
        : Some(numerator/denominator);
};

let result = divide(2.0, 3.0);

match(result,{
    Some:x=>console.log(`Result: ${x}`),
    None:()=>console.log('Cannot divide by 0')
});
// > Result: 0.666...

Result

import {Ok,Err,match} from 'rusted';

function Foo(x){
    if(x>5){
        return Ok(x);
    }else{
        return Err('Less than 5 !');
    }
}

console.log(match(Foo(3),{
    Ok:x=>x,
    Err:e=>e
}));
// > Less than 5 !

console.log(Foo(10).unwrap()); // > 10
console.log(Foo(3).unwrap()); // throws error

(es5 version.)

var rusted=require('rusted'),
    Ok=rusted.Ok,
    Err=rusted.Err,
    match=rusted.match;

function Foo(x){
    if(x>5){
        return Ok(x);
    }else{
        return Err('Less than 5 !');
    }
}

console.log(match(Foo(3),{
    Ok:function(x){
        return x;
    },
    Err:function(e){
        return e;
    }
}));

console.log(Foo(10).unwrap());
console.log(Foo(3).unwrap());

License

MIT