Desu
2018-11-05 21:37

Po złożeniu zamówienia na Uber Eats, jak zwykle zostałem przekierowany na listę moich zamówień, gdzie zazwyczaj mogę sprawdzić, czy zamówienie zostało przyjęte przez lokal. Czekam.. 10, 20, 30 sekund i nic. Loader jak był tak jest. Trochę z niecierpliwości, a trochę odruchowo otworzyłem DevToolsy, a tam stos błędów w stylu undefined is not a function, can not access property dupa of undefined itp.

Eh... Dobrze, że mogłem sobie puknąć do API i śledzić status swojego zamówienia wygrzebując go z json'a :D Mina kolegi (nie deva), który na pytanie co robię, dostał odpowiedź, że śledzę status naszego zamówienia - bezcenna.

Inclouds

Oo, widzę, że wcale nie jestem oryginalny ze swoimi nazwami testowych zmiennych :D

grski

@Inclouds bynajmniej, dupa debugging to bardzo popularna technika programistyczna stosowana przez specjalistów najwyżśzego szczebla i najlepszego sortu

cerrato

A czy macie jakiś system nazywania zmiennych sterujących pętli FOR? Ja zawsze (jeśli jedynym celem takiej zmiennej jest "przelecenie" przez FORA i tylko po to została stworzona) nazywam ją "ster". Taki zwyczaj od ponad 20 lat :D

slayer9

Nie używam pętli for 😁

cerrato

@slayer9: dowiedz się może od swojego nauczyciela, kiedy będziecie ten typ pętli przerabiać na lekcjach ;)

Progress

Ja stosuje 'a', 'b' itd. 'dupa' to za dużo pisania ;) a for'a używam bardzo rzadko i jak już to zawsze nazywam zmienną standardowo 'i' i w sumie zdziwiłbym się gdyby zobaczył tam jakąś inna nazwę

slayer9

Takimi sucharami to może przed kumplami błyśniesz.

scibi92

@cerrato: a może kolega @slayer9 jest nowoczesny i używa paradygmadu funkcyjnego który ma tylko 70 lat? Ja tez fora nie używam juz praktycznie :D

slayer9

Widocznie strumienie dopiero przed cerrato, stąd to nieporozumienie.

scibi92

Ja obstawiam że nie programuje w Javie :P

scibi92

poza tym pod względem możliwości wywalenia fora imperatywnego to niesty Java była dosyć daleko w tyle w porównaniu do np. Scalii, C# ( z tego co wiem od @somekind), Pythona pewno też

cerrato

Tak całkowicie poważnie - FOR może jest jedną z prostszych konstrukcji, ale często się przydaje. Oczywiście - można stosować różne alternatywy, ale to jak w wypadku malowania ściany w pokoju - większość osób weźmie wałek i pomaluje, aczkolwiek można jechać do firmy wynajmującej sprzęt budowlany i wypożyczyć kompresor z pistoletem. Tylko czy to ma sens? Tak samo z FOR - skoro wykonuje to, co jest potrzebne, to po co kombinować i udziwniać?

Desu

@cerrato: pętla for nie jest prosta, może jest Ci znajoma, ale nie jest prosta.

somekind

@cerrato - dla czytelności i skrócenia zapisu. Wiele rzeczy, które są rozwiązywane pętlą da się rozwiązać ładniejszymi konstrukcjami w znacznie zwięźlejszy sposób. A ster? Dziwaczna nazwa, nie widziałem jeszcze nigdy, żeby nie uzywać i w tym celu.

cerrato

No to mamy pewną rozbieżność. Dla mnie to jedna z prostszych konstrukcji: "przeleć po kolei numerki od 7 do 45 i dla każdego z nich zrób coś, co jest podane poniżej". Czy możesz jakoś uzasadnić (pytam z ciekawości, nie żeby się kłócić, czy Cię atakować) dlaczego uważasz, że FOR nie jest prosty?

scibi92

a ja mogę zrobić w list.forEach(this::doSomething) i jak dla mnie jest to o wiele lepsze niż for (O o: Type) { doSomething(o);}

cerrato

