Czy stosowanie pętli for to obciach?

Czy stosowanie pętli for to obciach?

Wątek przeniesiony 2022-12-16 09:55 z Nietuzinkowe tematy przez Riddle.

K8
K8
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 2 lata
  • Postów:791
0

Załóżmy, że mam tablicę i chcę wykonać pewne operacje na niej. Czyli muszę przeiterować po każdym elemencie.
Można to zrobić na kilka sposobów. Klasyczną pętlą for, albo map() lub forEach().

Spotkałem się ze stwierdzeniem, że for stosuje się "w przedszkolu". Natomiast "profesjonalne" podejście to kod typu myArray.filter().map()...

Co o tym sądzicie?

markone_dev
for stosuje się "w przedszkolu". Natomiast "profesjonalne" podejście to kod typu o chui xD. Gdzie tak piszą albo mówią, żeby unikać tych miejsc.
K8
kosmonauta80
Tak powiedział mi facet z branży (starszy gość).
markone_dev
Ja też jestem starszym gościem z branży :D Chodzi mi o to gdzie? W pracy, szkole, na uczelni, konferencji?
K8
kosmonauta80
Uczelnia. Facet na oko 55 lat.
markone_dev
Jak wykładowca to polecam go olać. Jeśli to kolega, który w wieku 55 lat postanowił zrobić inżynierkę z infy to unikać miejsca gdzie pracuje a najlepiej to podać to do informacji publicznej, żeby inni również unikali tego miejsca.
LukeJL
ojej, znowu. Już ktoś coś takiego pisał kiedyś, że usłyszał od wykładowcy, jakoby żaden profesjonalny profesjonalista nie używał break :D zdradzę ci sekret - niektórzy po prostu chcą się dowartościować rzucając takie teksty.
K8
kosmonauta80
Ale jak kto, facet pracuje w SCRUMie. Nie może się mylić. Jest pr0.
Paweł Biernacki
Słyszałem, że ma wyjść encyklika "Contra for", w której używanie "for" będzie napiętnowane jako grzech śmiertelny. Ja używam "for", ale ja mam dopiero 49 lat ;)))
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 5 godzin
  • Postów:812
4

Nie wiem jak w innych języka ale w C# z tego co pamiętam to kompilator generuje taki sam kod wynikowy zarówno dla for jak i foreach więc w C# różnicy w wydajności bym się nie spodziewał, ale może ktoś potwierdzi/zaprzeczy. W innych językach może być inaczej.

Ja używam foreach gdzie się da, zwłaszcza, że dużo operuję na kolekcjach, bo jest dla mnie czytelniejszy niż for a jeśli chodzi o lukier składniowy to najbardziej w C# lubię LINQ i jego ForEach, zamiast tradycyjnego foreacha, ale nie w każdej sytuacji da się go użyć bez rzutowania na listę.


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
edytowany 3x, ostatnio: markone_dev
WeiXiao
LINQ i jego ForEach, zamiast tradycyjnego foreacha, ale nie w każdej sytuacji da się go użyć bez rzutowania na listę. bo ForEach nie jest LINQowy :)
core1983
Skeet pisał o tym na SO, nawet dzisiaj widziałem tego posta ;-)
somekind
foreach to while, a nie for.
F9
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 3 godziny
  • Postów:76
2

Wszystko zależy od języka, każde narzędzie przydaje się do czegoś innego. Jak robisz operacje na wszystkich elementach to robisz foreach. Jak na części to jakiś filtr a potem foreach. Jak piszesz jakiś algorytm i musisz robić przy okazji jakieś magiczne ruchy to for. Nie uważam aby stosowanie for było błędem :d ale po to są takie narzedzia jako foreach aby kod był po prostu czytelniejszy.

K8
K8
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 2 lata
  • Postów:791
0

Chcę przeiterować elementy od końca. Wydaje się, że for będzie najlepszy:

  • mogę deklarować krok
  • mogę deklarować od którego elementu
  • mogę deklarować kierunek

Inaczej potrzebne są jakieś kombinacje typu (używając JS) myString.split().reverse().join()

