try finallly ma swoje zalety

4

tęsknię za try finally które wykona się nawet jeśli w funkcji było jakieś exit ;) właśnie zmieniam coś w funkcji w C gdzie jest kilka razy return a muszę zwolnić na końcu mutexa.
Przytulcie mnie ;)

7

W ogóle uważam, że Pascal jest mega niedocenianym językiem.

Przytknęła do niego etykietka zabawki dla początkujących - bo w Delphi każdy mógł w 3 minuty po zainstalowaniu IDE zrobić swoją pierwszą "aplikację" w życiu - więc przecież prawdziwy zawodowiec nie będzie z czegoś takiego korzystać :(

5

C gdzie jest kilka razy return a muszę zwolnić na końcu mutexa.

Uwaga, nie zartuje. goto zamiast return. A po goto zwolnienie mutexa i dopiero wtedy return.

Jezeli nie pojdziemy w dogmaty to lokalne goto jest akceptowalne. Szczegolnie kiedy to duzo upraszcza. Co innego skakanie w calym programie gdzie popadnie (do tego nie zachecam) :) EDIT: A przeciez z tego co mowisz to i tak program nie jest napisany strukturalnie

Albo tak jak mowi @KamilAdam
If-ologia powinno sie dac zrobic z tego dokladnie 1 return.

2
Miang napisał(a):

właśnie zmieniam coś w funkcji w C gdzie jest kilka razy return a muszę zwolnić na końcu mutexa.

Czy to właśnie nie dlatego powinno się ograliczać ilość return w funkcjach?

2

Zapraszam do Rusta - robisz impl Drop i masz gwarantowany destruktor nawet przy panikującym wątku, bez konieczności myślenia o żadnym try... finally... :-)

struct Something {
    name: &'static str,    
}

impl Drop for Something {
    fn drop(&mut self) {
        println!("My name is {} and I'm leaving the scope!", self.name);
    }
}

fn main() {
    let foo = Something { name: "Foo" };
    
    if true {
        (Something { name: "Bar"});
        return;
    }
    
    println!("impossible");
}

// My name is Bar and I'm leaving the scope!
// My name is Foo and I'm leaving the scope!
4
Miang napisał(a):

właśnie zmieniam coś w funkcji w C gdzie jest kilka razy return a muszę zwolnić na końcu mutexa.

Takie return x z C to nic innego jak Exit(x) z Pascala — używa się wtedy, kiedy faktycznie potrzeba w danym miejscu wyskoczyć z funkcji, zwracając jakąś wartość. Jeśli wartość zwracana ma być ustawiona bez wychodzenia z funkcji, to w C używa się zmiennej lokalnej i do niej wpisuje wartości, a na końcu raz używa return.

W Pascalu ten problem nie istnieje, ze względu na istnienie wbudowanej w każdą funkcję zmiennej Result. Wartość zwracaną można ustawiać ile razy się chce, bez opuszczania funkcji. A jeśli gdzieś wcześniej w kodzie funkcji trzeba wyskoczyć, to Exit(x) załatwia sprawę. przy czym Exit nie jest obowiązkowy, więc nieważne czy się go wykona czy nie, ważne aby do zmiennej Result co najmniej raz coś wpisać. I to jest eleganckie rozwiązanie.


cerrato napisał(a):

W ogóle uważam, że Pascal jest mega niedocenianym językiem.

A no jest — mimo bycia podobnie funkcjonalnym co C++ (miejscami nawet z lepszą funkcjonalnością), a przede wszystkim z bycia znacznie bezpieczniejszym i ze znacznie przyjemniejszą składnią (bardziej rozwlekłą, ale czytelną).


stivens napisał(a):

Uwaga, nie zartuje. goto zamiast return. A po goto zwolnienie mutexa i dopiero wtedy return.

goto nie jest złem — to ludzie, którzy nie potrafili z niego korzystać przynieśli mu złą sławę. I takie czasy, że wielu na sam widok goto w kodzie od razu panikują i obrzucają autora kodu gównem.

