Sunday 1 May 2022

bardzo zła przygoda

Cześć pracy!



Klepię kod, wyniki działania którego mają ambicję symulować zachowanie się pewnego układu fizycznego. Suspens - jeszcze nie powiem, jakiego. (На встречу с Борманом Штирлиц вышел в буденовке, напевая песню о Москве. - Вы бы хоть конспирацию-то соблюдали, - проворчал Борман. Штирлиц согласился и надел темные очки.)

Żeby napiąć zwiotczałe muskuły, stwierdziłem, że wyklepię to w C++, bo słabo znam, bo fajny - tak dużo klamer, dwukropków (to dziedziczne) i średników i nawiasów i strzałeczek i gwiazdek i ampersandów. A jak się namespace doda, to prawie jak C#, ale nie tak amatorsko, tylko zawodowo.

Więc tak: mam funkcję Run, która bierze jakieś parametry, ale symulacja zależy od "zewnętrznej" funkcji; wyjściem rzyga w terminal - można w plik rzecz jasna. (Jak łatwo zgadnąć po tej potrzebie funkcji danej z zewnątrz - coś w rodzaju zagadnienia sterowania, że tak uchylę rąbka. W środku "rozwiązywane" jest równanie różniczkowe II rzędu, jak to w mechanice.) Znakiem tego - trzeba przekazać wskaźnik do funkcji. Jak tylko przebiłem się przez te czytelne i przyjazne deklaracje itp., bo z typedef nie byłem za pan brat, wszystko szło naprawdę nieźle w fazie pre-testów, kiedy argumenty Run modyfikowałem ręcznie w kodzie w main(), kompilując na nowo przed każdym uruchomieniem i nakarmieniem gnuplota danymi z wyjścia. Zestaw tych wrzucanych funkcji miałem nad main i wszystko było super.

Ale nadejszła zatem ta epokowa chwila, gdy rzecz dojrzała do uporządkowania i w szczególności dania możliwości, żeby ostateczny wyrób (a.out się nazywa, bo niczego w Makefile nie dałem z "-o ...") uruchamiać automatycznie, np. z pytona - niech będzie na wieki wieków przeklęty, a wyznawcom niech żona puszcza się na prawo i lewo, a następnie w żałobie i wstydzie obetnie włosy, do trzech pokoleń wstecz i naprzód. Dodanie argumentów wywołania - konwertowanych na liczby - to nie problem, akurat chodzi o trzy rzeczywiste parametry. Ale jak w argumencie przekazać funkcję, a konkretnie wskaźnik do niej? Do głowy przyszedł mi banalny sposób: klasa, chowająca w sobie nazwę, funkcję wirtualną i rzecz*, która zwraca wskaźnik do tej funkcji - po redefinicji w klasach dziedziczących (bo dwukropek to mój fetysz, bo oszczędza kod, bo to, bo tamto.). Plus rzecz jasna wyszukiwania po nazwach, a nazwę da się prosto dostarczyć jako argument.

No i xuj, zakodowałem co trzeba i nixuja nie działa! Czytałem internaty parę godzin, coraz mniej rozumiejąc, aż wreszcie okazało się, że kompilator pod IntelliSense daje inne błędy niż g++. Czytałem dalej, dalej niewiele rozumiałem, a cut&paste coding to moja specjalność. I po trafieniu na toto: <https://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible> uznałem, że składam broń.

Są dwa wyjścia: std::function zdaje się zachowywać dobrze, ale rzekomo ma narzut zw. z wywoływaniem i gdyby wywołań było kilka, nie przejmowałbym się. Ale jest raczej dziesiątki tysięcy w każdym uruchomieniu, a uruchomień może być dziesiątki. A drugie - chyba włożenie Run do tej klasy bazowej! Że też wcześniej na to nie wpadłem.

Niemniej - poczucie, jest aż tak pod górkę w sytuacji, gdy wymyślenie całości zajmuje pół minuty, wpisanie tego w C# zajęłoby z 10 minut, a w pytonie (niech skiśnie, dziad!) pewnie pół godziny. Choć gadają uczeni w piśmie, że delegaty w C# wolne są. Nie wiem, nie robię numeryki w C#, choć pewnie można. Ale bardzo spodobał mi się styl stosowany w faq na isocpp, miodzio, jak to mawiano dawno temu. I jakże seksownie napisane - Garamond chyba.

No i o. A ile filmów powstanie i obrazów. Wywiady, autografy...

"Taki był mój dzień na przepustce" - ZCDCP, "Pirackie stacje telewizyjne" iks de.


* nie używam słowa "metoda".

No comments:

Post a Comment