@somekind: no właśnie to i jest takie za bardzo mainstreamowe ;) Ten ster jest ze mną od czasów końca podstawówki i tak zostanie chyba już do końca. Dobrze nam razem :D

Desu

@cerrato: tutaj masz odpowiedź https://youtu.be/nVZE53IYi4w?t=1038. Obejrzyj sobie od mniej więcej 18, do 24 minuty, jak nie masz czasu na całość ;)

MasterBLB

ja pisząc w C++ przyzwyczaiłem się używać w pętli for(;;) nazwy cnt dla zmiennej licznika. No to patrz @somekind, już zobaczyłeś :P

cerrato

@scibi92: jest to OK, ale czy lepsze... kwestia gustu.

scibi92

@cerrato: bo to bardzo prymitywny przykład. To co @Desu przesłał wyjasnia wszystko

MasterBLB

Przykład Desu obejrzę po pracy, natomiast co do Twojego @scibi92 to jakoś nie dostrzegam miażdżącej przewagi konstrukcji list.forEach(this::doSomething) nad pętlą for, przynajmniej patrząc z perspektywy C++. Widząc takie coś w nieznanym mi kodzie muszę sprawdzić co dzieje się w metodzie forEach(jakaśLambda?) bo tu znów nie ma gwarancji, czy faktycznie robi to, co sugeruje.
zapisując to w postaci for (int cnt = 0; cnt < list.size(); cnt++0{ this::doSomething(); } na pierwszy rzut oka widać:

  • jest to pętla
  • o określonej ilości przebiegów
  • w każdym przebiegu zrobi this::doSomething
somekind

Metoda forEach nigdy żadnej przewagi nad pętlą nie będzie miała, bo to wciąz imperatywny kod, którego jedynym celem jest mutowanie stanu.ja pisałem o skracaniu kodu w sytuacji, gdy daną kolekcję potrzebujemy odfiltrować, posortować, przekształcić elementy na inne typy albo wywołać jakąś funkcję agregującą.

cerrato

Ale to już zależy od konkretnego zadania. Są miejsca, gdzie trzeba zrobić coś więcej, ale nieraz potrzebne jest proste przelecenie czegoś po kolei. A jeśli do takich zadań FOR się nadaje idealnie, to nie wiem, czemu z niego nie korzystać. Dlatego też nie rozumiem ludzi, którzy kategorycznie stwierdzają, że FOR nie stosują. Jeśli do danego rozwiązania pasuje, to niech będzie.

scibi92

No to był tylko przykład. To akurat nie ma miażdzącej przewagi, ale wyobraź sobie np. coś takiego Collection<string> toUpperCase(Collection<string> strings) {
return strings.stream()
.map(String::toUpperCase)
.collect(ImmutableList.toImmutableList());
}

Fora mamy zastąpionego mapem. O wiele czytelniejsze

scibi92

Zwykłego fora używałem ostatnio tylko jak bawiłem się w implementacje algorytmów sortowania itd. , nie przypominam sobie żebym go używał w pracy od kiedy znam streamy i lambdy

Desu

Ja fora ostatnio użyłem na kolokwium z podstaw programowania, ponieważ w treści zadania było napisane, że musi być for :P

scibi92

@cerrato: żeby było jasne, nie używam fora nie z powodów żeby był cool tylko dlatego funkcyjna alternatywa jest czytelniejsza, oczywiście w granicach zdrowego rozsądku. Jak mamy aplikacje biznesowe rzadko robimy fora żeby tylko coś printowac, częściej to mapowanie, sumowanie filtrowanie itp. co łatwiej jest zrobić w stylu funkcyjnym :)

cerrato

No faktem jest, że for jest raczej rzadko używany. Ale w sumie, jakby spojrzeć z 40 komentarzy wcześniej, nie pisałem nigdzie że for to podstawa programowania, a jedynie zapytałem "czy macie jakiś system nazywania zmiennych sterujących pętli FOR?". Tak mi się skojarzyło ze słynnym dupa debugging i tyle, nie chodziło o nic więcej ;)

scibi92

