Co to jest idiomatyczne?

19

Rozumiem, że „idiom” to wspólna operacja lub wzorzec, którego w danym języku nie upraszcza składnia języka podstawowego, taka jak przyrost liczby całkowitej:

i = i + 1;

W języku C ++ ten idiom jest uproszczony przez operatora:

++i;

Kiedy jednak ktoś używa terminu „idiomatyczny”, nie jestem pewien, jak go zrozumieć. Co sprawia, że ​​fragment kodu jest „idiomatyczny”?

void.pointer
źródło
To tyle samo należy do english.stackexchange.com, jak tutaj.
S.Lott,
@ perl.j: wnikliwe. Naprawdę wyjaśniłeś, dlaczego definicja „Idiomatic” nie należy do angielskiego.stackexchange.com. Bardzo pomocny.
S.Lott,

Odpowiedzi:

24

Idiomatyczny sposób pisania kodu polega na pisaniu go w bardzo specyficzny sposób z powodu idiomów specyficznych dla języka, których nie mają inne języki.

Na przykład w C ++ wykorzystanie idiomu RAII prowadzi do sposobów pisania idiomatycznych zasobów zarządzających kodem C ++.

Innym przykładem może być użycie wyrażeń listowych w Pythonie do generowania list. Jest to idiomatyczne, ponieważ użyłbyś rozumienia listy w idiomatycznym Pythonie, ale możesz zrobić to samo, używając funkcji generatora w innym języku, a nawet w Pythonie.

Często ktoś, kto próbuje nowego języka bez użycia idiomów specyficznych dla tego języka, nie napisze kodu idiomatycznego.