edytowany 2x, ostatnio: kosmonauta80
Xarviel
Kombinacja myArray.split().reverse().join() jest błędna ponieważ tablice nie mają metody split.
K8
kosmonauta80
Wiem. Jak by co poprawiłem na myString.
kzkzg
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
  • Postów:925
2
markone_dev napisał(a):

Nie wiem jak w innych języka ale w C# z tego co pamiętam to kompilator generuje taki sam kod wynikowy zarówno dla for jak i foreach więc w C# różnicy w wydajności bym się nie spodziewał, ale może ktoś potwierdzi/zaprzeczy. W innych językach może być inaczej.


Keep calm and blame frontend.
Tell your cat I said pspsps.
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:2 minuty
  • Postów:8406
7

Zależy od języka i preferencji danego programisty. Oraz jaki mamy cel, po co chcemy iterować.

W JS:
jeśli chcę przejechać przez elementy tablicy, to robię zwykle .forEach:

Kopiuj
someArray.forEach(el => { console.log(el); });

jest to bardziej "skrótowe" niż pętla for i niektórzy się tym zachwycili i zaczęli rzucać teksty "nie używam już pętli for".

Tylko, że to krótkowzroczne myślenie. Pętla for pozwala na większą elastyczność. Np. iterację od tyłu (przydatne przy usuwaniu elementów). Albo dowolną iterację, nie tylko po tablicach. Również za pomocą for można przerwać iterację w trakcie, co też bywa zaletą. Np. jeśli element znaleziony, to nie musisz dalej przeszukiwać...

...ale z kolei do szukania elementów dodano metody find, findIndex , findLast, findLastIndex.

Dalej. Jeśli chcemy zamienić jedną tablicę w drugą, to mamy od tego map, które całkiem wygodnie pozwala na takie rzeczy.

myArray.filter().map()...

Taki kod również jest przydatny - najpierw przefiltrować tablicę i potem przemapować.
(jednak to, że tak można zrobić w pewnych przypadkach nie kasuje przydatności pętli for czy innych sposobów iteracji).

Dalej mamy reduce, które też jest przydatne jeśli chcemy zrobić z wielu elementów jeden (np. policzyć sumę elementów).
Natomiast ponieważ reduce jest dość elastycznym sposobem iteracji, to ludzie zaczęli tego nadużywać. W szczególności zobaczysz kody, które mutują pierwszy argument - np. dodają coś do obiektu, to częsty pattern:

Kopiuj
 someArray.reduce((acc, v, i) => { acc[v] = i; return acc }, {})

chociaż to hak i używanie czegoś niezgodnie z przeznaczeniem (bo reduce kojarzy się z programowaniem funkcyjnym, więc mutacja trochę nie bardzo pasuje). Chociaż nie jestem radykałem, sam tak robiłem. Nawiasem mówiąc powyższy przykład z reduce można i tak zapisać krócej używając Object.fromEntries:

Kopiuj
 Object.fromEntries(someArray.map((v,i) => [v,i]))

Jeśli chcemy utworzyć obiekt na podstawie tablicy.

W innych przypadkach użycie reduce można przepisać np. do zwykłej pętli for czy użycia metody .forEach. I często jest to bardziej czytelne (reduce ma dziwną skłonność zaciemniania kodu, bo często ludzie tam wrzucają imperatywny kod, ale pisany tak, żeby imitować programowanie funkcyjne).

Więc jeśli już ograniczyć się w używaniu czegoś, to sugerowałbym ostrożność w użyciu reduce ;) można oczywiście używać, ale łatwo napisać coś mało czytelnego używając reduce.

Długi post wyszedł, ale i tak tylko liznąłem temat. Bo poruszyłem tylko iterację po tablicach (a można jeszcze iterować po obiektach, iterablach itp.) oraz przez pętlę for mam na myśli for (init; cond; after) a w JS jest jeszcze pętla for... in, for... of czy for await...of.

Anyway, nie daj sobie wmówić głupot, że pętla for jest be. Wszystko zależy co robisz.

