saxus (statz) | #9, Agyfasz (419) |
4298 | #2a44 | ^ | Idézet | Mon, 27 Jan 2014 08:36:16 +01 |
84.3.*.* | *.catv.pool.telekom.hu |
Btw. szerintem az utolso hasznalhato KDE a KDE 1.x-ek voltak :) Na szoval lambda epression. Igen, amit a masodik peldaban adtal, az is kozelit hozza (mivel a JavaScriptnek sokkal-sokkal tobb koze van a Lisphez, mint a Javahoz), de nem egeszen errol van szo. Gondolom emlekszel ilyenre php-ben, mint call_user_func_array($array, $func), ahol minden egyes tombelemre meghivhattal, pl. igy: function lofasz($x) { echo $x, "\n"; } call_user_func_array($array, 'lofasz'); Na ezt teszi valamivel kulturaltabba a lambda: call_user_func_array($array, function($x) { echo $x, "\n"; } Kicsit mas peldak: .NET3-ban bejott a LinQ, ami ad rengeteg extension methodot mindenfele collectionok basztatasara. Ket fele modja van, egyik egy SQL szeru feliras, masik meg a fuggvenyesdi. Ott van pl. egy IEnumerable<T> Where(this IEnumerable<T>, Func<T, bool>) metodus. (Azaz minden T tipusu listat kibovit egy Where metodussal, ami parameterul egy olyan fuggvenyt var, aminek T bemenete van es boolt ad vissza, valamitn az egesz visszaad egy T tipusu felsorolot - gyakorlatilag az meg egy listat allit elo). Azaz modnjuk ezt a kodot: var lista = new List<int>(...); int n = 4; var ujLista = new List<int>(); foreach (var i in lista) if (Szures(i, n)) ujLista.Add(i); bool Szures(int i, int n) { return i > n; } Felirhatod a kovetkezokepp is: var lista = new List<int>(); int n = 4; var ujLista = lista.Where((x) => { return x > n; }); // vagy: var ujLista = lista.Where((x) => x > n); Nagy elonye a sima fuggvenyekhez kepest, hogy kepes atvenni a kornyezetebol a valtozok erteket. Masik elonye, hogy joval tomorebb es pl. 1-2 soros esemenykezelok irasakor joval egyszerubb egy ilyet irni, mint megcsinalni ra egy komplett fv-t. Plusz nem lesz annyira szetszorva sem a kod. Egyebkent egesz jol kivaltja a strategy patternt is: delegate int ValamiMuvelet(int a, int b); ValamiMuvelet Micsinaljunk(string s) { switch (s) case "+": return (a,b) => a+b; case "-": return (a,b) => a-b; case "*: return (a,b) => a*b; // ... } ValamiMuvelet v = Micsinaljunk("+"); int res = v(1,2); Na most ugyanez Javaban eddig ugy nezett ki, hogy: interface ValamiMuvelet { int muvelet(int a, int b); } ValamiMuvelet Micsinaljunk(string s) { if (s.equals("+") return new ValamiMuvelet { @Override public int muvelet(int a, int b) { return a+b; } }; if (s.equals("+") return new ValamiMuvelet { @Override public int muvelet(int a, int b) { return a-b; } }; if (s.equals("+") return new ValamiMuvelet { @Override public int muvelet(int a, int b) { return a*b; } }; } int res = Micsinaljunk("+").muvelet(1,2); (Most kb. ugyanannyi lesz, mint a C#-os verzio, csak => helyett ->. Leszamitva, hogy az interface marad es a felszin alatt ugyanaz a biolerplate kod fog elkeszulni a leforditott kodban, mint amit itt leirtam. (Lesz string case is, hurra.) Osztalyostul, mindenestul. .NET-ben ez ugyanugy csak egy fuggveny. Miert jo ez meg? Egyeszt azon kivul, hogy "kodot tusz visszaadni" egy metodusbol, van egy csomo plusz felhasznalasi terulete, ahol hasznos tud lenni. Pl. a PHP-s call_user_func_array() - vagy, hogy a .Where() -s peldanal maradjunk: a PHP-s array_filter - menthetetlenul vegigfut az osszes tombelemen. LinQ viszont ugy mukodik, hogy valojaban csak egy felsorolo objektumot ad vissza, ami gyakorlatilag egy olyan metodust implemental, amivel ki tudsz kerdezni mindig egy kovetkezo elemet. Ha pl. ezt a LinQ queryt nezzuk: var elolenyek = ... var kecskek = from x in elolenyek where x.Micsoda == "kecske" && x.Kor > 10 select x; foreach (var kecske in kecskek) ... Akkor a kecskek-be nem egy tomb fog egybol letrejonni, hanem egy olyan objektum, amibol a foreach mindig kiker egy elemet, mikor a kovetkezo elemre lep. Ennek van egy csomo elonye, pl. sporolsz memoriat (mert nem hozol letre egy tombot), nem dolgozol elore, stb. ilyen amugy van pl. Pythonban is, ld. range() fuggveny, bar mar PHP-ben is van. |