saxus (statz) | #9, Agyfasz (419) |
1117 | #2a40 | ^ | Idézet | Mon, 27 Jan 2014 01:28:54 +01 |
84.3.*.* | *.catv.pool.telekom.hu |
"Ja, saxus, olvastam, hogy valami barom hívogatott, zenélt, majd letette. Nagy kár volt a zenélős telefont tartani, csak nehogy aztán pislogj a telefonszámlára. " Valószínűleg egyébként a T-s ügyfélszolgálat volt. "Fingom sincs, hogy mi az a "lambdakifejezés", de borzasztóbb lehet, mint egy vérszomjas kecskehorda." Lényegében névtelen függvények. Gyakorlatilag egy függvényt adsz át paraméterül. Lehet, hogy csúnyán hangzik, de egyébként nem az, lehet vele gyorsan jó dolgokat összerakni. Annyival "tud" többet, mintha csak egy sima fv pointert adnál át, hogy képes használni a környezetét is, ahol definiáltad. Java-ban ezt helyben implementált interface-al szokták megoldani, kulturáltabb helyeken erre ott a delegált. Gondolom azért te is érzed, hogy egy típus és "paraméterbiztos függvényparaméter" helyett helyben implementálni egy névtelen osztályt elég ronda megoldás. Mondjuk Java Generics is elég ocsmány, pl. primitív típusokkal nem tud működni. Igazából az egész egy fordítási időben odahackelt valami, szemben pl. a .NET-tel, ahol maga a CLR része. |
TCH (statz) | #1, Főfasz (10443) |
170 | #2a41 | ^ | Idézet | Mon, 27 Jan 2014 01:33:38 +01 |
31.46.*.* | *.catv.pool.telekom.hu |
Én most ezt konkrétan nem értem. Most akkor ez lambda?faszom(kecske());Vagy ez? faszom.onkurwaanyad = function () { alert('anyad'); }; |
saxus (statz) | #9, Agyfasz (419) |
14 | #2a42 | ^ | Idézet | Mon, 27 Jan 2014 01:39:23 +01 |
84.3.*.* | *.catv.pool.telekom.hu |
Holnap leírom. |
TCH (statz) | #1, Főfasz (10443) |
1210 | #2a43 | ^ | Idézet | Mon, 27 Jan 2014 01:42:33 +01 |
31.46.*.* | *.catv.pool.telekom.hu |
Mármint reggel leírod, nem? Vagy még 24 órát várni kell?Hát én eddig is tudtam, hogy ez az ember totálisan retardált, de hogy ennyire? A KDE 4 egy instabil bloatware fos, a KDE 3 meg talán a legkönnyebben idomítható és legjobban testreszabható asztalkezelő. De itt a másik hülye: Tényleg? GNOME-ban nincsenek tán? De. XFCE? De. LXDE? De. Akkor...? Ja. Unity! Meg windóznyóccsempe! Éééééértem! Szóval a KDE 3 az autista óvodásoké! Azért ez nem gyengén fészpalm, pont azt a két csempés fost csinálták az r=0-knak, vö. winnyogsz vs. idiocracy. Ennek a két turbómajomnak jár az ikszdévonat az ultimate roflmao + ultimate fail kombóért. |
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. |
TCH (statz) | #1, Főfasz (10443) |
2001 | #2a45 | ^ | Idézet | Mon, 27 Jan 2014 12:17:44 +01 |
31.46.*.* | *.catv.pool.telekom.hu |
KDE 3-at használok, amióta az eszemet tudom. Az volt UHU alatt, az volt Slax alatt, az van Ubi alatt és az lesz Debian/CentOS alatt is (akármelyikre is váltsak majd). Csak tudom, hogy mennyire könnyen és jól idomítható, hogy stabil, hogy egy KDE4-hez vagy GNOME3-hoz, pláne egy junitihez képest mennyire gyors. Persze GNOME2-től és XFCE4-től elmarad sebességben, de sokkal többet tud náluk. És nem lassabb annyival, mint amennyivel többet tud és kényelmesebb. Jah, array_map és tsai. Ennyi? Melegvíz v2.0? Már megint előhúzott valaki egy negyven éves programozási metódust és adott neki valamilyen kúl nevet. (vö. MVC) Bazdmeg, ezt a SmallTalk már a hetvenes években tudta, csak ő kódblokknak meg névtelen függvénynek hívta. És még az sem biztos, hogy ő tudta ezt először... A többit meg had ne minősítsem. Réteg, réteg hátán, ojjektum az ojjektum kedvéért, klónozás a klónozás kedvéért... Viszont, hogy mondjak valamit amit talán hasznosítani tudsz, switch/case helyett ugrótáblát is használhatnál, mert annak a meghívása mindig ugyanannyi (egy indexelés és egy feltétel nélküli ugrás) lesz, míg a switch/case az minden egyes újabb ágnál +1 if/elseif azaz egy újabb branch, ennek megfelelően a szerkezet hosszával arányosan lassul. Sok tízszeres sebességnövekedést el lehet ezzel érni. Persze csak akkor, ha a nyelv amit használsz, támogatja a függvénycímtömböt és annak a meghívását. Nem tudom, hogy dzsuvába vagy cisztába van ilyen. Mísz-be* meg pláne nem tudom. * M# |
saxus (statz) | #9, Agyfasz (419) |
1200 | #2a46 | ^ | Idézet | Mon, 27 Jan 2014 12:48:53 +01 |
86.101.*.* | *.business.broadband.hu |
Ezt régen is lambda expression-nak hívták funkcprogos körökben. Ha ezt nézzük melegvíz, mert tényleg egy régóta létező dolog. Viszont OOP nyelvekben eddig ezek macerásak voltak, cserébe sok esetben jól használható és jóval tömörebb kódot ad.
:) .NET kb. 5-6 db switch-case után átvált arra, hogy csinál helyben egy statikus Dictionary<string, IntPtr> -t, oda belehányja a stringeket meg a kódblokkokat és ugrótáblázik. Mindezt a fordító automatikusan, nem kell vele baszakodni külön. Ugyanígy egy halom dolgot is optimalizáltak a .NET2-3 környékén a felszín alatt: pl. ha nekiállsz egy valag stringet +-al összefűzni, akkor a háttérben sok esetben a String.Concat() vagy egy StringBuilder működik, ami nem fogja teleleakelni részstringekkel, hanem előre lefoglal akkorát, amekkora a végső string lesz. Java-ban meg itt is marad a (new StringBuilder()).append("a ").append("kecske ").append("bassza ").append("meg ").append("a ").append("Javat."). |
saxus (statz) | #9, Agyfasz (419) |
52 | #2a47 | ^ | Idézet | Mon, 27 Jan 2014 12:49:45 +01 |
86.101.*.* | *.business.broadband.hu |
Bocs, pontosítanék, nem a fordító, hanem a JIT-ter. |
saxus (statz) | #9, Agyfasz (419) |
72 | #2a48 | ^ | Idézet | Mon, 27 Jan 2014 12:50:55 +01 |
86.101.*.* | *.business.broadband.hu |
Meg az 5-6 switch-case-t is úgy értem, hogy 5-6 case után egy switchben. |
saxus (statz) | #9, Agyfasz (419) |
375 | #2a49 | ^ | Idézet | Mon, 27 Jan 2014 13:29:38 +01 |
86.101.*.* | *.business.broadband.hu |
Mondjuk hozzáteszem: soktízszeres sebességnövekedést ezzel nem fogsz elérni .NET alatt, maximum, ha nagyon sok stringet hasonlítasz össze. Mivel .NET-ben a string immutable és egy közös tárolóban van, gyakorlatilag csak egy pointer összehasonlítás az egész alapból, nem nézi az összes karaktert egyenként. |
TCH (statz) | #1, Főfasz (10443) |
1320 | #2a4a | ^ | Idézet | Mon, 27 Jan 2014 16:23:45 +01 |
31.46.*.* | *.catv.pool.telekom.hu |
Hallod, végre implementáltak valami hasznosat is. Jáva sux. Az is valami. Hidd el, értettem. :P Én általában beszéltem. Baromi sok ágú switch az baromi lassú. Egy idő után meglesz az a több 10x-es sebességkülönbség. Persze ha automatice átfordítja, akkor nem, dehát az ugyanaz az eset, mintha te csinálnád manuálisan. Erre még visszatérek, de rohannom kell. |
saxus (statz) | #9, Agyfasz (419) |
1357 | #2a4b | ^ | Idézet | Mon, 27 Jan 2014 16:38:12 +01 |
86.101.*.* | *.business.broadband.hu |
.NET-ben viszont sok általánosságra rágyúrtank, gyúrnak folyamatosan. Pl. ott vannak a LinQ-s extension methodok. Alapvetően mind az IEnumerable<T> típushoz csapódnak, viszont egy-egy gyakran használt generikus típushoz vannak néha a felszín alatt plusz optimalizációk. Pl. egy int[] -re a Sum()-nál a leggyorsabb még mindig a foreach-os megoldás és a sima alap Enumerátoron keresztüli megoldás jóval lassabb. Ott pl. AFAIK ki van optimalizálva, hogy ne az alap megoldást használja. Vagy amit már említettem a stringműveletekkel: .NET 1.1-ben tényleg kurva lassú volt (bár azt nagyon kevesen használtak sztem, a .NET 2-vel kezdett el igazán terjedni), .NET 2-3 környékén rendbetették. C#/.NET mögött amúgy ez a koncepció: nem egyvalamiben próbálnak nagyon jók lenni, hanem minél többmindenben próbálnak hozni egy legalább átlagos szintet (még ha ez időnként a sebesség rovására megy) és minél több igényt lefedni, és megtámogatva azzal, hogy minél gyorsabban tudj vele kódolni. Mert általában ez a szűk keresztmetszet és nem a gép. Ha meg valami extra igényed van (pl. még absztraktabb dolgot akarsz írni - F#, vagy nem jó a statikus típusosság - ld. IronPython, vagy tényleg kell az a plusz pár százalék sebességben - C/C++ plusz hozzá a C++/CLR ragasztónak), akkor meg megvan a lehetőséged. |
TCH (statz) | #1, Főfasz (10443) |
534 | #2a4c | ^ | Idézet | Mon, 27 Jan 2014 21:18:54 +01 |
31.46.*.* | *.catv.pool.telekom.hu |
De most általánosságban az elméletről volt szó, hogy switch vs. ugrótábla. Amúgy meg ne hittéríts, megint itt vagy két posztnyi idő óta és már megy a rizsa, hogy mikrofos rulez. :P Egyébként, ha ilyen kurwa jól optimalizált a dotnet, akkor miért olyan kurwa lassú az egész? Azt mégis hogy, hogy csak egy pointer összehasonlítás a két string összehasonlítása? Nem csak előre definiált stringek vannak, egy valahonann beolvasott stringet hogy hasonlít össze csak egy pointerrel? Meg mi van, ha két egyforma stringünk is van? |
saxus (statz) | #9, Agyfasz (419) |
1175 | #2a4d | ^ | Idézet | Mon, 27 Jan 2014 23:27:15 +01 |
84.3.*.* | *.catv.pool.telekom.hu |
" akkor miért olyan kurwa lassú az egész?" Nekem nem lassú. (WPF meg egyenesen kurvagyors, főleg a régi megoldásokhoz képest. Mondjuk meg is van támogatva Direct2D-vel). "Azt mégis hogy, hogy csak egy pointer összehasonlítás a két string összehasonlítása? Nem csak előre definiált stringek vannak, egy valahonann beolvasott stringet hogy hasonlít össze csak egy pointerrel? Meg mi van, ha két egyforma stringünk is van?" Nem. .NET-ben minden string immutable, emiatt meg lehetett csinálni, hogy minden string - CLR-enként, tehát akár alkalmazások között - egy közös tárolóba "internáld". Viszont pontosítanom kell magam: nem mindent internál automatikusan. Most nem katpam elő a CLR via C#-ot, de gyors utánanézés alapján nekem úgy tűnik, hogy azokat, amik viszont fordítási időben bekerülnek a rendszerbe, azokat már igen, szóval az előbbi állításom nem minden esetben állja meg a helyét. Viszont két internált stringet összehasonlítani meg tényleg lehet referencia szerint (maga a == operátor illetve az Equals() felüldefiniálására is az az ajánlás, hogy a legelején nézd meg az object.ReferenceEquals()-al.) De persze, te is tudsz kézzel. |
kemi (statz) | #2, Főfasz (2970) |
508 | #2a4e | ^ | Idézet | Mon, 27 Jan 2014 23:34:54 +01 |
92.249.*.* | *.pool.digikabel.hu |
Lehetnek ott negatív, meg 255-nél nagyobb értékek is, és ha ezt képen akarod megjeleníteni, akkor vágni kell a 0-255 tartományra. Az utóbbit megcsinálja, ha az intet charba castolod, de az úgy túl fog csordulni, és nem lesz "szép" a képen. A javaslatod majd kipróbálom, ha lesz rá időm. |
TCH (statz) | #1, Főfasz (10443) |
1686 | #2a4f | ^ | Idézet | Tue, 28 Jan 2014 00:37:40 +01 |
31.46.*.* | *.catv.pool.telekom.hu |
Bezzeg amikor a monguzok aszongyák, hogy wörxformi, akkor kapják be. Értem, tehát két belefordított statikus konstans sztring között tud ilyet, ez így már működhet, csak az értelmét nem látom, hiszen mi értelme van annak, hogy 'kecske' == 'macska', vagy 'kecske' == 'kecske', amikor ezt elméletileg nem is lenne szabad úgy lefordítania, hogy belerakja a komparátort, simán false és true kéne, hogy beleforduljon. Ja értem. Akkor marad a másik kettő. Szerintem a két if eltakarítása kéne, hogy a leggyorsabb verzió legyen, a második csak egy if-et takarít el, azt is csak félig. De itt egy harmadik javaslat, ez fixen kiiktatja az egyik if-et. int sel[2] = {0, 255}; if (p < 0 || p > 255) { p = sel[p < 0]; }Vagy ugyanez fordítva. const signbit = (sizeof(int) << 3) - 1; int sel[2] = {255, 0}; if (p < 0 || p > 255)
{
p = sel[p >> signbit]; // lehet shr gyorsabb, mint cmp
} |