1)
Az alábbiakban látható egy python függvény summation
, amely kocka / négyzet / .. összeget képes végrehajtani, hasonló műveleteket .
def identity(k): return k def cube(k): return pow(k, 3) def square(k): return pow(k,2) def summation(n, term): if n == 0: return 0 else: return term(n) + summation(n-1, term) def sum_cubes(n): return summation(n, cube) if __name__ == "__main__": sum = sum_cubes(4) print(sum) """ In C, We can implement the same using function pointers. Goal is, to perform similar operations(Sum of ..) using single function summation()"""
2)
Az alábbiakban vegye fontolóra az api rendezését C-ből,
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
Itt qsort
bármilyen adatot bármilyen típusú , lebegők / fájlnevek tömbje egy könyvtárban / karakterláncok / …
Kérdés:
Hogyan definiálható egy általános függvény?
A summation
általános függvény?
vagy
A qsort
általános függvény?
vagy
Két példát felsorolva: A Általános függvény érvénytelen terminológia?
Megjegyzés: Motiváció-Cím qsort
vagy bármilyen általam tervezett funkció
Megjegyzések
- A ” általános függvény ” olvastad, hogy nem értesz ‘? Segíthet, ha ezt egy csomó kód megírása helyett közzéteszi.
- A típuselméleti kifejezés annak a genericizmusnak a fajtája, ahol a függvény bármilyen típusnál működik korlátozás nélkül és a konkrét típus ismerete nélkül: paraméteres polimorfizmus . Az identitásfüggvény ily módon általános.
- Egyes nyelvekben (például a Java-ban) ” a ” általános funkcióval rendelkezik egy konkrét műszaki meghatározás. De a Python esetében ez nem így van, így a ” általános függvénynek ” nincs pontosan definiált jelentése. Ez nem azt jelenti, hogy ” érvénytelen terminológia “, csupán azt, hogy a kifejezés használatakor ismernie kell a kontextust.
- @AndresF. A Javascrpt is nagyon használja ezt az általános funkció terminológiát. Mert lehet, hogy van olyan funkciója, amely bármely html elem feldolgozásához szükséges (példa – törölje az adott html elem összes gyermekét)
Válasz
A” generikus “kifejezésnek több jelentése van.
Informális meghatározás
“általános” a mindennapi nyelvben olyasvalami, amely közös tulajdonságokkal rendelkezik, de bizonyos szempontból kevésbé specifikus.
Ebben a perspektívában megfontolhatja az qsort()
általános nevet: ennek a függvénynek a kódját képes rendezni bármilyen rögzített méretű adatszerkezetet, amelyhez összehasonlítási függvényt határozhat meg a QSORT algoritmus használatával.
Ugyanez vonatkozik a summation()
függvényedre is, amely a függvények használatával kapott kifejezéseket egyetlen paraméterrel foglalja össze.
Formális meghatározás
A programozási nyelvek, például a C ++ vagy a Java, lehetővé teszik az általános programozást sablonok vagy generikusok használatával:
Definíció a C ++ 14 szabványból : A sablon osztály- vagy függvénycsaládot vagy álnevet definiál egy típuscsaládhoz.
Az elv az, hogy egy osztály vagy egy függvény megvalósítását típusok szerint lehet paraméterezni.
E formálisabb nézőpont szerint qsort()
nem általános függvény. Megvalósításának nem kell meghatároznia a fordítás során semmilyen típust, viselkedése pedig típusfüggetlen. Az egyetlen dolog, amire szüksége van, az a rendezendő elemek mérete, és ez a méret egy hétköznapi argumentum, amelyet futás közben dolgoznak fel.
olyan nyelv esetében, amely nincs statikusan beírva, például Python , nem vagyok biztos benne, mit válaszoljak a . Úgy gondolom, hogy nem általános, mert a megvalósítása és viselkedése nem típusfüggő: ez a függvény csak egy magasabb rendű függvény, a term
argumentummal Nem használ olyan funkciót, amely típusok alapján megváltoztatná ennek a függvénynek a viselkedését.
Egy általános függvény szemléltetéséhez nézze meg a C ++ szabványos függvényt std::sort()
: végrehajtása az argumentumok típusától függ (és adott esetben egy összehasonlító függvény egy meghatározott típusú argumentumokkal). A C ++ sablonok szolgáltatásainak felhasználásával bármilyen típusú tárolót rendezhet, azzal a feltétellel, hogy rendelkezik az operátorokkal / tagfunkciókkal / vonásokkal / iterátorokkal, amelyekre az általános függvény megvalósítása szükséges.
Lehet-e egy dinamikus gépelt nyelvnek általános funkciója?
A dinamikusan beírt nyelv megköveteli kevesebb általános kód, mint a statikusan tipizált nyelvek.
Ha például van dinamikus típusú objektumokból álló tárolója, akkor a qsort függvény generikusan rendezheti a tárolót, amennyiben a tároló két elemének bármilyen kombinációja összehasonlítható.
De ilyen rugalmas környezetben is hasznos lehet az általános – típusfüggő – programozás. A tipikus használati eset a multimódok, ahol a viselkedés vagy a kód függ az argumentumok típusától vagy akár a típusok kombinációjától (például két különböző alakzat metszéspontjának meghatározásához). További információ:
- Általános programozási csomag a python számára: multidispatching
- Az általános függvények használhatóvá tétele a smalltalk alkalmazásban
- Példa a General Lisp általános funkcióira
Megjegyzések
- Nem biztos, miért hasonlítjuk össze a generikusakat (főleg arra használják, hogy elkerüljék a Java-típusok átküldését (lásd: specifikáció vagy oktatóanyag ). Mindazonáltal ‘ enyhén szerkesztettem a definíciós részt, hogy foglalkozzon a megjegyzésével.
- A Python Generic csomagjának semmi köze az általános függvényekhez. Kivéve, ha ugyanaz a melléknév van.
- @Killian, ha általános programozás , arról szól, hogy elvonatkoztatnak a konkrét, hatékony algoritmusoktól. különböző algoritmusok megszerzéséhez, amelyek különböző adatábrázolásokkal kombinálhatók , úgy gondolom, hogy az adott csomagban szereplő multimódoknak be kell lenniük, ne gondolja
t?
Válasz
Az általános függvények legalább egy függvény argumentumának típusát veszik át fordításkor. Vagyis a fordító kideríti, hogy egy adott helyen melyik típust használják, és pontosan ezt a típust alkalmazza ott, ahol a függvényben használják. Például. ha a függvényében van egy általános argumentum, amelyet egy +
operátorral használnak, akkor a típusnak megfelelő módszerekkel kell rendelkeznie. A karakterláncok / tömbök esetében ez sok esetben összefűzés, az egész szám / lebegés pedig összeadás lehet. A fordító észlelheti, hogy egy alkalmazás helyes műveletet alkalmaz. A C rutin ebben az értelemben nem általános, mivel a programozó alkalmaz bizonyos méretinformációkat, és nem a fordító észleli a típust és a megfelelő méretet használja.
Pl. Valamilyen fiktív nyelven
func add(p1,p2) { return p1+p2 } print add("a", "b") // yields "ab" print add(1, 2) // yields 3
Itt a fordító első esetben észleli, hogy két karakterláncot alkalmaznak, és belsőleg kibővítenek például
func add(p1:string, p2:string)
és a +
-t összefűzésként kezelje, míg a második esetben ez kibővül
func add(p1:int, p2:int)
egész paraméterek. Általános azt jelenti, hogy a fordító a fordítási idő alatt egyedi kódot generál. A Python például be van írva, és futás közben ilyen típusú helyettesítést hajt végre. Azt jelenti: A Pythonnak nincsenek általános funkciói, mivel minden valamiféle általános.
Megjegyzések
- Nem jött létre az ötleted. Úgy érted, hogy a + egy általános függvény, szintaxis a C ++ nyelven?
- A függvényfüggvény-argumentumok magasabb rendűek funkció s a Python / JavaScript világban. A C-ben függvénymutatókra van szükségünk.
- Lásd a fenti szerkesztésemet.
- Tehát milyen funkció a
summation
, Magasabb rendű funkció? és ezen kívül semmi más? - Nagyon sok definíció létezik a generikus kifejezésre vonatkozóan. A Stroustrup például ” programozásként definiálja a típusokat paraméterként “. A wikipédia használatához inkább
megyek: hu.wikipedia.org/wiki/Generic_programming
Válasz
Ezt a C ++ perspektívájából fogom kezdeni, majd továbbmegyek C-be.
Az olyan statikusan beírt nyelvekben, mint a C, C ++, Java, stb., egy “általános” függvény lehetővé teszi a függvényműveletek egyszer megadását, helyettesítők használatával minden típushoz, amely változhat a különböző hívások között (ami azt jelenti, hogy olyan funkciók vannak, mint qsort
és bsearch
, egészen biztosan not általános függvények). Ideális esetben azt is szeretné, ha a fordító automatikusan észlelné az általános függvény minden hívását, és szükség esetén létrehozná a tényleges kódot.
A C ++ megkönnyíti ezt a 1 -et azáltal, hogy sablonokat kínál:
template <typename T> T summation( T *values, size_t numValues ) { T result = 0; for ( size_t i = 0; i < numValues; i++ ) result += values[i]; return result; }
T
bármely 2 típus helyőrzője, ezért hívhatja:
int ivals[] = {1,2,3,4,5,6,7,8,9}; double dvals[] = {1,2,3,4,5,6,7,8,9}; int sumi = summation( ivals, 10 ); double sumd = summation( dvals, 10 );
A kód fordításakor a fordító meglátja a két hívást a summation
címre, és levezeti az argumentumok típusait. Minden más típushoz generál egy új példányt a függvényből, egyedi nevet adva neki:
int summation_i( int *values, size_t numValues ) // actual compilers will generate { // more complex "mangled" names int result = 0; // than this ... } double summation_d( double *values, size_t numValues ) { double result = 0; ... }
Ezután kódot generál oly módon, hogy a summation_i
eredményt a sumi
és a summation_d
fájlhoz hozzárendeljük id = “1d3d5f0441”>
.
A C nem kínál hasonlót a sablon szolgáltatáshoz. Hagyományosan kétféle módon támadtuk meg az általános programozást – akár makrók, akár void *
mindenhol, és a típus-tudatos műveleteket más funkciókra delegálhatja.
Itt egy makroszintű megoldás rossz példája:
#include <stdio.h> #define SUMMATION_DEF(t) \ t summation_##t( t *values, size_t numValues ) \ { \ t result = 0; \ for ( size_t i = 0; i < numValues; i++ ) \ result += values[i]; \ return result; \ } #define SUMMATION(t,x,s) summation_##t(x, s) SUMMATION_DEF(int) SUMMATION_DEF(double) int main( void ) { int ivals[] = {1, 2, 3, 4, 5}; double dvals[] = {1, 2, 3, 4, 5}; int sumi = SUMMATION(int, ivals, 5); double sumd = SUMMATION(double, dvals, 5); printf( "sumi = %d\n", sumi ); printf( "sumd = %f\n", sumd ); return 0; }
A SUMMATION_DEF
nagyjából hasonlít egy sablonhoz, mivel megadja a függvényműveleteket, a t
makroparamétert használva helyőrzőként. Használjuk a t
a függvénynév részeként – a ##
a token beillesztési operátor, és az előfeldolgozó kibővül t
, és csatolja ezt az értéket a 3 függvény nevéhez.
Ahol különbözik a C ++ -tól, az a tény, hogy a makró csak néma szövegpótlás. Nem váltja ki a fordító bármilyen speciális művelete. A tényleges függvénypéldányok nem generálódnak automatikusan a SUMMATION
makró esetleges invokációi alapján – kifejezetten elő kell állítanunk a kívánt függvényeket (ezért a SUMMATION_DEF(int)
és SUMMATION_DEF(double)
a main
előtt. Ez azt is jelenti, hogy amikor hívjuk a summation_xxx
a SUMMATION
makrón keresztül át kell adnunk a típust a makró argumentumlista részeként, hogy a megfelelő függvény meghívható legyen. Milyen fájdalom.
A A C 2011 szabvány hozzáadta a _Generic
kulcsszót, amely ebből a szempontból kissé megkönnyítheti az életet:
#include <stdio.h> #define SUMMATION_DEF(t) \ t summation_##t( t *values, size_t numValues ) \ { \ t result = 0; \ for ( size_t i = 0; i < numValues; i++ ) \ result += values[i]; \ return result; \ } #define SUMMATION(x,s) _Generic((x), \ int * : summation_int, \ double * : summation_double \ )(x, s) SUMMATION_DEF(int) SUMMATION_DEF(double) int main( void ) { int ivals[] = {1, 2, 3, 4, 5}; double dvals[] = {1, 2, 3, 4, 5}; int sumi = SUMMATION(ivals, 5); double sumd = SUMMATION(dvals, 5); printf( "sumi = %d\n", sumi ); printf( "sumd = %f\n", sumd ); return 0; }
A _Generic
kulcsszó lehetővé teszi a kifejezések kiértékelését a típusok alapján, tehát ha az első argumentum típus a SUMMATION
int *
, hívjuk a következőt: summation_int
; ez s double *
, hívjuk a summation_double
-t. Így nem kell megadnunk a típus nevét a makró argumentumokban.
A másik megközelítés, amint látta, a void *
használata, és a típus-tudatos műveletek más funkciókra való átruházása. Mint fentebb mondtam, az ” s nem igazán “általános” programozás, mivel manuálisan kell végrehajtania az egyes összehasonlító függvényeket az egyes típusokhoz. “Nem lehet egyszer csak kódolni, és készen is van vele. És a void *
használatával alapvetően a típusbiztonságot dobja ki az ablakon és a szembejövő forgalomba.
És mielőtt bárki panaszkodna – nem, ezen összegző funkciók egyike sem ellenőrzi vagy nem foglalkozik a számtani túlcsordulással. Ez egy másik nap tárgya.
- A “könnyű” kellően laza meghatározásához. A sablonok támogatásához használt metaprogramozási nyelv Turing-teljes, így igazán csodálatos * és lehetetlen megérteni vele a dolgokat.
- A “bármilyen típusú” kellően laza meghatározásához. Vegye figyelembe, hogy bármilyen típusú típust támogatnia kell az
+=
operátort, különben a fordító rákiabál. - Ez a kód megszakad az olyan típusoknál, mint a
unsigned int
vagy along double
, mivel a szóközben van szó. Nem tudom azonnal a probléma megoldását, és elegendő időt fordítottam erre a válaszra.