No i jeszcze są pętle while czy do while, które też są przydatne, chociaż rzadziej (ale np. przy implementacji różnych algorytmów mogą się przydać).


edytowany 6x, ostatnio: LukeJL
Zobacz pozostałe 9 komentarzy
LukeJL
oo! masz rację. Jeszcze jest some oprócz rodziny metod find. Co ma uzasadnienie, w końcu jeśli jest co najmniej jeden element spełniający warunek, to nie trzeba dalej iterować. Analogicznie zachowuje się metoda every.
WY
Wypierdzistyy
No jednak nie działa na foreach coś mi się pomerdało, jakieś problemy z koncentracją mam.
Xarviel
Teoretycznie są 2 sposoby żeby przerwać metody forEach, map, reduce itd, ale oba głupie :D Pierwszy to zmiana długości tablicy na której jest wywoływana [1, 2, 3].forEach((el, i, arr) => { arr.length = 1 }). Taka pętla wykona się przykladowo tylko raz, ale stracimy pozostałe elementy. Drugim sposobem jest rzucenie wyjątku przez throw i złapanie błędu przez try { [1, 2, 3].map(el => throw new Error())} catch {} :P
WY
Wypierdzistyy
Ale to są dobre i sprytne rozwiązania, ja takie lubię chodź nie każdy widzi w tym piękno @Xarviel :>
Xarviel
@Wypierdzistyy Teoretycznie mogą być sprytne, ale wolę nie kombinować w taki sposób i jeśli faktycznie potrzeba przerwać pętle to wybieram for of / for in / for, gdzie działa normalny break.
ZD
  • Rejestracja:około 3 lata
  • Ostatnio:ponad rok
  • Postów:2310
4

Dodam, pętla (foreach / for) w stosunku do streamów / lambd jest perfekcyjnie podatna do śledzenia debugerem (Java / C#)

Nie zawsze autor jest w najwyższej kondycji intelektualnej, nie zawsze dane są czyste, czasem tropimy jakiś wyjątek po 2 latach pozytywnej eksploatacji, okazuje się że święte założenia co do danych nie są takie święte itd...


If you put a million monkeys at a million keyboards, one of them will eventually write a Java program - the rest of them will write Perl
WY
WY
  • Rejestracja:ponad 2 lata
  • Ostatnio:ponad 2 lata
  • Postów:101
1

W pythonie mają te funkcje duże różnice, ze względu na to jak język działa w wirtualnej maszynie, funkcje i zmienne są wyszukiwane jako stringi i możliwe są pewne optymalizacje, w niskopoziomowych językach nie ma to znaczenia bo każdy kod może być praktycznie tak samo przedstawiony, ale w dynamicznych może w internalsach być spora różnica.

CZ
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 godziny
  • Postów:2286
2

Kod ma być najprostszy i czytelny tak, żeby zrozumiał go stażysta.
Tak więc żenujące jest robić fikołki tylko po to, żeby ładnie wyglądało

LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:2 minuty
  • Postów:8406
6
Czitels napisał(a):

Kod ma być najprostszy i czytelny tak, żeby zrozumiał go stażysta.
Tak więc żenujące jest robić fikołki tylko po to, żeby ładnie wyglądało

Trochę się zgadzam, trochę nie.
Tj. zgadzam się, żeby pisać czytelny kod i że bezsensu jest robić fikołki tylko po to, żeby się popisać jakąś techniką.

Jednak z tak, żeby zrozumiał go stażysta mam problem. Jeśli będziemy się dostosowywać do stażystów, to okaże się, że niewiele się da zrobić i będziemy ogłupiać własny kod i np. nie używać zaawansowanych ficzerów w języku czy pewnych wzorców/technik, tylko dlatego, że nowicjusz może tego nie zrozumieć. A przecież to odwrotnie powinno być - stażysta wchodząc do projektu powinien się uczyć nowych technik i rozwijać, pytać o coś, jak nie rozumie itp.


edytowany 1x, ostatnio: LukeJL
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
2

Kod ma być najprostszy i czytelny tak, żeby zrozumiał go stażysta.

W sensie ze filter, map jest nieczytelne?


λλλ
K8
K8
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 2 lata
  • Postów:791
1

Jeżeli ktoś zna tylko for czy while to taki map() z operatorem lambda wywoła tylko jeden efekt: WTF.

SA
  • Rejestracja:około 12 lat
  • Ostatnio:około 5 godzin
  • Postów:1431
5
kosmonauta80 napisał(a):

Jeżeli ktoś zna tylko for czy while to taki map() z operatorem lambda wywoła tylko jeden efekt: WTF.

Jak ktoś nie umie programować to wiele rzeczy będzie dla niego wtf-em.

Dla mnie sprawa jest prosta (z perspektywy C#):

  1. Mutowanie lub side-effecty - foreach. Nigdy nie napisałem ani na szczęście nie widzę używania ForEach w tym kontekście, jakiś wygibasów z in-house extension methodami, bo IEnumerable nie ma ForEach.
  2. Select (czy jak kto woli map) w przeciwnym wypadku. Lambdy i LINQ są mocno zakorzenione w .NET i nikt nie marudzi, że to przejściowa moda na funkcyjne i for jest bardziej naturalny.

while to ma sens chyba tylko przy while(true), a for to w sumie tylko jak mamy mutowanie/side-effecty i potrzebujemy dostęp do indeksu.

edytowany 1x, ostatnio: Saalin
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
6
kosmonauta80 napisał(a):

Jeżeli ktoś zna tylko for czy while to taki map() z operatorem lambda wywoła tylko jeden efekt: WTF.

U Ciebie wszystko wywoluje WTFa ;) tak zauwazylem


λλλ
edytowany 1x, ostatnio: stivens
CR
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Postów:112
3

Oczywiście że for to siara. Prawdziwy programista pisze LDR PC, <adres instrukcji>.

KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:dzień
  • Lokalizacja:Silesia/Marki
  • Postów:5505
3

Chciałem napisać że w Haskellu to nawet nie ma fora, ale wcześniej sprawdziłem w Hoogle i nawet jest :P Zaimplementowany jako traverse z argumentami w odwrotnej koleności :D

Kopiuj
for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)
for = flip traverse

