Myślałem o używaniu Haskella do serwera gry, ale kiedy zacząłem kodować, znalazłem się w części, w której parsuję pakiety myśląc "Wow, to spowoduje wiele dopasowań wzorców" . Widząc liczbę meczów do wykonania jest wielu (idź tam, zaatakuj, zdobądź łup, otwórz i tak dalej).Skutecznie dopasowuję wiele wzorów w Haskell
Co mogę zrobić, to:
- Odbierz paczkę
- Przetwarza nagłówek pakietu w systemie szesnastkowym String (powiedzmy "02B5" na przykład)
- Get resztę danych z pakietu
- Dopasuj nagłówek w parseIO
- Wywołanie odpowiedniej funkcji z zawartością pakietu
Łatwo byłoby odwzorować ciąg -> metoda, ale metody mają różną ilość parametrów.
Pomyślałem o prostych dwóch sposobach dopasowywania wzorów pokazanych poniżej.
#1
packetIO :: String -> IO()
packetIO packet =
case packet of
"02B5" -> function1
"ADD5" -> function2
... and so on
#2
packetIO :: String -> IO()
packetIO "02B5" = function1
packetIO "ADD5" = function2
... and so on
Zarówno patrząc na wydajność i styl kodowania, istnieje sposób, aby lepiej obsługiwać pakiety otrzymane od klienta?
Jeśli masz jakieś zasoby lub linki, których nie udało mi się znaleźć, proszę wskazać mi kierunek!
EDIT 130521:
Wygląda obu alternatywnych, wymienionych poniżej, są dobrym wyborem. Tylko czekam na odpowiedź na moje pytania w komentarzach przed wyborem, które było dla mnie najlepszym rozwiązaniem.
- Przechowywanie (ByteString -> Function) w strukturze mapy. O (log n)
- Konwersja ByteString na Word16 i dopasowanie do wzorca. O (log n) przez drzewa lub O (1) za pomocą tabel przeglądowych
EDIT 130521:
postanowiliśmy pójść na wzór pasujący z Word16 jak Philip JF powiedział. Oba są świetne alternatywy i gdy moje przypuszczenie jest zarówno to równie szybko, mapa może być szybciej, gdyż ja nie trzeba konwertować do Word16, druga opcja dała kod bardziej czytelnym dla mojego użytku:
packetIO 0x02B5 = function1
packetIO 0xADD5 = function2
etc
Brzmi bardziej jak zadanie dla 'mapy' (z' Data.Map', z ['containers'] (http://hackage.haskell.org/package/containers)) , z 'ByteString' (naprawdę nie lubię' String';)) jako typu klucza i ** typ funkcji handler'a jako typ wartości **. Jeśli masz małe pakiety o stałej długości, to typ z 'Data.Word' (jak' Word16') będzie wystarczający jako klucz. W takim przypadku możesz nawet użyć 'Data.IntMap' dla jeszcze lepszej wydajności. –
@Rhymoid: Czy mógłbyś zmienić to w odpowiedź, abym mógł go przyjąć? –
@Rhymoid: Otrzymane dane rzeczywiście są ByteString na początku. Ale czy mapowanie nie dałoby mi złożoności czasu O (log n), gdy wybory z tablicami wyszukiwania dostarczały O (1)? A jak będą reprezentowane klucze ByteString? Używanie "pakietu" ze wszystkimi wariantami podczas ładowania? – Plankt