No w algorytmach to stosuje i,j itd. Tyle że w pracy nie implementuje merge sorta :D

MasterBLB

Zapisując tasiemca Brata scibiego w postaci strawnej wychodzi takie coś:
Collection<string> toUpperCase(Collection<string> strings)
{
return strings.stream().map(String::toUpperCase).collect(ImmutableList.toImmutableList());
}
no faktycznie, prostsze i czytelniejsze że hoho niż:
void toUpper(Collection<string> &strings)
{
for (string &s : strings)
{
s = s.toUpper();
}
}
a dla purystów czepiających się modyfikowaniu przesłanej kolekcji wersja:
Collection<string> toUpper(const Collection<string> &strings)
{
Collection<string> uppercasedCollection;

 for (string &s : strings)
 {
      uppercasedCollection.append(s.toUpper());
 }

 return uppercasedCollection;

}
Panowie, konstrukcje złożone nigdy nie będą prostsze od mnemoników języka programowania. No nie ma po prostu opcji.

MasterBLB

Ach,ten przykład scibi'ego i desu jest z C#. A to w tej materii to się nie wypowiem, może takie konstrukcje faktycznie są tam preferowane.

Akihito

@somekind: ma rację np nie idzie usunąć całej kolekcji w pętli foreach do tego potrzebny jest już for ;)

Spine

@Akihito:
Całą kolekcję łatwo bez for i bez foreach: https://docs.oracle.com/javas[...]i/java/util/List.html#clear--
Pojedyncze elementy spełniające jakiś warunek kasujemy w pętli for od tyłu.
Pojedyncze elementy, do których mamy referencję można kasować tak: https://docs.oracle.com/javas[...]html#remove-java.lang.Object-
Pojedyncze elementy, do których mamy indeks kasujemy tak: https://docs.oracle.com/javas[...]va/util/List.html#remove-int-

scibi92

W sumie forEeacha używałem do mutowania tylko że mutowałem ConcurrentMap (przekazywałem liczbę której częstośc miałem zliczyć). Nie było to funkcyjne ;]

somekind

Tylko po co kasować, od tego jest GC. @scibi92: dlatego ja zamiast używać jakiejś metody forEach wolę napisać zwykłą pętlę. Wtedy z daleka widać, że tu jest mutowanie albo efekt uboczny, więc np. debugowanie warto zacząć w tym miejscu. Wpychanie takich operacji w jakieś łańcuchy lambd zmniejsza tylko czytelność.

Pijak

Zdelegalizować fory i po problemie.

scibi92

@somekind niby tak, ale to było na końcu pewnych operacji:
Files.lines(file)
.map(this::splitLine)
.flatMap(Stream::of)
.map(String::trim)
.filter(StringUtils::isNumeric)
.map(Integer::parseInt)
.forEach(this::updateCounter);

MasterBLB

@scibi92: czyli zrobienie jeszcze większego wieżowca wywołań metod na kolejnych obiektach tymczasowych jest bardziej czytelne niż prosty for()? Ciekawie wy w tej Javie piszecie...

cerrato

@scibi92: ja już się trochę pogubiłem... czy to, co dałeś 2 komentarze wcześniej ma być argumentem za tym, że inne rzeczy są bardziej czytelne niż for/foreach? Bo dla mnie to wygląda totalnie nieintuicyjnie i jest całkowitym zaprzeczeniem prostoty pętli FOR, gdzie na pierwszy rzut oka wiesz co i ile razy się wykona.

danek

Czytelność to w dużej mierze przyzwyczajenie

cerrato

wiadomo, że można jeździć Matizem albo kadetem bez wspomagania i ABS i jak człowiek się przyzwyczai, to nawet w miarę ta jazda wychodzi, ale nie zmienia to faktu, że są wygodniejsze auta. Tak samo z "przyzwyczajeniem" - przyzwyczając sie do czegoś "dziwnego" nie powoduje się, że to coś jest mniej dziwne, ale raczej się obniża własny próg bólu.

danek

