bmaxa
Buduća legenda
- Poruka
- 42.102
Verovatno ste culi za multhimethods, double dispatch ili visitor pattern?
Radi se o tome da virtualne funkcije metodi, dispatchuju samo na jednom
objektu u skoro svim jezicima. ova dva gorepomenuta patterna simulira
multiple dispatch u takvim jezicima kao sto su Java, C++, C#...
Dakle, nim podrzava dispatch vituelnih funkcija nad vise tipova
objekata, zato mi je interesantan
Evo primera, koji sam ranije navodio, pancake sort u nimu
primeticete da make/unmake move dispatchuju po 3 objekta.
U klasicnim OO jezicima bi morao da se uradi dynamic cast
u zeljeni tip, a dispatch bi isao samo na prvom parametru...
Radi se o tome da virtualne funkcije metodi, dispatchuju samo na jednom
objektu u skoro svim jezicima. ova dva gorepomenuta patterna simulira
multiple dispatch u takvim jezicima kao sto su Java, C++, C#...
Dakle, nim podrzava dispatch vituelnih funkcija nad vise tipova
objekata, zato mi je interesantan

Evo primera, koji sam ranije navodio, pancake sort u nimu

Kod:
import strutils,algorithm
type
State = ref object of RootObj
Move = ref object of RootObj
Domain = ref object of RootObj
Search = object
solution: seq[State]
treshold: int
verbose: bool
# state methods
method `$`(s:State):string {.base.} =
"default State"
method copyState(s:State):State {.base.}=
echo "default copyState"
# Domain methods
method makeTestState(d:Domain):State {.base.}=
echo "default makeTestState"
method heuristic(d:Domain,s:State):int {.base.}=
echo "default heuristic"
method bf(d:Domain,s:State):int {.base.} =
echo "default bf"
method getMove(d:Domain,m:int):Move {.base.} =
echo "default getMove"
method makeMove(d:Domain,s:State,m:Move) {.base.} =
echo "default makeMove"
method unmakeMove(d:Domain,s:State,m:Move) {.base.} =
echo "default unmakeMove"
# Search procs
proc df(search:var Search,domain:Domain,state:State,depth:int):bool =
if depth == 0 : echo "Treshold ",search.treshold
if domain.heuristic(state) == 0 :
search.solution[depth] = state.copyState
return true
if depth == search.treshold: return false
if search.verbose : echo "".indent(4*depth," "),state
for i in 0..<domain.bf(state) :
let move = domain.getMove(i)
domain.makeMove(state,move)
if search.df(domain,state,depth+1) :
domain.unmakeMove(state,move)
search.solution[depth]=state.copyState
return true
domain.unmakeMove(state,move)
false
proc id(search:var Search,domain:Domain,start:State) =
search.treshold=0
while true:
search.solution = newSeq[State](search.treshold+1)
if search.df(domain,start,0): break
search.treshold+=1
for i in search.solution :
echo i
#concrete implementations
type
PancakeState = ref object of State
state: seq[int]
PancakeMove = ref object of Move
i: int
Pancake = ref object of Domain
#PancakeState methods
method `$`(s:PancakeState):string =
result = "["
var first = true
for i in s.state :
if not first : result &= " "
result &= $i
first = false
result &= "]"
method copyState(s:PancakeState):State =
var state : PancakeState
new(state)
state.state = s.state
result = state
#Pancake methods
method makeTestState(p:Pancake):State =
var state:PancakeState
new(state)
state.state = @[0, 5, 4, 7, 2, 6, 1, 3]
result = state
method heuristic(p:Pancake,ps:PancakeState):int =
result = 0
for i in 1..<ps.state.len :
if abs(ps.state[i]-ps.state[i-1])>1 :
result+=1
if ps.state[0] != 0 : result+=1
method bf(p:Pancake,ps:PancakeState):int =
result = ps.state.len-1
method getMove(p:Pancake,i:int):Move =
var move : PancakeMove
new (move)
move.i = i+2
result = move
method makeMove(p:Pancake,ps:PancakeState,pm:PancakeMove)=
reverse(ps.state,0,pm.i-1)
method unmakeMove(p:Pancake,s:PancakeState,m:PancakeMove)=
makeMove(p,s,m)
#main code
let domain = new(Pancake)
var search = Search()
echo domain.makeTestState()
search.verbose = false
let s = domain.makeTestState()
search.id(domain,s)
U klasicnim OO jezicima bi morao da se uradi dynamic cast
u zeljeni tip, a dispatch bi isao samo na prvom parametru...