W pewnej pythonowej bibliotece była pewna funkcja, która akceptowała dowolnie nazwane argumenty, a potem zapisywała je jako atrybuty znacznika HTML.
Coś w tym rodzaju:
def tag( t, **keys ): print( "<" + t, end='' ) for k in keys: print( ' ' + k + '="' + str(keys[k]) + '"', end = '' ) print( "/>" )
Z rozpędu próbowałem ostatnio wywołać ją w taki sposób:
tag( "circle", cx=100, cy=20, fill-opacity=0.6 )
To oczywiście nie działa, bo - cytuję:
>>> tag( "circle", cx=100, cy=90, fill-opacity=0.9 ) File "", line 1 SyntaxError: keyword can't be an expression
Trzeba to zrobić tak:
tag( "circle", cx=100, cy=90, **{"fill-opacity":0.9} )Używamy tu pythonowego zapisu służącego do przekazywania nazwanych argumentów przez słownik.
Pojedyncza gwiazka służy do przekazywania argumentów przez listę. Przekazywanie dowolnej liczby argumentów za pomocą tablicy nie jest niczym nowym. W języku C można to robić używając makrodefinicji va_start, va_list i pokrewnych, ale nie jest to elastyczny mechanizm. W JavaScript jest już lepiej - mamy apply() i call() w duchu lispowym. Cała idea pojawia się zresztą wyraźnie w sławnej SICP , ale, co ciekawe w oryginalnym interpreterze Johna McCarthy'ego - nie pojawia się wcale, ten pierwszy interpreter Lispu oparty był na eval.
To, co mamy w Pythonie i Javascripcie jest bardziej elastyczne i estetyczne - lista (słownik) argumentów może być zbudowana niezależnie, jako obiekt pierwszej klasy. W C to niemożliwe - musi ona pochodzić z wywołania naszej funkcji. Ale przynajmniej można ją przekazać dalej - robi się to tak:
#include#include void somefun( const char *fmt, ... ) { va_list ap; va_start( ap, fmt ); vprintf( fmt, ap ); va_end( ap ); }
Brak komentarzy:
Prześlij komentarz