@cerrato: To zapisz w forze to co napisał @scibi92. Z tego co rozumiem to na wejsciu jest lista Stringów, która następnie jest cięta (załóżmy ze po spacjach), następnie odrzucone wszystkie nie liczby i na koniec niech będzie żeby podać sumę tych licz (nie dokładnie to samo co kod wyżej ale sens podobny)

cerrato

@danek: masz rację, ciężko będzie to ogarnąć w jakiś zgrabny sposób w FOR (oczywiście - wszystko jest do zrobienia, ale wymagałoby to trochę gimnastyki). Mi chodziło o coś innego - wcześniej @scibi92 wspominał o czytelności. Podany przez niego przykład, może jest zwięzły i poprawnie działający, ale raczej nie jest czytelny (jak to ładnie napisał @MasterBLB - taki wieżowiec wywołań).

scibi92

To jest coś czego trzeba się nauczyć, ale jak już człowiek się nauczy to dla niego jest o wiele prostsze. Korzystanie np. z polimofrfizmu zamiast swtich tez może być na poczatku trudne jeśli ktos pisał proceduralnie. Chociaż zaznaczam że ten kod co wkleiłem jest nie w pełni funkcyjny - ostatnia linia modyfikuje instancje ConcurrentMap. Najpierw czytam po kolei linijjki z pliku, poźniej tworze tablice Stringów(rozdzielam na podstawie regexa), później przekazuje dalej pojedyńcze Stringi, dalej filtrruje te ktore sa liczbą, poźniej robie z nich liczby a poźniej aktualizuje mapę częstości.

scibi92

@cerrato: nie jest bo tak nie programujesz na codzień. Dla programisty Java który ma elementarną wiedze odnośnie Stream API to jest bułka z masłem :)

cerrato

@scibi92: tutaj muszę przyznać Ci rację - Java to dla mnie totalnie obcy temat. więc zakładam że masz rację i każdy javowiec patrząc na to od razu wie o co chodzi. Ale zamiast tego mam argument nie do obalenia: to jest brzydkie ;) :D

scibi92

No cóż, dla mnie to akutat jest bardzo piękne ;p Chociaż przyznam że na początku to tez było dla mnie trudne do ogarnięcia ;)

somekind

@scibi92: ja bym to zapisał tak:
var numbers = Files.lines(file)
.map(this::splitLine)
.flatMap(Stream::of)
.map(String::trim)
.filter(StringUtils::isNumeric)
.map(Integer::parseInt);
a potem:
foreach (var n in numbers)
this.updateCounter(n);

Właśnie po to, aby oddzielić "pobranie danych" od "modyfikacji danych". Pobranie bym zresztą pewnie wydzielił do oddzielnej metody. @cerrato - równoważnikiem tego będą zagnieżdżone pętle z zagnieżdżonymi ifami i kupa klamerek. A tu masz po prostu sekwencję wywołanych po kolei operacji - żadnych rozpraszaczy: skoków, gubienia kontekstu, analizowania co jest w ifie, a co poza nim, itp. Brak ifa jest zawsze ładniejszy niż jego istnienie.

Merylin

imperatywni ludzie ¯_(ツ)_/¯, @cerrato, @MasterBLB, jak dla was ten wiezowiec ktory pokazal @scibi92 jest nieintuicyjny i generalnie bleee, to czekam na wasza implementacje tych operacji w waszym forze;)

cerrato

@Merylin: a nie uważasz, że to, co napisał somekind jest lepsze?

Merylin

@cerrato: a nie uwazasz, ze to, co napisal somekind to jest praktycznie to samo? po prostu rozdzielil ostatnia linijke jako oddzielny blok logiczny?

cerrato

Powiem tak - to nie jest mój język, może osoby które w tym siedzą cały czas maja inne podejście, ale moim zdaniem ta wersja jest bardziej czytelna i zrozumiała.

Merylin

@cerrato: a napiszesz wersje w forze w twoim jezyku?^^

cerrato

Nie napisze, zresztą jakieś 10 komentarzy wcześniej napisałem, że zrobienie tego samego w ramach pętli FOR wymagałoby trochę gimnastyki. Wiadomo, że dobór odpowiedniego narzędzia do zadania jest ważny.