XD


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 2x, ostatnio: KamilAdam
W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 2 godziny
  • Postów:3544
0

Biorąc pod uwagę, że javowe Stream API jest bardzo okrojone jeśli chodzi o funkcjonalność względem for / while to właśnie streamy są dla przedszkolaków ;)
Główna siła streamów polega na tym, że kiedy do nich przywykniesz to są bardziej czytelne. Natomiast jeśli chodzi o wydajność to leżą i kwiczą, a jeśli do tego dorzucisz, że bardziej skomplikowane operacje na streamach robią się średnio czytelne to jest jeszcze słabiej.

Zobacz pozostałe 2 komentarze
R1
Każdy kto pisze o kiepskiej wydajności stream'ow zawsze zapominać dodać, że boli to tylko w bardzo wąskiej grupie zastosowań, przez co później trafia się na kogoś, kto używa zwykłych pętli, bo przeczytał, że są wydajniejsze. Co do czytelności - zwykłe pętle są zawsze mało czytelne, im bardziej skomplikowana operacja, tym jest gorzej. Streamy są dużo bardziej czytelne. Można popsuć czytelność stremów, przez nieumiejętne korzystanie z lambd.
jarekr000000
Natomiast są działki, gdzie większość dobrych praktyk znanych z biznesowych aplikacji idzie w odstawkę HFT (którego robienie na javie i tak jest dziwne...) i co jeszcze?
R1
HFT to coraz częściej scala, ostatnio też widziałem nowy projekt HFT w kotlinie.
jarekr000000
@rad1317: to widocznie niezbyt HF HFT. Można? Można.
W0
@jarekr000000: akurat robienie HFT w Javie nie było czymś jakoś niespotykanym. Nawet kiedyś byłem na prezentacji VMki specjalnie do tego, która miała zagwarantowaną reakcję na System.gc(). Jeśli chodzi o inne zastosowania to głównie distributed stream processing przy dużym natężeniu ruchu. Z takich rozwiązań lubianych przez korpo to Kafka Streams i Apache Beam/Apache Flink.
W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 2 godziny
  • Postów:3544