Klaim
źródło
Doskonały opis Więc w C #, jeśli utworzę metodę rozszerzenia wywoływaną TryAdd()w Dictionaryklasie Generic, aby najpierw sprawdzić, !Contains()a następnie wywołać Add(), byłoby to idiomatyczne? Korzystam z funkcji specyficznych dla metod rozszerzenia C #.
void.pointer
1
Nie jestem pewien, jak najbardziej doświadczony programista C ++ poleciłby ci pisać darmowe funkcje do rozszerzania klas zamiast dodawania członków, tam gdzie to możliwe. Nie jest to to samo, co metody rozszerzenia C #, ale jest dość zbliżone i dostępne w każdym języku, który umożliwia bezpłatne funkcje. Jestem pewien, że pisanie „set / getters” w C # przy użyciu właściwości JEST idiomatyczne.
Klaim
Ale to nie jest C ++, więc użycie metody „C ++” może nie być wystarczająco „idiomatyczne”. Użycie metody rozszerzenia tutaj jest rozsądne i bardzo podobne do C #. W każdym razie był to przykład, ale metody rozszerzenia są bardzo idiomatyczne w stosunku do C #.
void.pointer
Tak, dlatego powiedziałem „nie jestem pewien”, to jest idiomatyczne, ale jest tak blisko innych podstawowych funkcji innych języków, że nie jestem pewien (ponieważ nie jestem programistą C #). Mam inny przykład: zapętlanie odbywa się przez rekurencję we wszystkich językach funkcjonalnych. Możesz to zrobić w innych językach, ale wyraźnie jest to idiomatyczne dla języków funkcjonalnych. Nie jestem pewien, czy to pomaga.
Klaim
1
Oczywiście python idzie o krok dalej, mając idiomatyczny sposób odwoływania się do kodu idiomatycznego, tj. Pythonowego. * 8 ')
Mark Booth
12

Normalna definicja

Używanie, zawieranie lub oznaczanie wyrażeń, które są naturalne dla native speakera

Definicja programowania

Korzystanie zawierające lub oznaczając wyrażeń, które są naturalne w [Insert] Język programisty

ChaosPandion
źródło
1
Gdybym pomyślał, że definicje „google” tego terminu były pomocne, nie zamieściłbym tutaj. Chciałem lepszego opisu (samouczka) z przykładami.
void.pointer
3
@Robert - Chyba nie rozumiem, dlaczego nie rozumiesz.
ChaosPandion,
2
Najpierw przeczytałem twoją odpowiedź, nie była całkiem jasna. Po przeczytaniu odpowiedzi, która jest teraz oznaczona jako moja odpowiedź, stało się bardzo jasne, co znaczy „idiomatyczny” i teraz to rozumiem. Teraz, kiedy przeczytałem twoją odpowiedź, ma to sens. Jednak nie przeprowadziłeś mnie przez przykłady i różne scenariusze, dlatego myślę, że twoja odpowiedź nie była tak pomocna. Udzieliłeś odpowiedzi „webstera”, która jest technicznie poprawna, ale nie jest pomocna, o ile pomaga mi zrozumieć. Doceniam twoją pomoc.
void.pointer
7

Idiomatyczny w kontekście programowania można zwykle zdefiniować jako „najbardziej naturalny sposób wyrażenia czegoś w języku”

Widzę, że słowo idiomatic pojawia się szczególnie często w Ruby. W Ruby istnieją ogromne możliwości metaprogramowania i aby napisać idiomatyczny kod Ruby, zwykle musisz ich użyć.

Zauważ, że fakt, że fragment kodu jest idiomatyczny, nie oznacza, że ​​jest czysty, a nawet zwięzły. Wiele razy musisz iść na kompromis.

Zasadniczo więc idiomatyczny najczęściej odnosi się do najczęstszego sposobu pisania czegoś w języku, często w tym „slang” (idiomy). Jeśli fragment kodu nie jest idiomatyczny, może być doskonale czytelny, zwięzły, czysty i poprawny, ale może wydawać się / wyglądać dziwnie w używanym języku. Preferowana jest preferencja co do tego, czy idiomatyczne przepisanie takiego fragmentu kodu byłoby w rzeczywistości dobrą rzeczą i musi być oceniane indywidualnie dla każdego przypadku

Na przykład idiomatyczny angielski może zależeć od regionu. Używanie tego słowa bumjest prawdopodobnie wymagane w przypadku idiomatycznego angielskiego w Wielkiej Brytanii, podczas gdy buttjest bardziej odpowiednie dla angielskiego w USA. (Niestety nie znam dużo angielskiego angielskiego: /)

Earlz
źródło
Dzięki (pozytywnie oceniam), myślę, że twoja definicja trafiła we mnie od razu!
Ashaman Kingpin,
3

Najlepszy przykład, jaki mogę wymyślić z góry, dla czegoś idiomatycznego, pochodzi od Ruby.

W wielu językach możesz iterować z:

for( start; end; increment){
    code;
}

Lub coś bardzo podobnego. Wiele języków ma również foreach(x in SetOfXes)konstrukcję. Ale iteracja idiomatyczna dla Ruby obejmuje takie rzeczy jak:

collection.each do |current|
  current.do_stuff
end

i nawet

10.times do |x|
  puts x
end

Widzę je jako idiomatyczne, ponieważ reprezentują sposób robienia czegoś, co jest mniej powszechne, a to stanowi coś w rdzeniu filozofii jego dziedziny. Ruby ma filozofię interakcji z przedmiotami, która, choć nie jest unikalna, nie jest wszechobecna.

Mówiąc semantycznie, za każdym razem, gdy słyszę słowo idiomatyczne, mój mózg automatycznie uzupełnia tę myśl jako „idiomatyczną do ...” - po prostu odruchowo analizuję ją jako odnoszącą się do konkretnego tematu.

przedpola
źródło
Czym się collection.each do |current|różni foreach(current in collection)? Oba są konstrukcjami pętli ustawionymi currentdla każdego elementu collection.
MSalters
2

Idiomy są zazwyczaj najlepszym możliwym sposobem wyrażenia wspólnej, stosunkowo złożonej sytuacji w języku. Zwiększanie nie jest idiomem ani niczym w tym rodzaju. Używając przyrostka prefiksu zamiast postfiksa, możesz argumentować, że jesteś idiomem C ++.

Idiomy to najlepszy sposób używania języka, określony przez ekspertów. Prawdziwym idiomem C ++ byłyby obiekty funkcyjne. Innym idiomem byłoby RAII. W tym języku nic nie mówi, że musisz uwolnić zasoby w destruktorze. Ale idiomatyczne jest to zrobić. Innym przykładem są szablony - idiomatyczne jest używanie szablonów do wszystkiego, co możesz, ale nic nie stoi na przeszkodzie, abyś nadmiernie korzystał z dziedziczenia.

DeadMG
źródło
Wikipedia użyła inkrementacji jako przykładu, dlatego wspomniałem o tym w swoim pytaniu. Dlaczego idiomy muszą być złożone? To nie wydaje się być częścią definicji opartej na innych odpowiedziach.
void.pointer
4
@Robert Dailey: Jak inkrementacja może być idiomem? To część języka . Idiomy są tworzone przez użytkowników języka, zmieniają się z czasem. Zwiększanie nie jest idiomem, to podstawowa funkcjonalność języka. Biorąc tę ​​logikę, mógłbym powiedzieć, że każda inna podstawowa funkcja języka jest idiomem, a zatem każdy program jest idiomatyczny, a tak nie jest.
DeadMG,
2

Twoja definicja nie wydaje mi się poprawna. Idiom to sposób na napisanie czegoś, co może, ale nie musi, być możliwe w innych językach, ale jest to powszechne w tym języku. Zwykle jest krótszy niż alternatywa, ale tak naprawdę nie jest to wymóg.

Łatwiej byłoby to wyjaśnić, mówiąc o tym, co nie jest idiomatyczne. W C ++ napisanie:

Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y);
if(p)
{
 // whatever
}