MasterBLB

@Merylin: niby to samo, ale wyraźny rozdział na operacje zebrania danych i wykonania swojej operacji na otrzymanym zbiorze powoduje, że czytelność kodu jest nieporównywalnie większa. Nie stosując zapisu "wieżowego"
var numbers = Files.lines(file).map(this::splitLine).flatMap(Stream::of).map(String::trim).filter(StringUtils::isNumeric).map(Integer::parseInt);
foreach (var n in numbers)
this.updateCounter(n);
bardzo łatwo się takie coś odczytuje bez konieczności analizy wszystkich pięter wieżowca:
skoro widzę "var numbers = " to chu mu w du skąd się ten zbiór danych wziął, skoro się skompilowało to znaczy, że się go dostało, ewentualnie jest pusty
foreach (var in numbers)//poniżej od razu widzę do czego ten zbiór jest użyty. Poza tym użycie słowa kluczowego (? o ile w Java foreach macie, ale przyjmijmy, że tak) bez cienia wątpliwości pokazuje, co będzie wykonane.
this.updateCounter(n);
A jeśli somekind faktycznie by wydzielił pobieranie zbioru danych do oddzielnej funkcji to wówczas kompletnie by zwyciężył na polu wyrazistości i jasności kodu nad przykładem scibi'ego:
var numbers = getCollectionForUppercase();//nazwa funkcji nie najszczęśliwsza, ale autor z pewnością dobrałby odpowiednią
foreach (var in numbers)
this.updateCounter(n);

Więc ja z @cerrato twierdzimy jedynie, że twierdzenie o braku czytelności for-ów jest mocno nietrafione.

somekind

@MasterBLB: ten mój kod to bardziej taki pseudokod, bo połączyłem funkcje z Javy z pętlą foreach z C# (nie chciało mi się przerabiać oryginału, chodziło tylko o ideę).

MasterBLB

@somekind no ja się domyślam, ale doskonale obrazuje jak prostą zmianą drastycznie zwiększyć czytelność.

somekind

Dzięki za uznanie. :)

scibi92

@cerrato: ja to akurat zrobiłem ze względów wydajnościowych tzn operacowałem na kilkudziesieciu tysiącach liczb (o ile dobrze pamiętam 20k) w projekcie ćwiczeniowym (wielowątkowość) a nie projekcie nad którym ktoś mógł by pracowac. Generalnie wiadomo ze read of update powinny być osobne

scibi92

Chociaż w sumie @somekind dał mi pomysł na użycie pewnego innego mechanizmu z java.util.concurrent do zabawy ;]

somekind

Nie powiedziałbym, że z czymś takim: throws IOException cokolwiek jest lepiej.

scibi92

Niestety usunąłem komtentarz, ale masz racje throws IOException nie jest ładne. Niestety tzw. checkedExceptiony to jedno z największych wad Javy...

scibi92

Teraz główna metoda wygląda tak:
public void run() {
try {
Collection<integer> numbers = readNumbers();
updateBarrier.await();
updateCounter(numbers);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
countDownLatch.countDown();
}
}
To przerzucanie wyjątków nie jest łądne, ale co zrobić ktos tak ch*jowo zaprojektował język :/

jarekr000000

Wracając do poprzedniej części dyskusji to przejście na list.forEach( myFun) z prostackiego for ( var v in list) { myFun(v) } ma też głębsze uzasadnienie. Eleminujemy jeden byt z przestrzeni nazw - mało interesującą zmienną. Z której nazewnictwem zresztą są zwykle kłopoty (bo tak naprawdę nam zwisa). Sens tego widać jak się konsekwentnie takie eliminacje robi. Jest to droga do point-free style . Dopiero po tej abstrakcji widać kolejne poziomy na których można uprościć kod (bo np. mamy powtarzalne serie operatorów) . Przykład: prawie każdy fukcyjny programista szaleje po kodzie foldami, które w stylu imperatywnym prawie się nie pojawiają. Mimo, że mają nadal sens. Po prostu bez przejsćia na point free nie widać wyraźnie, że mamy akurat miejsce na folda (albo, że mamy monoid i jest jeszcze lepiej ).

