プログラムを書いてどんな感じか試してみた
仕様に特に悩まないものでかつ色んな機能を使えるもの=状態管理!
そういえばScalaの練習も状態管理だったなぁ〜
ということで、書いてみた(感想は後ほど)
実際には全体を3回ほど見直して記述を試してみた結果の最後の形(色々試すのに飽きたの意味)
sealed class Node<T>(val name: String) { class ActionNode<T>(name: String , val action: (T) -> Unit) : Node<T>(name) class StateNode<T>(name: String) : Node<T>(name) } data class NodeLink<T>(val fromNode: Node<T> , val toNode: Node<T> , val check : (T?) -> Boolean) data class Flow<T>(val getState : (T) -> String , val setState : (T,String) -> T , val nodes : Map<String,Node<T>> , val links : Map<String,Map<String,NodeLink<T>>> ) fun <T> Flow<T>.plus(node : Node<T>) : Flow<T> { return this.copy(nodes = this.nodes + Pair(node.name , node)) } fun <T> Flow<T>.link(from: String, toName: String, check: (T?) -> Boolean) : Flow<T>? { val fromNode = nodes.get(from) ?: return null val toNode = nodes.get(toName) ?: return null return link(fromNode, toNode, check); } fun <T> Flow<T>.link(fromNode: Node<T>, toNode: Node<T>, check: (T?) -> Boolean) : Flow<T> { val nodeLink = NodeLink<T>(fromNode,toNode,check) val child = links.get(fromNode.name) ?: mutableMapOf<String,NodeLink<T>>() val newChild = child + Pair(toNode.name , nodeLink) val newLinks = this.links + Pair(fromNode.name , newChild) return this.copy(links = newLinks) } class ToNextStatusException(message: String?) : Exception(message) class FlowExecutor<T> (val flow: Flow<T>) { init { // 本当はflowのチェック入れたかった } fun toNextStatus(data : T) : T { val current = flow.getState(data) val currentNode = flow.nodes.get(current) ?: throw ToNextStatusException("status name not found") return walkNode(data, currentNode); } protected fun checkNode(data: T , toNode : Node<T>) :T = when (toNode) { is Node.ActionNode<T> -> { toNode.action(data) walkNode(data,toNode) } is Node.StateNode<T> -> flow.setState(data , toNode.name) } protected fun walkNode(data: T, currentNode : Node<T>) : T { val nexts = flow.links.get(currentNode.name) ?: throw ToNextStatusException("status name not found") val nextNodes = nexts.values.filter { it.check(data) } return when (nextNodes.size) { 0 -> throw ToNextStatusException("zero match") 1 -> checkNode(data , nextNodes.first().toNode) else -> throw ToNextStatusException("many match") } } }
判ったこと