[][src]Macro rosy::def_method

macro_rules! def_method {
    (
        $class:expr,
        $name:expr,
        |
                $this:ident $(: $this_ty:ty)?
            $(, $args:ident $(: $args_ty:ty)?)*
            $(,)?
        |
        $body:expr
    ) => { ... };
}

Defines a method on a Class instance in a simple manner.

This is purely a convenience wrapper for def_method that makes the process much less painful and tedious.

Examples

This macro skips all of the necessary type shenanigans when calling the method on Class. The focus is instead placed where it should be: on the method's definition.

This code runs with edition 2018
use rosy::prelude::*;

let class = Class::of::<String>();

rosy::def_method!(class, "blank?", |this: String| {
    this.is_whitespace()
}).unwrap();

let string = String::from(" \n\r\t");
let output = unsafe { string.call("blank?") };

assert!(output.is_true());

All argument counts supported by def_method work here as well:

This code runs with edition 2018
use rosy::prelude::*;

let class = Class::object();

rosy::def_method!(class, "eql_either?", |snap, crackle, pop| {
    snap == crackle || snap == pop
}).unwrap();

let object = AnyObject::from("snap");
let output = unsafe {
    object.call_with("eql_either?", &[AnyObject::nil(), object])
};

assert!(output.is_true());

The same types supported in def_method are supported here via explicit type annotations:

This code runs with edition 2018
use rosy::prelude::*;

let class = Class::of::<Array>();

rosy::def_method!(class, "plus_args", |this: Array, args: Array| {
    this.plus(args)
}).unwrap();

let expected: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
let array: Array<Integer> = (0..4).collect();

let args = [Integer::from(4), Integer::from(5), Integer::from(6)];
let value = unsafe { array.call_with("plus_args", &args) };

assert_eq!(value.to_array().unwrap(), *expected);