cerrato

@jarekr000000: "mało interesującą zmienną. Z której nazewnictwem zresztą są zwykle kłopoty" - właśnie od tego się zaczęła cała dyskusja, zapytałem czy macie jakiś szczególną nazwę dla zmiennych sterujących pętli (w domyśle - zmiennej, która niczego nie robi poza sterowaniem FOR'em) :D

scibi92

W sumie od kiedy znam Grooviego i Kotlina to pewno nazwałbym ją it xD

somekind

Ja tam jestem zdania iż udawanie, że pisze się w innym języku niż się faktycznie pisze nie ma większego sensu.

somekind

To fakt, teraz jest znacznie więcej możliwości pisania słabego kodu niż kiedyś.

WeiXiao

@somekind: No nie wiem. Teraz to IDE krzyczy Ci o prawie wszystko co się da, a nawet proponuje refaktor na 10 sposobów..

somekind

Także te refaktory, które mogą nie tylko pogorszyć czytelność kodu, ale i go w ogóle zepsuć. No i pokaż mi IDE, które pokazuje złamanie SRP albo OCP.

danek

@somekind: a zdefiniuj dobrze SRP albo OCP ;)

WeiXiao

@somekind: które mogą nie tylko pogorszyć czytelność kodu, ale i go w ogóle zepsuć. z czego korzystałeś?

somekind

@danek: no właśnie o to chodzi. :) IDE może pokazać błędy gramatyczne, ale nie semantyczne ani merytoryczne.

WeiXiao

@somekind: no ta, bo przecież nawet w Visualu nie masz narzędzi, które potrafią stwierdzić, że robisz coś źle! :D np. deep nesting

somekind

A co ma deep nesting to SRP?

WeiXiao

@somekind: Już pomijając, że SRP/OCP to nie jedyne rzeczy w kodzie, które można zepsuć, to występowanie deep nestingu (ify, forki, switche 5 pięter w bok) jest silną sugestią, że własnię SRP jest łamane. Nie musi, ale prawdopodobnie.

jarekr000000

@somekind ja tam uważam za kiepski pomysł pisanie w języku tak jak to sobie wymyślili jego twórcy. Bo np. było to 20 lat temu i świat poszedł troszkę do przodu. Szkoda mi czasu. Chociaż czasem spotykam programistów tradycjonalistów i mamy jakieś spięcia (ale raczej kontrolowane).

scibi92

@jarekr000000: no to akurat jest częsty problem wśród dżawowcow. Ja miałem spięcie bo zaproponowałem VAVRa, konkretnie chodziło o użycie Either. Team leader powiedział że Java to nie Scala i to był jego argument...

somekind

@WeiXiao: nie widzę jakoś powiązania deep nestingu z SRP, to po prostu brak podziału na odpowiednie metody, a nie klasy. Deep nesting to jest kosmetyka - bo IDE potrafią znaleźć jedynie problemy kosmetyczne, a nie na poziomie designu czy w ogóle sensu implementacji danego ficzera w dany sposób. @jarekr000000: ja z kolei wystrzegam się fashion driven development i robienia czegokolwiek tylko dlatego, że teraz tak jest modnie. Kiedyś modne było konfigurowaniem IoC przez XML, teraz najwyraźniej udawanie, że jak dodasz parę metod do języka, to nagle mu się paradygmat zmieni. Opisywana tutaj zmiana nie czyni jakiejś wielkiej rewolucji ani w czytelności ani w utrzymywalności kodu, co najwyżej poprawi samopoczucie tym, którzy chcieliby w Haskellu, ale mają tylko Javę.

scibi92

@somekind: gdyby twórcy Javy nie chieli żeby ludzie pisali funkcyjnie, nie daliby wsparcia w postarci wyrażeń lambda

somekind

Czy wsparcie dla lambd czyni Javę językiem funkcyjnym?

scibi92

Nie, ale daje sygnał że może być konstrukcją mieszaną. Optional to tez jest konstrukt funkcyjny. Streamy generalnie też, więc Java ma już dodanych "sporo" elementów z FP.