Jeszcze bardziej idiomatyczne jest pisanie:

Foo* p; 
if(p = SomeThingThatReturnsAFooPointer(arg, param, x, y))
{
 // whatever
}

Ten kod robi dokładnie to samo - niektórzy ludzie, którzy są nowicjuszami w C ++, mogą go przeczytać jako testowanie, aby sprawdzić, czy p jest równe zwrotowi funkcji, ale to nie to, co robi.

Porównaj z tym, co ktoś mógłby napisać, bardzo nieidiomatycznie, kto przyszedł z innego języka:

Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y);
if(p !=NULL)
{
 // whatever
}

Zobaczysz również te rzeczy odrzucone jako nie idiomatyczne:

if (x>0)
  return true;
else
 return false;

Ponieważ podejście idiomatyczne jest

return (x>0);

Nie-idiomatyczne sposoby nie są złe, ale zwykle wymagają dłuższego pisania i zawsze wymagają dłuższego czytania, dla tych, którzy znają idiomy. Jeśli nazywam cię „chłopcem, który płakał wilkiem” i znasz tę historię, jest to szybsze niż wyjaśnienie, w jaki sposób fałszywe alarmy powodują, że ludzie cię ignorują. Problem oczywiście polega na tym, że nie znasz tej historii i nie wiesz, co wilki mają wspólnego z tym, o czym mówimy. Podobnie może być problem, jeśli nigdy wcześniej nie widziałeś return x<y;i naprawdę nie wiesz, co robi.

Kate Gregory
źródło
1
Idiomatycznym podejściem byłoby z pewnością zadeklarowanie wskaźnika w warunku if, aby nigdy nie można było uzyskać do niego dostępu, jeśli nie ma wartości NULL. if(Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y))
DeadMG,
mm, prawdopodobnie. Lub tysiąc linii wcześniej, ponieważ jest używany w tym bloku. Lub w pliku nagłówkowym, ponieważ jest to zmienna członkowska. Zadeklarowałem to tylko, aby czytelnicy wiedzieli, że to Foo *, masz rację, że w prawdziwym życiu nie będzie tam zadeklarowane.
Kate Gregory
1

Gdy istnieje wiele sposobów wyrażenia czegoś, najczęstszy lub powszechnie akceptowany sposób. Na przykład za pomocą instrukcji strukturalnej w C zamiast dokładnego odpowiednika za pomocą instrukcji goto.

hotpaw2
źródło