(a little)
MVCoconut
(more)
Tinkerbell
tink_core
- Future
- Promise
- Signal
- etc.
(this one we already know)
tink_state
Observable state primitives
- Observable
- State
- Observable.auto
- ObservableArray, ObservableMap
tink_state: Observable
abstract Observable<T> {
// readable value
var value(get, never):T;
// a way to bind/unbind value change callbacks
function bind(handler:Callback<T>):CallbackLink;
// magic \o/ (more on this later)
static function auto<X>(f:()->X):Observable<X>;
}
tink_state: State
abstract State<T> to Observable<T> { // also is an Observable
// writable value
var value(get, set):T;
// created with initial value
function new(value:T):Void;
// also bindable
function bind(handler:Callback<T>):CallbackLink;
}
- Any state is also an observable, but not every observable is a state.
- One could also say that states are read-write versions of observables.
tink_state: Observable.auto
// Some observable state
var messages = new ObservableArray([
{isRead: new State(true)},
{isRead: new State(false)},
{isRead: new State(false)},
]);
// Observable from a "computation"
var unreadCount = Observable.auto(() -> {
var count = 0;
for (message in messages) {
if (!message.isRead.value) {
count++;
}
}
return count;
});
// Example
trace(unreadCount.value); // 2
messages.push({isRead: new State(false)});
messages.push({isRead: new State(false)});
messages[1].isRead.value = true;
trace(unreadCount.value); // 3
(no macros involved, just smart invalidation management)
tink_state: performance
- State wraps values in small objects
- Reading values:
- Simple State: just a field read
- Computable Observable (e.g. Observable.auto): cached computations
- Changing values simply sets observable to the "invalid" state and notifies subscribers.
- Bindings are delayed and batched
tink_state: goodies
- ObservableArray
- ObservableMap
- Promised (Loading/Done/Failed)
- Comparators
- Guards
- Composition
- Transformation
- Debugging tools
coconut.data
- Observable models, based on tink_state
- Ergonomics for common use cases
- Statically enforced observability
coconut.data
Macro-built model classes
class Player implements Model {
@:constant var id:Int;
@:editable var name:String;
}
class Player implements Model {
@:isVar public var id(get, never):Int;
public var name(get, set):String;
public final observables:{id:Observable<Int>, name:State<String>};
final __coco_name:State<String>;
public function new(__coco_init:{name:String, id:Int}) {
this.id = __coco_init.id;
this.__coco_name = new State(__coco_init.name);
}
inline function get_id() {
return this.id;
}
inline function get_name() {
return this.__coco_name.value;
}
function set_name(param:String) {
this.__coco_name.set(param);
return param;
}
}
source
output (simplified)
coconut.ui
- Reactive UIs for coconut.data models
- Similar ideas to React (and friends)
- tink_state powered invalidation
- JSX-style markup DSL via tink_hxx
- Pluggable renderers, cross-platform
class Totals extends View {
@:attribute var count:Int;
function render() '
<TextField text=${"You have " + count + " resources"}/>
';
}
coconut.ui: features
- attributes
- states
- children
- references
- life cycle callbacks
- implicit attributes
- lazyness
- batching
tink and coconut
By Dan Korostelev
tink and coconut
- 1,043