somekind

No i właśnie - to są tylko elementy FP, z których można efektywnie korzystać. Ale to nie powód, żeby udawać, że cały paradygmat się zmienił i pisać w taki sposób, nawet jeśli nie daje to żadnego zysku.

scibi92

Paradygmad się częściowo zmienił i to jest fakt. Był "obiektowy" teraz jest "obiektowo-funkcyjny" (w uproszczeniu). Nie zauważyłem żebym stosował kod funkcyjny w sposób nadmiarowy

somekind

A pseudo funkcyjny kod mutujący stan, to co to niby jest? :)

scibi92

Tak się składa że
1)nie mutował stanu kolekcji po której szedłem
2)był to kod z projektu do tzw. półki co zresztą opisałem. Normalnie tak bym nie napisał.

MasterBLB

@somekind: "(...)fashion driven development i robienia czegokolwiek tylko dlatego, że teraz tak jest modnie(...)" o toto, +milion.

WeiXiao

@MasterBLB: no tak, bo przecież to musi tylko i wyłącznie chodzić o "mode", bo fakt, że w większości przypadków podejście funkcyjno-ish jest lepsze ze względu na krótszy kod jest nieistotne? @somekind: zamiast linq też nawalasz loopy? no nie, bo najważniejszy jest krótki i czytelny kod poza pewnymi wyjątkami.

MasterBLB

Skoro najważniejsza jest prostota i krótkość zapisu, to czemu wszyscy programiści jeszcze nie przesiedli się na brainfucka? :] A tak na poważnie Bracie @WeiXiao, na to nie ma jednoznacznej i prawdziwej w każdych warunkach odpowiedzi. Wracając do wieżowca wywołań scibiego w wersji z forEach() mimo, że sam zapis był krótki to tak naprawdę zmuszał żeby wleźć przynajmniej do forEach() aby sprawdzić, co tam się wyprawia - co wymusiłoby przeskok w inne miejsce kodu, zaburzając płynność czytania. Sytuację uratował @somekind przez proste wprowadzenie var collection = <rezultat wywołań wieżowca> i potem pętli foreach na collection wybitnie uprościł całą funkcję. Btw, strony książki też chyba wygodniej się czyta sekwencyjnie, a w ostateczności jeśli przypisy/objaśnienia są u dołu strony niż kiedy są umieszczone na końcu książki, i ciągle trzeba skakać w te i nazad, zgadza się?

scibi92

@MasterBLB: czyli rozumiem że nie dzielisz publicznych metod na prywatne mniejsze bo to zaburza czytelnośc i musisz skakać ? :D

WeiXiao

@MasterBLB: to czemu wszyscy programiści jeszcze nie przesiedli się na brainfucka? napisałem :) bo najważniejszy jest krótki i czytelny kod a brainfuck nie spełnia drugiego wymagania. Wracając do wieżowca wywołań scibiego w wersji Ja pisałem bardziej o ogólnym stosowaniu "fukcyjnego" podejścia niż do w/w przypadku. Bez wątpienia i funkcyjnym podejściem można pisać nieczytelny kod, ale to powiedz mi jakbyś zamienił forEach(funkcja) na taki aby nie wymagał skoku do funkcji? no bo np. foreach (something in collectionOfsomething) { function(something) } też wymaga skoku. Bo jeżeli ta funkcja jest dłuższa, to i tak raczej chcesz ją wydzielić, a jeżeli jest "wystarczająco" krótka, to raczej wejdzie w forEach

MasterBLB

@scibi92: różnie z tym bywa. Generalnie w C++ mamy rozdzieloną deklarację klasy i jej metod od definicji która jest umieszczona w pliku .cpp, więc nie ma też takiego parcia do dzielenia metod na mniejsze. @WeiXiao jak już wspomniałem, nie ma na to jednoznacznej w każdych warunkach odpowiedzi. W przykładzie scibi'ego poprawionym przez somekinda lepiej się sprawił zapis somekinda niż funkcyjny. W Twoim co tu przytaczasz podejście czysto funkcyjne może istotnie być lepsze.