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ó:

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.


  1. 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.
  2. 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.
  3. Ez a kód megszakad az olyan típusoknál, mint a unsigned int vagy a long 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.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük