Niebezpieczna operacja a operator logiczny

0

Zdaje mi się, ze jest tak, że jeśli mamy
if (p && q) to komputer, gdy warunek p okaże się fałszywy, nie sprawdza q.
Jednak zawsze na wszelki wypadek i dla czytelności wole pisać np

if (a.Length > 0) //a jest stringiem
{
   if (a[0] != ' ')
   {

   }
}

Czy też tak robicie czy walicie wszystko w jednej linijce?

0

W C/ C++ short-circuit od lewej do prawej jest chyba częścią semantyki języka i można na tym polegać. Pewnie podobnie jest w Javie i C#. Nie zawsze jednak short-circuit musi być w danym języku dostępny albo stosowany.

<pauza>

Sprawdziłem w Wiki, jednak nie chyba, ale na pewno :)
http://en.wikipedia.org/wiki/Short-circuit_evaluation

PS:
W C++

When overloaded, operators && and || are eager and can return any type.
Ciekawe jak jest w C#?

1

Walę w 1 linijce, nie dość, że krócej to jeszcze wprowadza mniej wieloznaczności, oraz zalecane np. przez WebKita

0

W jednej. W C# jest tak samo jak w Javie. Btw, chciwym odpowiednikiem, który oblicza zawsze obydwa operandy, jest & (oraz | dla ||), tak jak and i or bitowe.

1

Ja często wykorzystuje short circuit. Taki kod jest krótszy, bez straty na czytelności, tzn. dodatkowy poziom jest mniej czytelny niż prosty warunek (np. if (ptr && [...])) przed drugim. Ogólnie zawsze jestem zwolennikiem krótszego bardziej płaskiego kodu (z priorytetem na krótkość pojedynczych metod/funkcji przed wielkością całego kodu), oczywiście pod warunkiem, że krótszy kod nie jest zbyt "sprytnawy" (czyli niewymagający dodatkowych komentarzy). Nie powinno to być jednak usprawiedliwieniem do np. usuwania asercji.

0

A czy w Scali tak jest? Możesz zdefiniować sobie metodę &&. Czy takowa - bez argumentu by-name - oblicza (albo czy powinna obliczać) dany argument leniwie? W Boolean formalnie mamy zdefiniowaną ją jako &&(x: Boolean).

Hmm i tak żeby można było zastosować short-circuit to wyniki muszą być typu Boolean, czyli gdzieś tam po drodze musi nastąpić konwersja. Zrobiłem przykład, nie wiem czy jest sensowny: http://ideone.com/PvjGC
Konwersja implicit jak widać się nie wykonała przy && &&, ale przy && || już tak.

&& nie oblicza prawego argumentu jeżeli lewy to false. Jeżeli argumentami nie są Booleany, ani nie są one konwertowalne implicite do Booleanów, to nie ma wtedy jak rozgraniczyć sytuacji, w której potrzebne jest liczenie prawego. W ogóle semantyka prawdopodobnie nie będzie się zgadzać nawet.

Ale to już chyba wszedłem w zbyt abstrakcyjne rozważania :P

1

W Javie nie ma przeciążanie operatorów, a w C# jest, więc pytanie czy przeciążone operatory z C# zachowują leniwość?

w C# można przeciążyć operatory & i |, a przy spełnieniu dodatkowych warunków kompilator użyje ich jako leniwe && i ||. tak że leniwość będzie zachowana.

0

Jakie są te dodatkowe warunki?

0

Ja bym po prostu zaczął od sprawdzenia warunku i walnął wyjątkiem jeśli źle, skoro to jest 'niebezpieczna operacja'.

0
@Wibowit napisał(a)

&& nie oblicza prawego argumentu jeżeli lewy to false. Jeżeli argumentami nie są Booleany, ani nie są one konwertowalne implicite do Booleanów, to nie ma wtedy jak rozgraniczyć sytuacji, w której potrzebne jest liczenie prawego. W ogóle semantyka prawdopodobnie nie będzie się zgadzać nawet.

http://ideone.com/QG3UA

W Boolean jest:

final class Boolean extends AnyVal {
  def ||(x: Boolean): Boolean = sys.error("stub")
  def &&(x: Boolean): Boolean = sys.error("stub")
  // Compiler won't build with these seemingly more accurate signatures
  // def ||(x: => Boolean): Boolean = sys.error("stub")
  // def &&(x: => Boolean): Boolean = sys.error("stub")
}

Tu znalazłem o C#:
http://msdn.microsoft.com/en-us/library/aa691312(v=vs.71).aspx
Myślę, że to najlepsze rozwiązanie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1