-
1. Data: 2014-11-11 23:36:57
Temat: Makra higieniczne w jezyku Scheme
Od: g...@g...com
W kolejnym poscie zamieszczam czwarty rozdzial swojego wywodu
o makrach w Schemie.
Poruszam w nim temat makr higienicznych "syntax-rules", starajac sie
przy tym pokazac, jakie problemy rozwiazuja, a jakie tworza nowe.
Sympatycy ogonkow moga sobie sciagnac zaktualizowana wersje PDF stad:
https://bytebucket.org/panicz/slayer/raw/f62eab57112
287c619310e72de5c17d9dc44cb1e/doc/makra.pdf
-
2. Data: 2014-11-11 23:37:23
Temat: Re: Makra higieniczne w jezyku Scheme
Od: g...@g...com
* MAKRA OPARTE NA PRZEKSZTALCANIU WZORCOW (syntax-rules)
** PROBLEMY Z "define-macro"
W poprzednim rozdziale udalo sie uzyskac dosc zgrabna metodologie pisania
makr, ktore sa stosunkowo proste w analizie. Pewien problem dotyczyl
destrukturyzacji danych wejsciowych do makra -- uzywalismy do tego
funkcji zbudowanych w oparciu o funkcje car i cdr.
Innym problemem bylo to, ze moglismy niechcacy stworzyc makro, ktore
wprowadza jakas zmienna kolidujaca z istniejaca zmienna. Z tym problemem
jakos sobie poradzilismy, uzywajac funkcji gensym. Nalezy jednak zauwazyc,
ze nie rozwiazuje to wszystkich mozliwych problemow. Niekiedy makro moze
odnosic sie do jakichs zewnetrznych wiazan, ktore moglyby niechcacy
zostac przesloniete przez uzytkownika makra w kontekscie jego uzycia.
Na przyklad wartosc wyrazenia
: (let ((if list))
: (cond ((= 2 3) 'a)
: (else 'b)))
przy podanej wczesniej definicji makra "cond" moze okazac sie zaskakujaca:
nie bedzie to bowiem symbol a, tak jak moglibysmy sie spodziewac, tylko lista
(#f a (#t b)).
Moglibysmy zatem oczekiwac od naszego systemu makr, zeby zachowywaly
"przezroczystosc odniesieniowa", tzn. zeby uzywane w nich identyfikatory
odnosily sie do wartosci z kontekstu definicji makra, a nie z do wartosci
z kontekstu jego uzycia (chyba ze zazadamy tego explicite). Tylko bowiem
w taki sposob mozemy uwolnic uzytkownika makr od koniecznosci martwienia
sie jego szczegolami implementacyjnymi.
Kolejnym problemem, o ktorym nie wspominalismy, byl brak mozliwosci
tworzenia makr o ograniczonym zasiegu -- forma define-macro wprowadzala
nowe makro w biezacym zasiegu. Dla odmiany, mozemy z latwoscia definiowac
sobie pomocnicze funkcje wewnatrz innych funkcji. (Wprawdzie mozna
sobie zdefiniowac makro pomocnicze wewnatrz funkcji, jednak nie mozna
uzyc makra o ograniczonym zasiegu do utworzenia definicji w zasiegu
globalnym.)
** ROZWIAZANIE: MAKRA HIGIENICZNE "syntax-rules"
Standard R5RS jezyka Scheme definiuje trzy nowe podstawowe formy specjalne
sluzace do definiowania makr, mianowicie define-syntax, let-syntax
i letrec-syntax. W przeciwienstwie do define-macro, owe formy jako swoje
argumenty przyjmuja procedury (np. stworzone przy pomocy wyrazen lambda).
Specyfika tych procedur jest dosc skomplikowana i przyjrzymy sie jej blizej
dopiero w nastepnym rozdziale.
Tymczasem omowie pewna wtorna forme specjalna "syntax-rules", ktora
ulatwia tworzenie odpowiednich procedur. Postac owej formy jest nastepujaca:
: (syntax-rules (identyfikatory-specjalne ...)
: ((wzorzec przeksztalcenie)
: ...))
Formy "wzorzec" i "przeksztalcenie" wyrazone sa w specjalnym jezyku
wzorcow. Nie bedziemy zglebiac tego, w jaki sposob ow jezyk jest
implementowany. Osoby zainteresowane moga zajrzec do implementacji
stworzonej przez Abdulaziza Ghulouma i R. Kenta Dybviga w jezyku Scheme:
https://www.cs.indiana.edu/l/www/chezscheme/r6rs-lib
raries/
Forma "wzorzec" jest odpowiedzialna za destrukturyzacje i opisuje,
jakie jest zamierzone uzycie makra, natomiast forma "przeksztalcenie"
jest odpowiedzialna za restrukturyzacje formy w terminach bardziej
pierwotnych. Formy skladaja sie z dowolnie zagniezdzonych list
symboli oraz ewentualnie specjalnego symbolu "..." (elipsy).
Jezeli dane uzycie makra nie pasuje do danego wzorca, to procedura
wygenerowana przez "syntax-rules" probuje je dopasowac do kolejnego
wzorca, a jezeli zaden wzorzec nie pasuje do danego uzycia, procedura
zglasza blad skladni.
** NOWA DEFINICJA FORMY "let"
Zamiast szczegolowo wyjasniac jezyk wzorcow makra "syntax-rules",
najlepiej przedstawic kilka praktycznych przykladow. Zaczniemy
od redefinicji omowionego wczesniej makra "let". Nowa definicja,
wyrazona w termiach jezyka wzorcow, bedzie miala postac:
: (define-syntax let
: (syntax-rules ()
: ((let ((name value) ...) body + ...)
: ((lambda (name ...) body + ...) value ...))))
Warto zwrocic uwage na kilka rzeczy. Po pierwsze, nasza definicja
wyglada prawie dokladnie tak, jak wczesniejsza specyfikacja makra "let".
Glowna roznica jest taka, ze musimy owinac te specyfikacje w czarodziejskie
zaklecie. Poza tym w specyfikacji nasz wielokropek traktowalismy nieformalnie,
natomiast tutaj jest on uzyty jako literalny symbol o dobrze okreslonej
semantyce -- musi on wystapic za jakims identyfikatorem (albo dowolnie
zagniezdzona lista zawierajaca przynajmniej jeden zwykly identyfikator)
i oznacza zero lub wiecej wystapien danego elementu.
Ponadto, jezeli w formie "wzorzec" wielokropek wystepuje za jakims
identyfikatorem (byc moze zagniezdzonym w liscie), to ilekroc uzyjemy
tego identyfikatora w formie "przeksztalcenie", musimy za nim rowniez
dostawic wielokropek.
Kolejna uwaga dotyczy tego, ze w naszej definicji nazwa makra ("let")
pojawia sie dwa razy: jako pierwszy argument formy "define-syntax" oraz
jako pierwszy element formy "wzorzec".
Tak naprawde tylko pierwsze z tych uzyc ma realne znaczenie -- pierwszy
element formy "wzorzec" i tak jest ignorowany przez transformator, wiec
mozna by bylo w jego miejsce wstawic dowolny symbol. Uzycie jakiegokolwiek
symbolu innego niz nazwa makra mogloby byc mylace, ale powszechnie
stosowanym idiomem jest uzywanie w tej pozycji symbolu "_":
: (define-syntax let
: (syntax-rules ()
: ((_ ((name value) ...) body + ...)
: ((lambda (name ...) body + ...) value ...))))
Mozna tez zauwazyc, ze nasze makro jest stosunkowo proste -- wystepuje
w nim tylko jedna para (wzorzec przeksztalcenie), zas lista
identyfikatory-specjalne jest pusta.
Do definiowania takich przypadkow moglibysmy zdefiniowac makro pomocnicze:
: (define-syntax define-syntax-rule
: ((_ (name . args) transfomation)
: (define-syntax name
: (syntax-rules ()
: ((name . args)
: transformation)))))
Dzieki niemu nasza definicja przyjmie jeszcze prostsza postac:
: (define-syntax-rule (let ((name value) ...) body + ...)
: ((lambda (name ...) body + ...) value ...))
** NOWE DEFINICJE SPOJNIKOW LOGICZNYCH "and" i "or"
Definicja formy "and" bedzie raczej prosta:
: (define-syntax and
: (syntax-rules ()
: ((_ p)
: p)
: ((_ p q ...)
: (if p (and q ...) #f))))
Glowna roznica wzgledem poprzedniego makra jest taka, ze tym razem
w formie "syntax-rules" pojawiaja sie dwa przypadki. Odpowiada to
dwom przypadkom z formy "if" we wczesniejszym wariancie wyrazonym
przy pomocy define-macro.
Definicja formy "or" rowniez nie powinna nastreczac wiekszych trudnosci:
: (define-syntax or
: (syntax-rules ()
: ((_ p)
: p)
: ((_ p q ...)
: (let ((T p)) (if T T (or q ...))))))
Skorzystalismy tutaj z faktu, ze makra zachowuja higiene, i transformator
makr sam zadba o to, zeby uzyta przez nas nazwa zmiennej tymczasowej
nie kolidowala z zadna nazwa wystepujaca w kontekscie uzycia makra.
** NOWA DEFINICJA FORMY "cond"
: (define-syntax cond
: (syntax-rules (else)
: ((_ (else actions + ...))
: (begin actions + ...))
:
: ((_ (condition actions + ...))
: (if condition
: (begin actions + ...)))
:
: ((_ (condition actions + ...) other-clauses ...)
: (if condition
: (begin actions + ...)
: (cond other-clauses ...)))))
Powyzsza definicja jest wprawdzie nieco dluzsza od tej wyrazonej
przy pomocy define-macro, ale wydaje sie tez bardziej zrozumiala.
Pojawil sie w niej wreszcie identyfikator specjalny "else", co stwarza
okazje do wyjasnienia jego roli.
Gdyby slowo kluczowe "else" nie znajdowalo sie na liscie identyfikatorow
specjalnych, to dwa pierwsze wzorce w definicji makra bylyby nierozroznialne
-- dla jezyka wzorcow w ogolnosci nie ma znaczenia, czy wystepujacy
w nim symbol ma postac "condition", "else" czy jakakolwiek inna (za
wyjatkiem symbolu "...").
Umieszczenie slowka "else" na liscie identyfikatorow specjalnych sprawia,
ze pierwszy wzorzec zostanie dopasowany tylko wtedy, gdy w przetwarzanej
formie wystapi literalnie symbol "else".
** PROBA PONOWNEGO ZDEFINIOWANIA FORMY "while"
W pierwszej chwili moglibysmy chciec zdefiniowac nasze makro "while"
nastepujaco:
: (define-syntax-rule (while condition actions ...)
: (call/cc
: (lambda (break)
: (define (LOOP)
: (if condition
: (begin actions ... (LOOP))))
: (LOOP))))
Niestety, okazuje sie, ze oprocz tego, ze transformator makr ukrywa przed nami
identyfikator "LOOP", to nie mamy tez sposobu, zeby dostac sie z zewnatrz
do identyfikatora "break".
Co gorsza, system makr syntax-rules robi wszystko, zeby nam ten dostep
uniemozliwic, i chociaz w ogolnosci istnieja sposoby na omijanie higieny
makr w tym systemie, sa one bardzo trudne, a ich zastosowanie powoduje
powstanie kodu, ktorego analiza jest bardzo trudna.
Jedyny "prosty" sposob obejscia tego problemu polega na tym, zeby uczynic
slowo kluczowe sluzace do przerwania petli jednym z argumentow makra:
: (define-syntax-rule (while/break break condition actions ...)
: (call/cc
: (lambda (break)
: (define (LOOP)
: (if condition
: (begin actions ... (LOOP))))
: (LOOP))))
Trudno jednak uznac takie rozwiazanie za satysfakcjonujace. Znalezienie
lepszego rozwiazania bedzie od nas wymagalo wyjscia poza system makr
"syntax-rules" i przyjrzenia sie jego architektonice.
-
3. Data: 2014-11-12 05:42:14
Temat: Re: Makra higieniczne w jezyku Scheme
Od: A.L. <a...@a...com>
On Tue, 11 Nov 2014 14:36:57 -0800 (PST), g...@g...com
wrote:
>W kolejnym poscie zamieszczam czwarty rozdzial swojego wywodu
>o makrach w Schemie.
>
>Poruszam w nim temat makr higienicznych "syntax-rules", starajac sie
>przy tym pokazac, jakie problemy rozwiazuja, a jakie tworza nowe.
A do czego to sie moze przydac?...
A.L.
-
4. Data: 2014-11-12 09:02:06
Temat: Re: Makra higieniczne w jezyku Scheme
Od: g...@g...com
W dniu środa, 12 listopada 2014 05:42:15 UTC+1 użytkownik A. L. napisał:
>
> A do czego to sie moze przydac?...
Zastosowaniom zamierzalem wprawdzie poswiecic osobny rozdzial,
ale moge co nieco opowiedziec juz teraz. Ostatnio musialem napsiac
taki kod w javascripcie:
function allowedMoves(board, position) {
var x = position[0];
var y = position[1];
var result = [];
for(var i = x-1; i >= 0 && !board[i][y]; --i) {
result.push([i,y]);
}
for(var i = x+1; i < board.length && !board[i][y]; ++i) {
result.push([i,y])
}
for(var j = y-1; j >= 0 && !board[x][j]; --j) {
result.push([x,j]);
}
for(var j = y+1; j < board[x].length && !board[x][j]; ++j) {
result.push([x,j])
}
return result;
}
Sa tutaj cztery petle, z ktorymi niewiele tak naprawde mozna
zrobic. Sa tez cztery okazje do popelnienia bledow. (Nawiasem
mowiac, przy pisaniu tego kodu rzeczywiscie popelnilem blad,
ktory byl dosc trudny do znalezienia)
Gdybym mial w JS do dyspozycji system makr, moglbym napisac cos
w stylu, powiedzmy
function allowedMoves(board, position) {
var x = position[0];
var y = position[1];
var result = [];
var W = board.length;
var H = board[0].length;
with_syntax(mark($, <>, limit, n, over, p, q),
for(var n = over $ 1; n <> limit && !board[p][q]; n = n $ 1) {
result.push([p,q]);
})
{
mark(-, >=, 0, i, x, i, y);
mark(+, <, W, i, x, i, y);
mark(-, >=, 0, j, y, x, j);
mark(+, <, H, j, y, x, j);
}
return result;
}
Wprawdzie dlugosc kodu jest porownywalna, ale wszystkie pojawiajace
sie w nim nietrywialne powtorzenia strukturalne zostaly wyekstrahowane
do makra, co ulatwia utrzymanie kodu i zmniejsza mozliwosc popelnienia
bledu.
Pozniej postaram sie podac bardziej zaawansowane przyklady.
-
5. Data: 2014-11-12 11:00:50
Temat: Re: Makra higieniczne w jezyku Scheme
Od: firr <p...@g...com>
W dniu środa, 12 listopada 2014 09:02:07 UTC+1 użytkownik g...@g...com
napisał:
> W dniu środa, 12 listopada 2014 05:42:15 UTC+1 użytkownik A. L. napisał:
> >
> > A do czego to sie moze przydac?...
>
> Zastosowaniom zamierzalem wprawdzie poswiecic osobny rozdzial,
> ale moge co nieco opowiedziec juz teraz. Ostatnio musialem napsiac
> taki kod w javascripcie:
>
> function allowedMoves(board, position) {
> var x = position[0];
> var y = position[1];
>
> var result = [];
>
> for(var i = x-1; i >= 0 && !board[i][y]; --i) {
> result.push([i,y]);
> }
> for(var i = x+1; i < board.length && !board[i][y]; ++i) {
> result.push([i,y])
> }
> for(var j = y-1; j >= 0 && !board[x][j]; --j) {
> result.push([x,j]);
> }
> for(var j = y+1; j < board[x].length && !board[x][j]; ++j) {
> result.push([x,j])
> }
> return result;
> }
>
jawaskrypt ciekawy jezyk, nieststy ciagle nie mam sily sie go nauczyc, tylko czasem
wpadaja mi w oko kwiatki ktore rozumiem albo ktorych nie rozumiem
mialbys moze chwile by wyjasnic mi co tutaj sie
przykladowo dzieje
io.sockets.on("connection", function (socket) {
socket.unit = null;
socket.on("connectServer", function (data, reply) {
var unit = new IB.Player(data);
worldHandler.addUnit(unit);
}
});
mniej chodzi mi o sementyke ale o skladnie
co to jest? cialo funkcji przekazywane jako argument? a dalej w srodku z tym
socket.on to samo? sa to po prostu skrotowe zapisy by nie pisac 3 cial funkcji w
trzech miejscach czy cos wiecej?
-
6. Data: 2014-11-12 11:19:16
Temat: Re: Makra higieniczne w jezyku Scheme
Od: g...@g...com
W dniu środa, 12 listopada 2014 11:00:53 UTC+1 użytkownik firr napisał:
> jawaskrypt ciekawy jezyk, nieststy ciagle nie mam sily sie go nauczyc, tylko czasem
wpadaja mi w oko kwiatki ktore rozumiem albo ktorych nie rozumiem
>
> mialbys moze chwile by wyjasnic mi co tutaj sie
> przykladowo dzieje
>
> io.sockets.on("connection", function (socket) {
> socket.unit = null;
> socket.on("connectServer", function (data, reply) {
> var unit = new IB.Player(data);
>
> worldHandler.addUnit(unit);
> }
> });
>
> mniej chodzi mi o sementyke ale o skladnie
> co to jest? cialo funkcji przekazywane jako argument? a dalej w srodku z tym
socket.on to samo? sa to po prostu skrotowe zapisy by nie pisac 3 cial funkcji w
trzech miejscach czy cos wiecej?
jest mniej wiecej tak jak mowisz. (jednak zamiast powiedziec, ze "cialo funkcji
jest przekazywane jako argument", raczej bym powiedzial, ze "funkcja jest
przekazywana jako argument")
zgodnie z oczekiwaniem, moglbys alterniatywnie zapisac:
function connectServerHandler(data, reply) {
var unit = new IB.Player(data);
worldHandler.addUnit(unit);
}
function connectionHandler(socket) {
socket.unit = null;
socket.on("connectServer", connectServerHandler);
}
io.sockets.on("connection", connectionHandler);
nie ma duzej roznicy pomiedzy takim kodem, a np. kodem w C
przekazujacym wskazniki do funkcji.
w ogolnosci jednak sila ekspresji javascriptu jest wieksza,
niz sila ekspresji C, poniewaz mozesz w js tworzyc tzw. "domkniecia"
("closures"), czyli funkcje ktore przechowuja swoje lokalne srodowisko.
klasyczny przyklad wyglada tak:
function make_counter() {
var counter = 0;
return function() { return ++counter; }
}
var c = make_counter();
print c(); // 1
print c(); // 2
print c(); // 3
w C mozesz oczywiscie uzyskac funkcjonalnie podobny efekt, przekazujac
do funkcji osobna strukture (wiele bibliotek ma takie interfejsy, ze
pobieraja wskaznik na funkcje i wskaznik void *, ktory funkcja
ma sobie sama rzutowac do odpowiedniego typu)
-
7. Data: 2014-11-12 11:41:42
Temat: Re: Makra higieniczne w jezyku Scheme
Od: firr <p...@g...com>
W dniu środa, 12 listopada 2014 11:19:17 UTC+1 użytkownik g...@g...com
napisał:
> W dniu środa, 12 listopada 2014 11:00:53 UTC+1 użytkownik firr napisał:
>
> > jawaskrypt ciekawy jezyk, nieststy ciagle nie mam sily sie go nauczyc, tylko
czasem wpadaja mi w oko kwiatki ktore rozumiem albo ktorych nie rozumiem
> >
> > mialbys moze chwile by wyjasnic mi co tutaj sie
> > przykladowo dzieje
> >
> > io.sockets.on("connection", function (socket) {
> > socket.unit = null;
> > socket.on("connectServer", function (data, reply) {
> > var unit = new IB.Player(data);
> >
> > worldHandler.addUnit(unit);
> > }
> > });
> >
> > mniej chodzi mi o sementyke ale o skladnie
> > co to jest? cialo funkcji przekazywane jako argument? a dalej w srodku z tym
socket.on to samo? sa to po prostu skrotowe zapisy by nie pisac 3 cial funkcji w
trzech miejscach czy cos wiecej?
>
> jest mniej wiecej tak jak mowisz. (jednak zamiast powiedziec, ze "cialo funkcji
> jest przekazywane jako argument", raczej bym powiedzial, ze "funkcja jest
> przekazywana jako argument")
> zgodnie z oczekiwaniem, moglbys alterniatywnie zapisac:
>
> function connectServerHandler(data, reply) {
> var unit = new IB.Player(data);
> worldHandler.addUnit(unit);
> }
>
> function connectionHandler(socket) {
> socket.unit = null;
> socket.on("connectServer", connectServerHandler);
> }
>
> io.sockets.on("connection", connectionHandler);
>
> nie ma duzej roznicy pomiedzy takim kodem, a np. kodem w C
> przekazujacym wskazniki do funkcji.
>
> w ogolnosci jednak sila ekspresji javascriptu jest wieksza,
> niz sila ekspresji C, poniewaz mozesz w js tworzyc tzw. "domkniecia"
> ("closures"), czyli funkcje ktore przechowuja swoje lokalne srodowisko.
> klasyczny przyklad wyglada tak:
>
> function make_counter() {
> var counter = 0;
> return function() { return ++counter; }
> }
>
> var c = make_counter();
>
> print c(); // 1
> print c(); // 2
> print c(); // 3
>
> w C mozesz oczywiscie uzyskac funkcjonalnie podobny efekt, przekazujac
> do funkcji osobna strukture (wiele bibliotek ma takie interfejsy, ze
> pobieraja wskaznik na funkcje i wskaznik void *, ktory funkcja
> ma sobie sama rzutowac do odpowiedniego typu)
swietnie,
moge dorzucic pare uwag
1. nazwa handler tutaj jakiej uzywasz jest na pewno zła - powinno to sie nazywac
raczej OnConnection, OnConnectServer - to słowo handeler wprowadza jezykową pianę i
wydłuza 'językowo' kod a im krotszytym lepszy
2. wiesz moze co te 3 funkcje wlasciwie robia?
to pierwsze jest jakby jasne na sygnel polaczenia ustawia handler dla eventu
connectServer - ale dlaczego to tak jest? tego jakos nie pojalem, to piwrwsze to jest
pierwsze polaczenie a to drugie to sa eventy dla poszczegolnych przychodzących
pakietow or what?
3. jestes pewien ze to z closures jest to dzialajacy kod? nie do konca zrozumielem
jak to dziala acz musze troche dluzej popatrzec
4. system callbackow czy 'przekazywania funkcji do funkcji' w c jest raczej slaby,
kiedys pisalem ntt i jeszcze kiedys pewnie napisze
(ale nie teraz bo jest to glebszy temat)
-
8. Data: 2014-11-12 12:11:37
Temat: Re: Makra higieniczne w jezyku Scheme
Od: g...@g...com
W dniu środa, 12 listopada 2014 11:41:42 UTC+1 użytkownik firr napisał:
>
> swietnie,
> moge dorzucic pare uwag
>
> 1. nazwa handler tutaj jakiej uzywasz jest na pewno zła - powinno to sie nazywac
raczej OnConnection, OnConnectServer - to słowo handeler wprowadza jezykową pianę i
wydłuza 'językowo' kod a im krotszytym lepszy
to zalezy tez od konwencji przyjetych w reszcie projektu.
ale nie do konca sie zgodze z tym, ze im kod krotszy tym lepszy.
im kod bardziej zrozumialy, tym lepszy (w przeciwnym razie APL
bylby najlepszym jezykiem programowania)
w tym przypadku jednak moim celem bylo pokazanie rownowaznosci
semantycznej dwoch form syntaktycznych, i mysle, ze temu celowi
uzywanie nawet nieco rozwleklejszego zapisu sluzy dobrze.
tak naprawde oryginalny kod jest pod wzgledem zwiezlosci lepszy
od tego, co ja napisalem.
> 2. wiesz moze co te 3 funkcje wlasciwie robia?
> to pierwsze jest jakby jasne na sygnel polaczenia ustawia handler dla eventu
connectServer - ale dlaczego to tak jest? tego jakos nie pojalem, to piwrwsze to jest
pierwsze polaczenie a to drugie to sa eventy dla poszczegolnych przychodzących
pakietow or what?
pewnie musialbys poczytac wiecej o programowaniu sieciowym i o tej
konkretnej bibliotece.
na ile rozumem temat (zgadujac, ze kod jest oparty na gniazdach unixa),
to jest tak, ze serwer nasluchuje na jednym porcie z ktorym zwiazane
jest gniazdo, natomiast ilekroc jakis klient sie polaczy, jest tworzone
nowe gniazdo do obslugi tego konkretnego klienta. Ale nie wiem.
ten kod jest wziety z nodejs?
> 3. jestes pewien ze to z closures jest to dzialajacy kod? nie do konca zrozumielem
jak to dziala acz musze troche dluzej popatrzec
jak masz chrome'a albo firefoxa, to mozesz wcisnac ctrl+shift+c,
wejsc w konsole i wpisac ten kod i sprawdzic czy dziala.
/* u mnie dziala */
> 4. system callbackow czy 'przekazywania funkcji do funkcji'
> w c jest raczej slaby, kiedys pisalem ntt i jeszcze kiedys pewnie napisze
> (ale nie teraz bo jest to glebszy temat)
jak to powiedzial Stanislaw Wyspanski, lepszen taken niz zaden (czy cos)
-
9. Data: 2014-11-12 12:13:08
Temat: Re: Makra higieniczne w jezyku Scheme
Od: firr <p...@g...com>
>
> 4. system callbackow czy 'przekazywania funkcji do funkcji' w c jest raczej slaby,
kiedys pisalem ntt i jeszcze kiedys pewnie napisze
> (ale nie teraz bo jest to glebszy temat)
to o czym pisałem bylo o tym (i to jest wazna uwaga) ze w c mozna przekazywac
wskazniki na
funkcje ale nie mozesz przekazac funkcji juz
z argumentami, na przyklad powiedzmy ze
mam funkcje profie() ktora mierzy czas wykonania (w nanosekundach) przekazanej jej
funkcji
profile( add(1,2,3) );
profile( print(" [11:47] <omatkoboska> idę na szluga ") );
profile( Beep(10,1000) );
a takie cos jest b. potrzebne.. (skladnia jest zajeta ale mozna dodac jakies
oznaczenie/slowo kluczowe informujace ze to nei ejst 'wywolywane na wejsciu tylko w
srodku' itp)
(co mozna zrobic w c to wiadomo.. tak jak zdaje sie mowisz mozna napisac sobie
wrappery
void add(void* args) { ....}
void print(void* args) { ....}
void Beep(void* args) { ....}
i funkcje przyjmujaca te wrappery
profile(pFunWrapper fun, void* args)
{
//... kod
fun(args);
// ... kod
}
)
tymaczasem mozna by to w c zrobic automatycznie
i jest to proste do zrobienia (czy to jest odpowiednik closures z innych jezykow to
nie wiem, byc moze nie do konca bo te przekazywane funkcje nie maja tutaj dostepu do
swoich jakichs tam kontekstow tylko po prostu ciagna swoje argumenty)
druga rzecz ze tą warstwe kombinowanie funkci w c miedzy sobą mozna jeszcze o wiele
bardziej rozbudowac o czym bylo pisane przeze mnie calkiem niedawno (chyba ze dwa
tygodnie temu na plc)
-
10. Data: 2014-11-12 12:20:17
Temat: Re: Makra higieniczne w jezyku Scheme
Od: g...@g...com
W dniu środa, 12 listopada 2014 12:13:08 UTC+1 użytkownik firr napisał:
> >
> to o czym pisałem bylo o tym (i to jest wazna uwaga) ze w c mozna przekazywac
wskazniki na
> funkcje ale nie mozesz przekazac funkcji juz
> z argumentami, na przyklad powiedzmy ze
> mam funkcje profie() ktora mierzy czas wykonania (w nanosekundach) przekazanej jej
funkcji
>
> profile( add(1,2,3) );
>
> profile( print(" [11:47] <omatkoboska> idę na szluga ") );
>
> profile( Beep(10,1000) );
>
> a takie cos jest b. potrzebne.. (skladnia jest zajeta ale mozna dodac jakies
oznaczenie/slowo kluczowe informujace ze to nei ejst 'wywolywane na wejsciu tylko w
srodku' itp)
>
> (co mozna zrobic w c to wiadomo.. tak jak zdaje sie mowisz mozna napisac sobie
wrappery
>
> void add(void* args) { ....}
> void print(void* args) { ....}
> void Beep(void* args) { ....}
>
> i funkcje przyjmujaca te wrappery
>
> profile(pFunWrapper fun, void* args)
> {
> //... kod
> fun(args);
> // ... kod
> }
> )
>
> tymaczasem mozna by to w c zrobic automatycznie
> i jest to proste do zrobienia (czy to jest odpowiednik closures z innych jezykow to
nie wiem, byc moze nie do konca bo te przekazywane funkcje nie maja tutaj dostepu do
swoich jakichs tam kontekstow tylko po prostu ciagna swoje argumenty)
Akurat tego rodzaju rzeczy mozna dosc latwo rozwiazac przy pomocy
makra preprocesora C:
#define PROFILE(call) { \
// ... kod \
call; \
// ... kod \
}