Rozważ następujące:
if(a == b or c)
W większości języków należy to zapisać jako:
if(a == b or a == c)
co jest nieco kłopotliwe i powtarza informacje.
Wiem, że moja powyższa przykładowa składnia jest nieco niezgrabna, ale jestem pewien, że są lepsze sposoby przekazania tego pomysłu.
Dlaczego nie oferuje tego więcej języków? Czy występują problemy z wydajnością lub składnią?
a == b or c
i nawet nie działa dobrze IMHO.Odpowiedzi:
Problem ze składnią polega na tym, że wymaga ona składni.
Bez względu na to, jaką składnię ma Twój język, ludzie używający tego języka muszą się go nauczyć. W przeciwnym razie grozi im zobaczenie kodu i brak wiedzy o jego działaniu. Dlatego ogólnie uważa się za dobrą rzecz, jeśli język ma prostą składnię, która czysto obsługuje wiele przypadków.
W twoim konkretnym przykładzie próbujesz pobrać operator infix (funkcja, która przyjmuje dwa argumenty, ale jest zapisany
Argument1 Operator Argument2
) i próbujesz rozszerzyć go na wiele argumentów. To nie działa bardzo czysto, ponieważ cały punkt operatorów infix, o ile istnieje, polega na umieszczeniu operatora pomiędzy dwoma argumentami. Wydłużenie do(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
wydaje się nie dodawać dużo przejrzystościEquals(Arg1,Arg2,...)
. Infix jest zwykle używany do naśladowania konwencji matematycznych, które ludzie znają, co nie byłoby prawdą w przypadku alternatywnej składni.Nie ma żadnych szczególnych problemów z wydajnością związanych z twoim pomysłem, poza tym, że parser musiałby poradzić sobie z gramatyką z inną regułą produkcyjną lub dwiema, co może mieć niewielki wpływ na szybkość parsowania. Może to mieć znaczenie dla języka interpretowanego lub skompilowanego w JIT, ale prawdopodobnie nie jest to duża różnica.
Większy problem z tym pomysłem polega na tym, że tworzenie wielu specjalnych przypadków w języku jest złym pomysłem .
źródło
.
. Byliby zapisani jakoarg1 op (arg2, arg3)
. Niezupełnie piękny, ale potrzebny w niektórych miejscach w kontekście tego języka.if my_var in (a, b)
wtedy? czy to nie jest więcej kwestia użycia odpowiedniego narzędzia do pracy?a == b or c
a inni tego chcąa == b or c but not d
. IMO właśnie tam na ratunek przychodzą funkcje / biblioteki narzędzi.f().Equals(a,b,c)
; można ocenić, ponieważ(var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
ta składnia byłaby idealna, ale jeśliint[] arr = {a,b,c}; f().Equals(arr);
byłaby oceniona jako taka, nie byłoby to tak dobre, zwłaszcza gdyby dla każdego wywołania trzeba było utworzyć nową tablicę.Ponieważ jest to bezproblemowe, a jego rozwiązanie przynosi zasadniczo zerową korzyść, ale wdrożenie go przynosi niezerowe koszty.
Istniejące funkcje oparte na zakresie i takie, które praktycznie każdy język oferuje, mogą doskonale działać w tej sytuacji, jeśli skalują się do rozmiaru, w którym
a == b || a == c
nie można ich wyciąć.źródło
in_array($a, [$b, $c, $d, $e, $f])
. : PNiektóre języki mają takie funkcje. Np. W Perl6 możemy użyć połączeń , które są „superpozycjami” dwóch wartości:
Połączenia pozwalają nam wyrażać operacje na zbiorze danych dość zwięźle, podobnie do sposobu, w jaki operacje skalarne rozkładają się na kolekcje w niektórych językach. Np. Używając Pythona z numpy, porównanie można rozłożyć na wszystkie wartości:
Działa to jednak tylko dla wybranych typów pierwotnych.
Dlaczego skrzyżowania są problematyczne? Ponieważ operacje na skrzyżowaniu rozkładają się na zawarte w nim wartości, sam obiekt skrzyżowania zachowuje się jak proxy dla wywołań metod - coś, co może obsłużyć kilka systemów typów oprócz typowania kaczego.
Problemów z układem typów można uniknąć, jeśli takie połączenia są dozwolone tylko jako specjalna składnia wokół operatorów porównania. Ale w tym przypadku są one tak ograniczone, że nie dodają wystarczającej wartości, aby dodać je do rozsądnego języka. To samo zachowanie można wyrazić za pomocą operacji ustawiania lub ręcznego wypisywania wszystkich porównań, a większość języków nie wierzy w dodanie zbędnej składni, jeśli istnieje już doskonale doskonałe rozwiązanie.
źródło
2 in [1, 2, 3]
. Z drugiej strony, jeśli numpy ma.all()
coś lub coś, równoważny zwykły python nie jest tak zwięzły.==
operatora, możemy również użyć<
zamiast tego - gdzie jestin
teraz twój ? Połączenia są bardziej ogólne niż ustawione testy członkostwa, ponieważ operacje na skrzyżowaniu rozkładają się na wszystkich członków -(x|y).foo
jestx.foo|y.foo
, dopóki połączenie nie zostanie ostatecznie zwinięte do jednej wartości. Podany kod NumPy pokazuje dokładnie równoważne, ale bardziej pełne tłumaczenie połączeń Perl6, przy założeniu, że są to typy pierwotne.W językach z makrami łatwo jest dodać coś takiego, jeśli jeszcze go nie ma. Rozważ rakietę
W innych językach bez metaprogramowania, być może możesz przeformułować to jako sprawdzanie członkostwa w ustawieniach / listach, być może:
źródło
W niektórych (popularnych) językach
==
operator nie jest przechodni. Na przykład w JavaScript0
jest równy zarówno''
i'0'
, ale''
i wtedy'0'
nie jest sobie równy. Więcej takich dziwactw w PHP.Oznacza to,
a == b == c
że dodałoby to kolejną niejednoznaczność, ponieważ może dać inny wynik w zależności od tego, czy jest interpretowany jako(a == b) & (a == c)
czy(a == b) & (a == c) & (b == c)
.źródło
W większości języków powinno to być trywialnie osiągalne przez napisanie
In
funkcji, więc dlaczego warto włączyć ją do rzeczywistego języka?Na przykład Linq
Contains()
.Dobra, dla was wszystkich pedantów, oto moja implementacja w C #:
źródło
a == b || a == c
wiele razy, może nadszedł czasequals_any(a, {b, c})
if (a > (b or c))
iif (a mod (b or c) == 2)
.i
zmiennej. I ogólnie rzecz biorąc, wydaje się, że napisano to po długim dniu :) Ponieważ umieszczenie zarówno wewnątrz, jakreturn true
ireturn false
wewnątrz pętli oznacza, że nie ma mowy, aby kiedykolwiek wyszło poza pierwszą iterację. Porównujesz tylko z pierwszymvalue
. Nawiasem mówiąc, dlaczego nie skorzystać zAny
sugestii @Bob i uprościć jąreturn values.Any(value => Object.Equals(obj, value));
„if (a == b lub c)” działa w większości języków: jeśli a == b lub jeśli c nie jest ujemne, zerowe lub zerowe.
Narzekanie, że jest to gadatliwe, nie ma sensu: nie powinieneś układać kilkunastu rzeczy w warunkowe. Jeśli chcesz porównać jedną wartość z dowolną liczbą innych wartości, zbuduj podprogram.
źródło
c
oceniany jest na wartość logiczną, prawie każdy język może sobie z tym poradzića == b || c
:)if(a == b or c)
. Myślę, że muszę zrobić sobie przerwę ...: Pif (a == b or c)
jest pseudo-kodem, aby sprawdzić, czya
jest równyb
luba
równyc
. Nie ma na celu sprawdzenia,c
czy nie jest to zero.Zwykle chcesz ograniczyć składnię do minimum i zamiast tego pozwolić, aby takie konstrukcje były definiowane w samym języku.
Na przykład w Haskell można przekonwertować dowolną funkcję z dwoma lub więcej argumentami na operator infix za pomocą odwrotnych poleceń. To pozwala napisać:
gdzie
elem
jest po prostu normalna funkcja pobierająca dwa argumenty - wartość i listę wartości - i sprawdza, czy pierwszy jest elementem drugiego.Co jeśli chcesz użyć
and
zamiastor
? W Haskell możesz po prostu użyć następujących poleceń zamiast czekać, aż dostawca kompilatora zaimplementuje nową funkcję:źródło
Niektóre języki to oferują - do pewnego stopnia.
Może nie jako twój konkretny przykład, ale weźmy na przykład wiersz Python:
Tak więc niektóre języki są w porządku z wieloma porównaniami, pod warunkiem, że wyrażasz to poprawnie.
Niestety nie działa tak, jak można by się tego spodziewać w przypadku porównań.
„Co masz na myśli mówiąc, że zwraca True lub 4?” - zatrudnienie po tobie
Jednym rozwiązaniem w tym przypadku, przynajmniej w Pythonie, jest użycie go nieco inaczej:
EDYCJA: Poniższe czynności również zrobiłyby coś podobnego, ponownie w Pythonie ...
Niezależnie od tego, jakiego używasz języka, może nie być tak, że nie możesz tego zrobić, po prostu musisz najpierw przyjrzeć się, jak działa logika. Zazwyczaj jest to kwestia znajomości tego, o co „pytasz” język, który ma ci powiedzieć.
źródło
Metoda indexOf stosowana w macierzy, którą posiadają wszystkie języki, pozwala porównać wartość z kilkoma innymi, więc chyba specjalny operator nie ma większego sensu.
W javascript, który napisałby:
źródło
Pytasz, dlaczego nie możemy tego zrobić:
if(a == b or c)
Python robi to bardzo skutecznie, w rzeczywistości najskuteczniej z
set
:W przypadku testowania członkostwa „ustaw” sprawdza, czy skróty elementu są takie same, i dopiero wtedy porównuje się pod kątem równości, więc elementy b i c muszą być mieszalne, w przeciwnym razie lista bezpośrednio porównuje równość:
źródło
Języki w stylu APL pozwalają porównać skalar z każdym elementem w wektorze w jednej operacji. To tworzy wektor boolowski. Na przykład chciałbym bezwstydnie promować mój minimalnie funkcjonalny kalkulator apl, inca ( tłumacz online ).
Aby sprowadzić to do jednej wartości, możemy wykonać włącznie lub sumując i sprawdzając wartość niezerową.
Tak więc, jak mówią inne odpowiedzi, problemem jest składnia. Do pewnego stopnia składniowe rozwiązania nie stwierdzono, być może w dużym kosztem nauki paradygmat tablicy.
źródło