From 549ef6bf7ff18df0752d51d7c71ed90842f9c7b3 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 27 Jun 2020 17:34:39 +0800 Subject: [PATCH] Add oop.rhai script. --- doc/src/about/features.md | 2 +- doc/src/about/non-design.md | 3 +- doc/src/language/object-maps-oop.md | 2 +- doc/src/language/object-maps.md | 1 + doc/src/start/examples/scripts.md | 1 + scripts/oop.rhai | 45 +++++++++++++++++++++++++++++ src/packages/map_basic.rs | 11 +++++++ 7 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 scripts/oop.rhai diff --git a/doc/src/about/features.md b/doc/src/about/features.md index c5292a42..75df3def 100644 --- a/doc/src/about/features.md +++ b/doc/src/about/features.md @@ -37,7 +37,7 @@ Dynamic * Dynamic dispatch via [function pointers]. -* Some support for [OOP]. +* Some support for [object-oriented programming (OOP)][OOP]. Safe ---- diff --git a/doc/src/about/non-design.md b/doc/src/about/non-design.md index f93bb9ec..da3747df 100644 --- a/doc/src/about/non-design.md +++ b/doc/src/about/non-design.md @@ -13,7 +13,8 @@ It doesn't attempt to be a new language. For example: * No structures/records - define your types in Rust instead; Rhai can seamlessly work with _any Rust type_. There is, however, a built-in [object map] type which is adequate for most uses. - It is possible to simulate [OOP] by storing [function pointers] in [object map] properties, turning them into _methods_. + It is possible to simulate [object-oriented programming (OOP)][OOP] by storing [function pointers] + in [object map] properties, turning them into _methods_. * No first-class functions - Code your functions in Rust instead, and register them with Rhai. diff --git a/doc/src/language/object-maps-oop.md b/doc/src/language/object-maps-oop.md index ae61ff9e..4727871b 100644 --- a/doc/src/language/object-maps-oop.md +++ b/doc/src/language/object-maps-oop.md @@ -3,7 +3,7 @@ Special Support for OOP via Object Maps {{#include ../links.md}} -[Object maps] can be used to simulate object-oriented programming ([OOP]) by storing data +[Object maps] can be used to simulate [object-oriented programming (OOP)][OOP] by storing data as properties and methods as properties holding [function pointers]. If an [object map]'s property holds a [function pointer], the property can simply be called like diff --git a/doc/src/language/object-maps.md b/doc/src/language/object-maps.md index 5cf6ae67..27220134 100644 --- a/doc/src/language/object-maps.md +++ b/doc/src/language/object-maps.md @@ -50,6 +50,7 @@ operate on object maps: | `remove` | property name | removes a certain property and returns it ([`()`] if the property does not exist) | | `+=` operator, `mixin` | second object map | mixes in all the properties of the second object map to the first (values of properties with the same names replace the existing values) | | `+` operator | first object map, second object map | merges the first object map with the second | +| `fill_with` | second object map | adds in all properties of the second object map that do not exist in the object map | | `keys` | _none_ | returns an [array] of all the property names (in random order), not available under [`no_index`] | | `values` | _none_ | returns an [array] of all the property values (in random order), not available under [`no_index`] | diff --git a/doc/src/start/examples/scripts.md b/doc/src/start/examples/scripts.md index a4c8584c..20836aef 100644 --- a/doc/src/start/examples/scripts.md +++ b/doc/src/start/examples/scripts.md @@ -20,6 +20,7 @@ There are also a number of examples scripts that showcase Rhai's features, all i | [`function_decl3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl3.rhai) | A [function] with many parameters | | [`if1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/if1.rhai) | [`if`](#if-statement) example | | [`loop.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/loop.rhai) | Count-down [`loop`](#infinite-loop) in Rhai, emulating a `do` .. `while` loop | +| [`oop.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/oop.rhai) | Simulate [object-oriented programming (OOP)][OOP] | | [`op1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op1.rhai) | Just simple addition | | [`op2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op2.rhai) | Simple addition and multiplication | | [`op3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op3.rhai) | Change evaluation order with parenthesis | diff --git a/scripts/oop.rhai b/scripts/oop.rhai new file mode 100644 index 00000000..fe03b636 --- /dev/null +++ b/scripts/oop.rhai @@ -0,0 +1,45 @@ +// This script simulates object-oriented programming (OOP) techniques +// using function pointers (Fn) and object maps. + +// Define object +let obj1 = #{ + _data: 42, // data field + get_data: Fn("getData"), // property getter + action: Fn("action"), // method + update: Fn("update1") // property setter +}; + +fn getData() { + this._data +} +fn action() { + print("Data=" + this._data); +} +fn update1(x) { + this._data = x; + this.action(); +} + +if obj1.get_data() > 0 { // property access + obj1.update(123); // call method +} else { + print("we have a problem here"); +} + +// Define another object based on the first object +let obj2 = #{ + _data: 0, // data field - new value + update: Fn("update2") // property setter - another function +}; +obj2.fill_with(obj1); // add all other fields from obj1 + +fn update2(x) { + this._data = x * 2; + this.action(); +} + +if obj2.get_data() > 0 { // property access + obj2.update(0); // call method +} else { + obj2.update(42); // call method +} diff --git a/src/packages/map_basic.rs b/src/packages/map_basic.rs index 1488e655..a86e4665 100644 --- a/src/packages/map_basic.rs +++ b/src/packages/map_basic.rs @@ -39,6 +39,17 @@ def_package!(crate:BasicMapPackage:"Basic object map utilities.", lib, { Ok(()) }, ); + lib.set_fn_2_mut( + "fill_with", + |map1: &mut Map, map2: Map| { + map2.into_iter().for_each(|(key, value)| { + if !map1.contains_key(key.as_str()) { + map1.insert(key, value); + } + }); + Ok(()) + }, + ); lib.set_fn_2_mut( "+=", |map1: &mut Map, map2: Map| {