0

@rad1317: to, że ktoś może pomylić "streamy są wolniejsze od pętli" z "należy unikać streamów" to już nie mój problem. Równie dobrze mógłbym napisać "jeśli nie napiszesz, że streamy są wolniejsze od pętli to potem znajdzie się ktoś, kto to przeczyta i będzie wrzucał streamy nie tam gdzie trzeba".

Jeśli chodzi o czytelność - to przestrzegam cię po prostu przed zwrotami w stylu "pętle są zawsze mało czytelne" - bo w programowaniu naprawdę trudno znaleźć takie ostateczne prawdy (swoją drogą całkiem niedawno dyskutowałem o tym, że zapis z streamami jest dla mnie czytelniejszy niż taki bardziej imperatywny). Taki bardzo prosty przykład:

Kopiuj
for (Request request: requests) {
   for (Element element: request.elements()) {
      for (Attribute attribute: element.attributes()) {
         if ("someName".equals(attribute.getName())) {
            doSomething(attribute.getName());
         }
      }
   }
}

// Na streamach jest to dużo prostsze: 

requests.stream()
   .flatMap(r -> r.elements().stream())
   .flatMap(e -> e.attributes().stream())
   .map(a -> a.getName())
   .filter(name -> "someName".equals(name))
   .forEach(this::doSomething);

Proste, prawda? No to lekka modyfikacja:

Kopiuj
for (Request request: requests) {
   for (Element element: request.elements()) {
      for (Attribute attribute: element.attributes()) {
         if ("someName".equals(attribute.getName())) {
            doSomething(request, element, attribute);

            break;
         } else if ("otherName".equals(element.getName())) {
            break;
         }
      }
   }
}

No i teraz pytanie - jak to zapiszesz? Tak, żeby nie trzeba było zbytnio skakać oczami pomiędzy kilkoma kawałkami kodu.

edytowany 2x, ostatnio: wartek01
R1
ten stream który wrzuciłeś modyfikujesz w ten sposób, że w 15 linijce w zależności od nazwy elementu robisz na streamie z atrybutami findFirst().filter() lub filter().findFirst() i zmieniasz to na stream. Żeby było czytelnie pewnie całość flatMap trzeba przenieść do osobnej metody. Dla mnie wersja z stream będzie czytelniejsza, mimo, że będę musiał zajrzeć do metody niżej.
R1
jeszcze, żeby była jasność - nie uważam streamApi za coś cudownego, uważam, że z dwojga złego lepiej już korzystać z streamApi, jeszcze lepiej gdy przejdzie się np. na vavr'a.
W0
Widzisz, i tutaj mógłbym trochę bardziej skomplikować ci przykład poprzez dorzucenie kolejnego if'a z continue - i wtedy będziesz naprawdę się musiał męczyć, żeby taką logikę przerzucić na dowolne streamy. Da się, ale po prostu będzie to dużo bardziej skomplikowana konstrukcja niż te kilka zagnieżdżonych pętli.
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
2

W Scali dosyc prosto.

Kopiuj

.collectFirst {
  case "someName" => doSmth()
  case "otherName" => ()
}

Na JS-owym Javovym API sie nie znam. Moze tam nie ma takich funkcji.

EDIT:

A dobra. Bo tutaj sie jeszcze wywolanie doSomething(request, element, attribute); zmienilo. No to troche wiecej trzeba

Kopiuj
 (for {
   request <- requests
   element <- request.elements
   attribute <- element.attributes
 } yield (request, element, attribute))
   .collectFirst {
     case (request, element, attribute) if attribute.name == "someName" => doSomething(request, element, attribute)
     case (_, _, attribute) if attribute.name == "otherName" => ()
   }

* for-comprehension to lukier skladniowy na flatMapy, nie jest to petla per se. Jakby ktos sie mial czepiac ;)