Sam nie uważam goto za zło, o ile używa się go z głową. Użyte po to by zwiększyć wydajność kodu lub go drastycznie skrócić, jest absolutnie sensowne i zrozumiałe. Często można spotkać jego użycie w różnych algorytmach szyfrujących, w których skoki do różnych bloków instrukcji pozwalają po pierwsze uniknąć wywołań mnóstwa funkcji, a po drugie, zapisać całość w krótkiej i przyjemnej formie.

goto przydaje się też do implementacji instrukcji switch z C/C++, bo w Pascalu jest tylko case of, który posiada wbudowany (ukryty) Break w każdym bloku. Aby móc skakać po blokach case of tak jak przechodzi się z jednego bloku do drugiego w switch, można skorzystać właśnie z goto. W przeciwnym razie trzeba sztukować takie cuś z funkcji lub po prostu duplikować kod, a to dość słabe rozwiązanie. Lepiej po prostu zrobić zamiast case of przyjemną kupkę etykiet i goto, co działa dokładnie tak samo jak w C/C++ i nawet wizualnie podobne jest do switchów.

1
KamilAdam napisał(a):
Miang napisał(a):

właśnie zmieniam coś w funkcji w C gdzie jest kilka razy return a muszę zwolnić na końcu mutexa.

Czy to właśnie nie dlatego powinno się ograliczać ilość return w funkcjach?

int ret;
if(cośtam)
{
    ret = cośtamInnego;
}
else
{
    ret = jeszczeCośInnego;
}
return ret;

vs

if(cośtam)
{
    return cośtamInnego;
}
else
{
    return jeszczeCośInnego;
}

Wydaje się, że to drugie jest wyraźnie prostsze?

0
YetAnohterone napisał(a):

Wydaje się, że to drugie jest wyraźnie prostsze?

A jeśli będziesz miał:

int ret;
if(cośtam)
{
    ret = cośtamInnego;
}
else
{
    ret = jeszczeCośInnego;
}
doSomethingBeforeReturn();
return ret;

vs

if(cośtam)
{
    doSomethingBeforeReturn();
    return cośtamInnego;
}
else
{
    doSomethingBeforeReturn();
    return jeszczeCośInnego;
}

?
Oczywiścienajlepiej byłoby gdyby if był wyrażeniem a nie instrukcją i zwracał wartość (jak w Kotlinie, Scali, czy Haskellu)

int ret = if(cośtam)
{
    cośtamInnego;
}
else
{
    jeszczeCośInnego;
}
doSomethingBeforeReturn();
return ret;
0

@KamilAdam:

Prosi się o:

doSomethingBeforeReturn();
if(cośtam)
{
    return cośtamInnego;
}
else
{
    return jeszczeCośInnego;
}

Tak wiem, oba kody nie muszą mieć tej samej semantyki (warunek w ifie może mieć side effecty), ale zazwyczaj da się niewielkim kosztem doprowadzić do tego, by ten snippet, który napisałem wyżej, był poprawny

0

Miang: ktoś ma rozwiązanie twojego problemu XD Musisz tylko wcześniej zwalniać mutex XD — KamilAdam 11 minut temu

Rozumiem, że @KamilAdam twierdzisz, że to, co napisałem, jest bez sensu, bo nie można zwolnić mutexu przed sprawdzeniem warunku?

bool warunek = obliczWarunekNaPodstawieDanychObwarowanychMutexem();
zwolnijMutex();
if(warunek)
{
    return cośtam;
}
else
{
    return cośInnego;
}

Przyznaję, nie zawsze się tak da i nie zawsze jest sens.

....hmm po zastanowieniu może w tym wypadku to rzeczywiście nie ma sensu, nawet jeśli cośtam i cośInnego do obliczania nie wymaga obwarowania mutexem? Mutex powinien być zawsze zwalniany na samym końcu funkcji?

1

Mutex powinien być zawsze zwalniany na samym końcu funkcji

Nie

Mutex powinien być zawsze zwalniany

Tutaj clue

2

W C (GCC) możesz zrobić

pthread_mutex_t* mut __attribute__ ((__cleanup__(pthread_mutex_unlock))) = &global_mut;
pthread_mutex_lock(mut);

Oczywiście może to być sprzeczne z oczekiwaną logiką zwalniania tego konkretnego muteksa.

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