EDIT2: Co nie znaczy, ze nie zgadzam sie z haslem it depends


λλλ
edytowany 8x, ostatnio: stivens
W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 2 godziny
  • Postów:3544
1

No akurat, że w językach mocno funkcyjnych takie rzeczy robi się łatwiej, to wiem. Sam pisałem kiedyś wstawki w Q z KDB i tam przekazywanie nadrzędnego elementu jest jeszcze prostsze niż w Scali. Mi głównie chodziło o javowe Streams API, bo od dłuższego czasu widzę dziwną kargokultyzację tego rozwiązania, tzn. ludzie tworzą niespotykanie skomplikowane streamy,

W Streams API problemem jest to, że nie masz kluczowego słówka yield, co oznacza tyle, że musisz się gimnastykować. Tj.

Kopiuj
// Takie coś
for (Request request: requests) {
   for (Element element: request.elements()) {
      doSomething(request, element);
   }
}

// Trzeba zapisać jako takie coś:
requests.stream()
   .flatMap(r -> r.elements().stream().map(e -> Tuple2.of(r, e)))
   .forEach(t -> doSomething(t.f0, t.f1));

// Albo tak:
Function<Request, Stream<Tuple2<Request, Element>> flattenElements = (r -> r.elements().stream().map(e -> Tuple2.of(r, e)));
requests.stream()
   .flatMap(flattenElements)
   .forEach(t -> doSomething(t.f0, t.f1));

// Albo pójść na prosto, tj.
Consumer<Request> consume = (r -> r.elements().stream().forEach(e -> doSomething(r, e)));
requests.stream().forEach(consume);

Wtedy tracisz podstawową zaletę javowych streamów - tj. prostolinijne czytanie od dołu do góry, no i przy użyciu tupli musisz sprawdzać, co leży pod t.f0, a co pod t.f1. Już lepiej faktycznie lecieć po skosie, ewentualnie wykorzystać vavr.io, chociaż to ostatnie to ciągle jest samo API.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

Dla mnie zarówno pętla for (i każda inna) jak i java.util. streamy to obciach (java i kotlin). Z tym, że java.util nawet większy - bo poletko zastosowań jest nikłe.


jeden i pół terabajta powinno wystarczyć każdemu
LukeJL
Dla mnie zarówno pętla for (i każda inna) jak i java.util. streamy to obciach (java i kotlin). - a to nie jest tak, że ogólnie Java jest obciachem? W sensie nie wiem, niektórzy uważają to za poważny język.
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
0

Btw. Wydaje mi sie, ze w przypadku OP-a chodzi raczej o JS a nie stream-api


λλλ
jarekr000000
Myślę, że dorosłem już do tego, żeby nie odróżniać dżawy od dżawy w wersji skrypt.
stivens
Stream api jest wybitnie paskudne :p
LukeJL
w jakim sensie stream api? (w sensie to wieloznaczne pojęcie, przynajmniej jeśli chodzi o JSa)
stivens
Java stream api
LukeJL
A to nie wiem. Myślałem ze chodzi o streamy w JS
NT
  • Rejestracja:ponad 2 lata
  • Ostatnio:ponad 2 lata
  • Postów:15
1

Jeśli celem jest produkowanie wartości wówczas map/filter jest lepsze, bo taki kod można łatwiej:

  1. przekształcić, by wykonać równolegle
  2. wartościować/ewaluować leniwie
  3. oraz ostatecznie postrzegać jako wyrażenie, które nie tylko łatwo rozbudować, ale również zapisać w repl.

Natomiast jeśli celem jest mutowanie stanu czy wywoływanie innych efektów to wtedy for jest lepszy, bo taki kod łatwiej jest debugować, oprzeć na przerwaniach, łączyć z wyjątkami. Oczywiście warto ograniczyć mutowanie, ale jeśli program nie ma efektów to raczej wątpliwe ma zastosowanie.

Dla mnie obciachem jest sytuacja, gdy osoba jest zaślepiona składnią, opiera się wyłącznie ku jednej stronie nie biorąc pod uwagę celu do jakiego musi w danej sytuacji dążyć, by rozwiązać problem. Jeśli ktoś próbuje np. robić efekty, proszę bardzo, ale lewniwe wartościowanie i efekty to wówczas proszenie się o dodatkowe problemy.

EDIT:
Zasadniczo cały wątek sprowadza się do pytania co lepsze: instrukcje czy wyrażenia? Na ogół jedno bez drugiego nie ma większego sensu.

edytowany 1x, ostatnio: nie_tak_wiele_postow
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Wrocław
3
kosmonauta80 napisał(a):

Spotkałem się ze stwierdzeniem, że for stosuje się "w przedszkolu". Natomiast "profesjonalne" podejście to kod typu myArray.filter().map()...

Co o tym sądzicie?

Jak najbardziej. Nierozsądnie jest używać do przeszukiwania/filtrowania/mapowania danych z kolekcji jakichś rozwlekłych pętli, jeśli mamy biblioteki pozwalające pisać nam bardziej zwięzły kod.

G8
  • Rejestracja:około 3 lata
  • Ostatnio:około rok
  • Postów:2000
1

Czemu miałbym używać pętli for, gdy istnieje bardziej czytelny i zwięzły zapis? To, że ktoś nie rozumie, jak działa map to chyba tylko jego problem. To niech się douczy.

edytowany 1x, ostatnio: Riddle
ML
  • Rejestracja:ponad 19 lat
  • Ostatnio:około 11 godzin
  • Postów:856
1

Obciachem jest mówienie że to obciach.

katakrowa
  • Rejestracja:około 10 lat
  • Ostatnio:około 2 lata
  • Lokalizacja:Chorzów
  • Postów:1670
2

For tak samo dobry jak map. Zależy od zastosowania. Równie często używam for i while, foreach - rzeczywiście for używam najrzadziej ale używam.
Jak kogoś boli używanie pętli for czy while to moim zdaniem coś jest z nim "nie tak".
Pisanie, że for to obciach to owszem obciach ale dla tego co tak pisze...
Ogólnie dyskusja na tym samym poziomie co "taby czy spacje".


Projektowanie i programowanie. Hobbystycznie elektronika i audio oszołom.
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:2 minuty
  • Postów:8406
1

Najlepiej dobrać narzędzia do problemu, znając również wady i zalety poszczególnych narzędzi w danym kontekście i języku programowania (bo i od języka programowania to będzie zależeć, czego się najlepiej używa).

pętli for

pętle for też bywają różne. W wielu językach do iteracji po kolekcji można zrobić coś w stylu for a in b i to jest bardziej czytelne niż for (init; cond; after). Do Pythona nawet pętle for wsadzili do list comprehension i ludzie z tego korzystają i uważają za cool.

Przykład Pythona. Powiedzmy, że mamy listę liczb:

Kopiuj
numbers = [1, 2, 3, 4, 5, 6]

i chcemy przefiltrować tylko parzyste [2, 4, 6] i pomnożyć przez dwa, czyli uzyskać [4, 8, 12].

możemy to zrobić tak (list comprehension)

Kopiuj
out = [a * 2 for a in numbers if a % 2 == 0]

albo tak (używając pętli for):

Kopiuj
out = []
for a in numbers:
	if a % 2 == 0:
		out.append(a * 2)

albo używając map i filter:

Kopiuj
out = list(map(lambda a: a * 2, filter(lambda a: a % 2 == 0, numbers)))

No i moim zdaniem wersja z map i filter jest najmniej czytelna z tych opcji.


edytowany 1x, ostatnio: LukeJL
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0

Nie.

WY
WY
  • Rejestracja:ponad 2 lata
  • Ostatnio:ponad 2 lata
  • Postów:101
0

Ja powiem, że nie mam takiej wiedzy, mam w C++ std::ranges::any_of i ona iteruje i sprawdza nie wiem czy przerwie się przy pierwszym znalezionym czy nie i może to czasem opóźnić wszystko.

edytowany 1x, ostatnio: Riddle
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)