Snakker du om goto? Jeg tror du må zoome ut endel og fortelle oss hva du
lurer på, ikke hvor du stod fast.
--
In a fight against something, the fight has value, victory has none.
In a fight for something, the fight is a loss, victory merely relief.
70 percent of American adults do not understand the scientific process.
Ja
--
Tor <torust AT online DOT no>
men trenger noen andre måter å hoppe rundt i programmet mitt på, og sånne
while løkker er det nok av der frafør :)
mvh anders
Ikke for å være spydig, men det du trenger er kanskje å ta et skritt
tilbake, se over problemet på nytt, og komme opp med en bedre totalløsning?
Det kan av og til være tidsbesparende å kaste noe som ikke virker fremfor å
hacke på det til det gjør det, _selv_ om det som ikke virker tok lang tid å
lage!
--
Joachim
Har du lyst til å oppgi navnet på de kjøtthuene som har gjort noe så
_ubeskrivelig_ dumt?
| men trenger noen andre måter å hoppe rundt i programmet mitt på, og sånne
| while løkker er det nok av der frafør :)
enum { label_exit, label_A, label_B, label_C, label_D, ... } goto;
while (goto != label_exit) {
switch (goto) {
case label_A:
...
goto=label_C;
break;
.
.
Kan ikke forstå at det er mangel på slikt, hvis du bruker funksjoner,
switcher, if/else if/else... Uansett er goto og globals store nono's i
C/C++.
> On 24 May 2002 22:56:13 +0200, Bjorn Borud <borud...@borud.no> wrote:
>
>>| Uansett er goto og globals store nono's i C/C++.
>
>>jeg er ikke helt enig i at label og goto er noe man *aldri* skal
>>bruke. jeg har sett veldig mye komplett idiotisk kode for f.eks å
>>komme seg ut av nøstede loop'er der man burde brukt en enkel goto for
>>å komme seg ut og hoppe til riktig sted på slutten av funksjonen slik
>>at nødvendig opprydding gjøres før man returnerer.
>
> Ja, for å frigjøre rett ressurser i rett rekkefølge om en feil oppstår.
> Men ingen tør å bruke goto lenger, så da blir det skikkelig ekkel og
> hårete kode istedet.
Ikke det at jeg skal påstå at linux-kjerna er gjennomgående vakkert
koda (bare se på #include-kaoset som de diskuterer oppryddinga av på
lkml for tida), men de tør iallefall bruke goto :)
[ilmari@galadriel linux-2.5]$ grep -r goto .|wc -l
17179
Dette er 2.5.17 pluss litt patcher
--
ilmari
Dette er noe du er blitt fortalt fordi den som fortalte deg det innså at
det ville være farlig å fortelle deg sannheten. Vær vennlig å la være å
fortelle det videre -- hvis du da ikke vil at mer erfarne og dyktigere
programmerere skal le av deg som det har vært nødvendig å fortelle dette.
Dette er jo nettopp kjernedefinisjonen av "spydig". Du vet jo ikke om
han har gjort noe feil i det hele tatt. I mine øyne er det derimot helt
hjerneskadd å fjerne goto fra noe som skal kalle seg C.
| Det kan av og til være tidsbesparende å kaste noe som ikke virker fremfor
| å hacke på det til det gjør det, _selv_ om det som ikke virker tok lang
| tid å lage!
Av og til er goto beste løsning. Mange av de som har lært å programmere
av folk som ikke programmerer, skjønner ikke slikt.
Jeg hører mange sier dette, og de sier som regel også at
man skal kun ha ett retur punkt per funksjon, koden skal
flyte fritt og naturlig uten hopp fram og tilbake. Der
ryker i så fall også break og continue, men det jeg ikke
helt skjønner er hvordan man på dette grunnlaget kan hate
goto og sammtidig syntes C++ try/catch er flotte greier.
Hva er egentlig forskjellen mellom:
int foo()
{
int ret = 0;
try
{
bar();
...
}
catch (...)
{
...
ret = 1;
}
return ret;
}
og
int foo(void)
{
if (bar() != 0)
goto error;
...
return 0;
error: /* cleanup */
...
return 1;
}
Hva gjør den ene bedre/verre enn den andre?
MEN siden alle sikkert lurer her, så er det snakk om å programere en
mikrokontroller som skal kunne takle masse inputs og noe outputs (den skal
styre en step-boremaskin).
men takk for alle svar
mvh Anders
PS. Informatikk-læreren min her på skolen er også motstander av goto, og han
skulle så vise et eksempel som da skulle være mye bedre, men det er den
værste spageti-loop programeringa jeg har sett :)
Noen mennesker har ikke rukket å skjønne eller lære seg de enkleste
logiske lover, så dette med selvmotsigelser er ikke et problem for dem.
Tvert imot, det er en _feature_ at de kan bruke goto hvis den heter break
eller continue. Jeg tror det er slik at goto er et minusord, slik at
folk som har omtrent 75 i IQ kan se på listen sin over stygge ord og
finne at try og catch og break og continue ikke er på listen over stygge
ord, så da kan de bruke dem. Men ikke bruke goto og globals, for det er
store nonos, for hvis man sa goto i barnehaven, måtte man gå og vaske
munnen sin. Sånt sitter i lenge hvis man ikke er så veldig smart.
> Men det mest irriterende med compilatoren til atmels avr, er at goto er
> reservert som ord og får fet skrift som de andre.
GCC kan generere kode for desse AVR-greiene. Sjå på
http://gcc.gnu.org/install/specific.html#avr. Viss du tilfeldigvis
bruker FreeBSD, så ligg det ein cross-compiler-port av GCC for AVR i
/usr/ports/devel/avr-gcc.
(Og GCC støttar sjølvsagt goto, om det var noka tvil om det.)
--
johs
Kanskje ikke mange, men ihvertfall har er potensialet der.
| MEN siden alle sikkert lurer her, så er det snakk om å programere en
| mikrokontroller som skal kunne takle masse inputs og noe outputs (den
| skal styre en step-boremaskin).
Det fremgikk at du egentlig ville implementere en tilstandsmaskin, ja. Å
gjøre det uten goto er egentlig meningsløst. Men den fakede goto'en min
med en diger switch vil gjøre susen.
| PS. Informatikk-læreren min her på skolen er også motstander av goto, og
| han skulle så vise et eksempel som da skulle være mye bedre, men det er
| den værste spageti-loop programeringa jeg har sett :)
Alle som skal vise at goto er feil, går i den fellen, for at goto er feil
er en sånn fix idé som får smarte mennesker til å oppføre seg veldig dumt
og dumme mennesker til å gjenta misforståelsen til krampa tar dem.
For et par år siden tok jeg MC-lappen. Under en kjøretime spurte jeg
om bremsing i sving, og fikk vite at det var livsfarlig av
kjørelæreren.
Etter å ha hatt sykkel i to måneder kjørte jeg ut i sving fordi jeg
ikke turte bremse. Sånt gjør man jo ikke, og det hadde jeg blitt
fortalt av en person som var profesjonell.
Senere har jeg tatt flere kjørekurs. En av øvelsene som går igjen er
brems i sving, mer eller mindre uten unntak.
Det her er samme greia. Det du skriver over bunner enten i mangel på
egen behersking av goto, eller frykt du har fått fra andre.
Geir
goto behersker jeg bra det, brukte det mye i "gamledager" da vi programerte
spill på kalkulatoren vår (ti-82) som jeg fortsatt har glede av :)
Det er et viktigere prinsipp, at en funksjon er lesbar og har minimalt
med return statements. Funksjoner skal i utgangspunktet ha en
inngang og en utgang. Amen. ;-)
I tilfeller hvor alternative metoder er mindre lesbare, så bruker mange
goto. De som har hatt en bad-trip tidlig i karriæren, med en
300 000 linjers spaghetti sak i gammel Fortran, overdriver ikke
bruken av goto...C har i det minste ikke aritmetisk IF! :-)
De har hørt litt for mye på Dijikstra. En "C" kompilator som ikke
støtter goto, er _ingen_ C kompilator! Har de fjærnet continue også?
> men trenger noen andre måter å hoppe rundt i programmet mitt på, og
> sånne while løkker er det nok av der frafør :)
Prøv å splitt opp i flere funksjoner. Har du dyp nøsting, så kan du
alternativt innføre en state variabel:
state = NOK;
for(...)
for (j=0; j<N && state == NOK; j++)
if (...)
state = OK;
En annen teknikk på å simulere goto er å innføre en "løkke" som
eksekveres _en_ gang:
do
{
if (...)
break;
...
} while (0);
men denne metoden virker ikke like godt, hvis funksjonen har
for/while løkker.
Jamen... Det som er så morsomt. Jeg hadde en stygg opplevelse med
akkurat det for en 13 års tid siden eller så. Vi satt og oversatte
noe gammel Algol-kode, og fant en konstruksjon med 2 aritmetiske
if'er, og et sted mellom 7 og 12 goto'er. Når vi var ferdig med å
nøste, satt vi igjen med en ganske liten if/then/else. :)
Enkelte ting er det kanskje best at ikke så mange husker lenger, ja.
-Harald
--
Harald Nordgård-Hansen, Linpro AS <>< http://www.linpro.no/~hnh/
PB. 375, N-1601 Fredrikstad, Norway Phone/Fax: +47 6935 2424/25
Ta følgende eksempel, jfr. slik som Thore B. Karlsen også nevnte, så
er goto fin ved trinnvis allokering av ressurser, der alle må
frigjøres etter tur hvis en allokering feiler.
int init_resources(void) {
if (allocate_rec(1)) goto fail_3;
if (allocate_rec(2)) goto fail_2;
if (allocate_rec(3)) goto fail_1;
if (allocate_rec(4)) goto fail_0;
return OK;
fail_0: free_rec(3);
fail_1: free_rec(2);
fail_2: free_rec(1);
fail_3: return NOT_OK;
}
Hvis du har tid så hadde det vært interessant om du kunne finne ut
hvordan læreren din vil la ovenstående snutt se ut på en mer lettlest
og elegant måte, uten bruk av goto.
Jeg har sett at lure folk har implemetert tilstandsmaskiner vha. tung
bruk av goto, og som jeg tror hadde vært veldig lite lesbare på andre
vis.
Jeg synes at anti-goto-folkene er noen ordentlige raringer, jeg.
--
Øystein Svendsen
int init_resources(void)
{
void *p1,*p2,*p3,*p4;
p1 = allocate_rec(1);
p2 = allocate_rec(2);
p3 = allocate_rec(3);
p4 = allocate_rec(4);
if (!p1 || !p2 || !p3 || !p4)
{
free_rec(p4);
free_rec(p3);
free_rec(p2);
free_rec(p1);
return 1;
}
return 0;
}
La allocate_rec() returnere NULL ved feil og free_rec() gjøre
ingenting ved NULL argument (eller tilsvarende intern funksjon
hvis argumentene er noe annet enn pekere til allokerte objekter).
Jeg syntes faktisk denne er mere oversiktelig. Alternativt kunne
du kansje gjøre (muligens bedre ytelse ved error-condition hvis
det måtte bety noe),
int init_resources(void)
{
void *p1,*p2,*p3,*p4;
p1 = p2 = p3 = p4 = NULL;
if ((p1 = allocate_rec(1)) == NULL)
goto error;
if ((p2 = allocate_rec(2)) == NULL)
goto error;
if ((p3 = allocate_rec(3)) == NULL)
goto error;
if ((p4 = allocate_rec(4)) == NULL)
goto error;
return 0;
error:
free_rec(p4);
free_rec(p3);
free_rec(p2);
free_rec(p1);
return 1;
}
Var det noe slikt du mente?
Denne er ikke ekvivalent med koden jeg postet, og forutsetter andre
omgivelser enn det jeg gjorde.
| free_rec(p4);
| free_rec(p3);
| free_rec(p2);
| free_rec(p1);
| return 1;
| }
|
| Var det noe slikt du mente?
Egentlig ikke, fordi du potensielt kaller free_rec med NULL som
argument. Min kode gjorde nøyaktig det som var nødvendig, og den
unngikk å kalle free_rec når det ikke var nødvendig (og om mulig
ulovelig), og slik at leseren slipper å måtte bry seg om hva som skjer
om man kaller free_rec unødig med NULL som argument.
Ikke det at din måte er ille, men hvis man ikke har lov til å kalle
free_rec uten at man har foretatt et vellykket kall til allocate_rec
for samme ressurs, så blir koden endel mer grisete enn det du gjorde
her.
Mitt poeng var at koden skulle være helt ekvivalent med koden min,
dvs. at akkurat samme rekkefølge og antall kall til free
og allocate skulle være lik. (Bare for øvelsens skyld.)
--
Øystein Svendsen
Du har rett. Jeg tenkte mere på en generell løsning hvor disse
funksjonene var noe man selv hadde skrevet. Ved å gi free_rec()
og allocate_rec() den oppførselen jeg tok utgangspunkt i, ville
resten av koden bli enklere.
> | free_rec(p4);
> | free_rec(p3);
> | free_rec(p2);
> | free_rec(p1);
> | return 1;
> | }
> |
> | Var det noe slikt du mente?
>
[...]
> Mitt poeng var at koden skulle være helt ekvivalent med koden
> min, dvs. at akkurat samme rekkefølge og antall kall til free
> og allocate skulle være lik. (Bare for øvelsens skyld.)
>
OK, tilbake til tenkeboksen. Jeg skal prøve igjen :-)
Dette er rett og slett feil. Ofte er goto en god løsning, men det er
liten tvil om at bruken av goto helt klart kan overdrives. Java har
utelatt goto, men der kan man bruke labeled break (for å hoppe ut av
en nøstet loop). Problemet er at mange har endt opp med å skrive
veldig ustrukturert kode, fordi de har overdrevet bruken av goto. Men
mange problemer løses rett og slett bedre med gotos.
Her blir jeg bare nødt til å referere til gode gamle Donald Knuth, og
hans "Structured programming with goto statements":
http://pplab.snu.ac.kr/courses/PL2001/papers/p261-knuth.pdf . Forøvrig
fylte nettopp Knuth 1000000 år. :) For de som ikke vet hvem Donald E.
Knuth er, kan dere ta en titt hjemmesiden hans:
http://sunburn.stanford.edu/~knuth/ . The Art of Computer Programming
anbefales forøvrig innkjøpt av alle som har interesse for
programmering og algoritmer. Er det forresten flere som gleder seg til
volume 4 og 5 forhåpentligvis kommer i henholdsvis 2007 og 2009? =)
Mvh
Jørund Leknes
int init_resources(void)
{
int i, error=0;
for (i=0; i<4 && !error; ++i)
error = allocate_rec(i+1);
if (error)
{
while (--i) free_rec(i);
return NOT_OK;
}
return OK;
}
Nå da? Ikke den peneste koden jeg har sydd sammen kansje,
men følger ikke denne kravene dine i det minste?
Vel, det høres gjerne ut som om jeg kverulerer nå, men det er slik at
når man allokerer ressurser sekvensielt, så er det gjerne slik at man
foretar forskjellige kall til helt ulike funksjoner, slik at du ikke
kan bruke en indeksvariabel til å nøste deg tilbake.
Eksemplet som jeg ga opprinnelig var kanskje litt dårlig egnet til å
vise hva jeg mente.
Et eksempel fra den virkelige verden, fra forrige gang jeg rotet meg
borti en goto-disputt (jeg hadde gjerne ordlagt meg annerledes i dag):
http://groups.google.com/groups?q=svendsen+goto&hl=en&lr=&selm=86r90uu2tw.fsf%40seabed.no&rnum=2
--
Øystein Svendsen
Array med referanser og funksjons-pekere da? Erh, da må jeg vel
bare si at goto versjonen høres penere ut. Nå som jeg har sett
den ene siden av historen og feilet stygt med å vise den andre
siden, har du noen brukbar løsning på dette uten goto's?
>
> Eksemplet som jeg ga opprinnelig var kanskje litt dårlig egnet
> til å vise hva jeg mente.
>
Det så ut som de andre skjønte hva det gikk ut på, så det er nok
heller meg som har litt for liten erfaring til å henge med på hva
noen av dere prater om. Vel, jeg prøvde i det minste. Takker for
tålmodigheten ;-)
Ikke jeg. Det er derfor jeg bruker goto.
--
Øystein Svendsen
| jeg tror du akkurat illustrerte hvorfor det er synd at mange unngår
| goto i endel situasjoner der den har sin plass utelukkende fordi de
| har hørt at det er noe de skal unngå.
regelen om å forby goto har et helt klart pedagogisk poeng.
folk som ikke kjenner til argumentene mot goto, bruker det feil altfor
mye. derfor har pedagogene funnet ut at dersom man forbyr goto, vil
folk skrive bedre kode.
så er problemet om folk vil skjønne når goto har sin funksjon når de er
blitt så gode at de kan sette spørsmålstegn ved det de har lært.
problemet her er at veldig mange mennesker, selv veldig flinke
mennesker, har store problemer med å sette spørsmålstegn ved det de har
lært.
sjøl har jeg skrevet bare to ordentlige systemer som har gjort noe
fornuftig, begge på ca. 5000 linjer og helt uten goto, men i begge
tilfeller ble høynivåspråk brukt, og det virker ut fra diskusjonen her
i hvert fall som om at goto har mest å si i algoritmefikling.
--
Rolf Lindgren http://www.roffe.com/
ro...@tag.uio.no
ønsker du å skrive slik at folk faktisk leser det du skriver? gode råd på:
http://home.online.no/~vidaandr/news/OBSquoting.html
Vi vet du er dum, nå. Ingen grunn til å flire og le som en idiot, også.
eg veit ikkje om eg synest dette var det beste eksempelet.
if (! allocate_rec(1)) {
if (! allocate_rec(2)) {
if (! allocate_rec(4)) {
if (! allocate_rec(4)) {
return OK;
}
free_rec(3);
}
free_rec(2);
}
free_rec(1);
}
return NOT_OK
eg trur det er ein smakssak kva for ein variant ein føretrekk. eg
likar den eksplisitte nøstinga, spesielt om ein skal flette inn meir
kode. her er det også lett å skilje indre delar av nøstinga ut i
eigne funksjonar viss funksjonen skulle vekse drastisk.
> Jeg har sett at lure folk har implemetert tilstandsmaskiner
> vha. tung bruk av goto, og som jeg tror hadde vært veldig lite
> lesbare på andre vis.
switch er ein glorifisert goto som ofte gjer slik kode ryddig og
oversiktleg. men for all del, eg trur deg på ditt ord :-)
> Jeg synes at anti-goto-folkene er noen ordentlige raringer, jeg.
det er aldri bra å vere fanatisk for eller mot noko.
--
Kjetil T. your computer can help researchers understand how
proteins work. http://folding.stanford.edu
Men da må det være bra å være fanatisk for eller mot noe noen ganger.
Jeg synes at mange nøstinger gjør ting betraktelig mer vanskelig å
lese, og for raringer som meg som har c-basic-offset satt til 8, så er
ikke dette heller noe godt alternativ. Spesielt hvis det er mye kode
inne i strukturen synes jeg ting kan bli ganske ille.
| det er aldri bra å vere fanatisk for eller mot noko.
Det er sant.
--
Øystein Svendsen
Dette har med å gjøre hvor mange mentale baller du kan i luften samtidig.
Det er et kjent problem at menneskehjernen selv med solid trening ikke
klarer mer enn 8, og mennesker som har så kort attention span at de kan
se Batman-filmer klarer ikke mer enn 3-4. Nesting er en måte å gi folk
flere ting å holde styr på samtidig, men det behøver ikke leses slik.
Det kan leses som at du får _færre_ ting å holde styr på, siden du har
_fjernet_ betingelser dess lenger inn i nestingen du kommer, slik at
koden gjelder for et mindre antall frie betingelser.
Dersom du _ikke_ klarer å se verden slik, vil du aldri noensinne kunne
bli en god programmerer, men vil vegre deg for å introdusere sjekker for
betingelser som faktisk finnes fordi koden din øker i kompleksitet når du
legger til slik kode. Ser du dette fornuftig, minker kompleksiteten i
koden som er dypest nestet -- den kjenner hele sin verden.
En parallell til noe en vennegjeng snakket over noen øl om etter å ha
sett Star Wars episode II igår: Meneskets DNA er på endel områder mye
enklere enn amøber fordi moren sørger for det miljøet som cellene skal
utvikle seg i, mens en amøbe må leve i havvann av ukjent temperatur,
mineralinnhold, pH-verdi, etc. Den samme korrelasjonen kommer til syne i
kode som vet den kan stole på exception handling for å ta seg av forhold
som ikke er mulig å forsvare seg mot, i forhold til kode som hele tiden
må undersøke at verden henger sammen.
C er typisk "ukjent-verden"-sprog, der du må sjakke returverdier for alle
systemkall og funksjoner du kaller, og selv bære på kode for å rydde opp,
noe som nettopp var saken her. I en smartere verden, ville du enten ha
automatiske kall til destructors eller garbage collection som frigjorde
ressursene. I en ideell verden, har du sproglige konstruksjoner som
garantert blir kjørt uansett hva slags exception handling som foregår.
I Java må man fortelle hvilke exceptions man skal være forberedt på, og
det er ikke så veldig lurt, men mye lurere enn C der man må sjekke alt
selv hele tiden. I Common Lisp bruker man unwind-protect for å sørge for
at kode blir utført på vei ut av koden. Sprog kan dømmes på basis av om
de har eller ikke har unwind-protect. I de som ikke har det, finnes det
faktisk _ingen_ mekanismer for å sikre at ressurser blir frigjort om det
skulle skje noe man ikke har tenkt på. Dermed øker kompleksiteten til
kode som skal ta dekning for alt, og dyp nesting er et symptom på hvor
mye "forsikring" man må pakke inn kode som skal stole på verden, men det
er uhyre viktig at man ser på dette som at usikkerheten fjernes dess
dypere man kommer, ikke at man ser på hele funksjonen og tror at den er
mer komplisert. Det samme gjelder f eks for arbeidstagerforhold. Fordi
vi har arbeidsmiljøvernloven, som ikke er noen spøk å beherske, kan man
klare seg med små arbeidskontrakter, men kostnaden er at ledere må lære
loven å kjenne og sørge for å følge den, hvis de ikke skal gå i fellen
som flere og fler udugelige ledere gjør for tiden mens man skalerer ned
firmaer og "bommer" på masseoppsigelsesparagrafen og slikt. Dersom alle
arbeidsgivere og arbeidstagere hadde full kontraheringsfrihet, ville de
ha måtte finne opp arbeidsmiljøvernloven selv og ha arbeidskontrakter på
mange hunder sider. Dermed må man forstå kompleksiteten som øker ved at
man har en komplisert arbeidsmiljølov som beskyttende og forenklende for
de som lever innenfor den.
| | det er aldri bra å vere fanatisk for eller mot noko.
|
| Det er sant.
Det er dessverre en meningsløs påstand.
Jeg tror det er vesentlig å forstå at det overstående er tegn på en mye
dypere innsikt i programmeringsverdenens faktiske vilkår enn kode som
bare tror dette handler om å ""gjøre ting. Ved å lese denne koden, kan
jeg se at "return OK" skjer bare i en verden der alt man har forsvart seg
mot ikke har funnet sted. Forsvarsmekanismene som ligger rundt denne
funksjonen, beskytter det innerste mot all skade og ødeleggelse. Hvordan
man må sette opp forsvarsverket varierer sterkt, men ved å gi en god
visuell indikasjon på hvor godt man har beskyttet den virkelige koden,
har man også sørget for å kommunisere at man lever i en komplisert verden
som det er verd å forsvare seg mot.
Skulle jeg ha gitt karakter for de to forsøkene, ville jeg ha gitt beste
karakter til Kjetil, og absolutt laveste ståkarakter til if-goto-koden
som lar forsvarsverket bestå av _uavhengige_ komponenter. Det er med
andre ord lett å bryte ned forsvarsverket gjennom vedlikehold av koden,
mens (enda) dypere nesting vil kommunisere ytterligere sikringstiltak.
| eg likar den eksplisitte nøstinga, spesielt om ein skal flette inn meir
| kode. her er det også lett å skilje indre delar av nøstinga ut i eigne
| funksjonar viss funksjonen skulle vekse drastisk.
Dette siste er ikke minst viktig. Ved at man skiller ut funksjoner som
lever i en mer beskyttet verden enn annen, og man er klar over hvordan
den kalles, gjerne gjennom sikrede portaler, kan man skrive kode i en mye
tryggere verden. Dette er ikke noe C-folk setter overvettes høy pris på,
ser det ut som, men det er desto viktigere at man er klar over at man
faktisk _kan_ bygge seg tryggere programmeringsomgivelser. Java's
sandbox er ett eksempel på det, som gjør helt andre ting mulig enn det
vettuge mennesker (dvs, folk utenfor Microsoft) _ikke_ tør gjøre på grunn
av sikkerhetsrisikoen. Common Lisp's _mye_ tryggere verden har avfødt et
mye høyere abstraksjonsnivå fordi man er nettopp er _trygg_ på at ikke et
element av tankeløshet et eller annet sted har underminert verden man
lever i.
Dette er også grunnen til at C++ er så ubeskrivelig jævlig: Du kan ikke
forsvare deg mot noe som helst av det som skjer "av seg selv" i C++, og
dess høyere du bygger, dess mer fragilt og porøst blir forsvaresverket
ditt. C++ er trolig det mest paranoide sproget som noensinne er laget,
men nettopp fordi det er paranoid og ikke trygt, skapes det langt flere
problemer enn man noensinne kan ha tid til å løse.
java.lang.RuntimeException. Kaster du noe basert på en slik passerer
den glatt gjennom alle de prosedurelle lagene dine udeklarert og
terminerer i verste tilfelle JVM-en din dersom du ikke fanger den.
Geir
<snip>
> Funksjoner skal altså være maks 20 linjer, ha ingen gotos, og kun ett
> returpunkt. Null problem.
>
> bool isthisretarded()
> {
> int i, j, k, l, m;
> double pi, e, sqrt2;
> bool succ = true;
C gruppe nå, ikke bruk .cpp i filnavnet. ;-)
> succ = succ && onlyusedonce1(&i, &j, &k, &l, &m, &pi, &e, &sqrt2);
> succ = succ && onlyusedonce2(&i, &j, &k, &l, &m, &pi, &e, &sqrt2);
> succ = succ && onlyusedonce3(&i, &j, &k, &l, &m, &pi, &e, &sqrt2);
> succ = succ && onlyusedonce4(&i, &j, &k, &l, &m, &pi, &e, &sqrt2);
> succ = succ && onlyusedonce5(&i, &j, &k, &l, &m, &pi, &e, &sqrt2);
succ = onlyusedonce1(&i, &j, &k, &l, &m, &pi, &e, &sqrt2)
&& onlyusedonce2(&i, &j, &k, &l, &m, &pi, &e, &sqrt2)
&& onlyusedonce3(&i, &j, &k, &l, &m, &pi, &e, &sqrt2)
&& onlyusedonce4(&i, &j, &k, &l, &m, &pi, &e, &sqrt2)
&& onlyusedonce5(&i, &j, &k, &l, &m, &pi, &e, &sqrt2);
Jeg bruker goto, så dette er bare for øvelsen sin skyld:
int init_resources(void)
{
int ok = OK;
if (allocate_rec(1))
ok = NOT_OK;
if (ok && allocate_rec(2))
free_rec(1), ok = NOT_OK;
if (ok && allocate_rec(3))
free_rec(2), free_rec(1), ok = NOT_OK;
if (ok && allocate_rec(4))
free_rec(3), free_rec(2), free_rec(1), ok = NOT_OK;
return ok;
}
tror jeg foretrekker goto løsningen...
Hva med lavere fart Geir? Bremse før svingen? La du deg nok
ned til siden? Det var kanskje flere grunner til at du kjørte ut?
> Det her er samme greia. Det du skriver over bunner enten i mangel på
> egen behersking av goto, eller frykt du har fått fra andre.
Selv om man, behersker og tør å gjøre goto "ut av en sving", så
vil goto misbrukere kunne påføre andre store smerter. De som
har følt slik fysisk smerte på kroppen selv, føler nok sinne og sorg
ved tanken på slikt kunne vært unngått "med litt lavere fart inn" i
svingen... ;-)
Bremse før svingen er noe man gjør _før_ svingen.
Lavere fart er av akademisk interesse når man allerede er oppe i
problemer og _må_ svinge. Man brekker ikke ned når man har fått
beskjed om at det er livsfarlig.
Grunnen til at jeg kjørte ut var at jeg hadde fått meg fortalt at det
var farlig å bremse og svinge samtidig, samt at ingen hadde fortalt
meg noe om overlevelsesreaksjoner og hvorfor de ikke gir mening i
trafikken. Det var tydeligvis for mye informasjon, som jeg ikke ble
tiltrodd.
Farten var det ingenting feil med. Jeg hadde helt utmerket klart den
svingen i nærmere doble hastigheten av det jeg holdt dersom det hadde
skjedd i dag. Da hadde jeg også vært mer eller mindre nøyaktig to
ganger over fartsgrensen. Problemet var manglende opplæring.
Har du sykkellappen? Jeg tar gjerne en lengre diskusjon om dette
temaet på mail, om du vil.
> Selv om man, behersker og tør å gjøre goto "ut av en sving", så
> vil goto misbrukere kunne påføre andre store smerter. De som
> har følt slik fysisk smerte på kroppen selv, føler nok sinne og sorg
> ved tanken på slikt kunne vært unngått "med litt lavere fart inn" i
> svingen... ;-)
Det her synes jeg slett ikke er noe å komme draende med fårete flir
om. Jeg fatter og forstår ikke hvorfor informasjon om hvorfor goto er
fy, i motsetning til "goto er fy", er feil.
Geir
<snip>
> Skulle jeg ha gitt karakter for de to forsøkene, ville jeg ha gitt
> beste karakter til Kjetil, og absolutt laveste ståkarakter til
> if-goto-koden
Kode med bug som (nesten) ingen ser, er ikke akkurat lesbar.
Uansett, så mener jeg goto-løsningen bedre egnet for reell kode. Det
å ha dyp nøsting, blir _mye_ mer uleselig når en slik funksjon er noe
mer enn et leke eksempel.
Det var da fælt, da.
Når jeg skriver kode prøver jeg å unngå situasjoner der det frister å bruke
goto. Dette pleier jeg å klare fint også (hemmeligheten ligger i det at jeg
holder koden min med en relativt konsis og pen, gjennomført stil). Om jeg
til nøds må ty til globals, gjør jeg dem i det minste statiske til en
header. Om dette skyldes at jeg rett og slett ikke ser vitsen med goto,
eller mang en dårlig erfaring fra bl.a. BASIC, vet jeg ikke.
Uansett ser jeg det som en svak design hvis man tar goto i bruk. Jeg hører
mange syter over hva man skal gjøre hvis man skal renske opp på slutten av
koden, og her kan jeg kanskje se at goto er grei til nøds. Men jeg ville
fortsatt heller gjort slik:
inline static void CleanUp(ClassThatNeedsCleanUp *ctncup1,
ClassThatAlsoNeedsCleanUp *ctncup2)
{
if(ctncup != NULL)
{
ctncup1->CleanUp();
delete ctncup1;
}
// do the same with ctncup2...
}
bool InitializeSomething(THING *pTheThing)
{
ClassThatNeedsCleanUp *ctncup1 = NULL;
ClassThatAlsoNeedsCleanUp *ctncup2 = NULL;
// initialization code here...
// oops.. something went wrong
if(SomethingFailed() == true) CleanUp(ctncup1, ctncup2);
// everything suceeded
CleanUp(ctncup1, ctncup2);
return true;
}
enn å bruke goto aternativet. Men det er nå bare min mening. Det eksempelet
jeg ga ovenfor var kanskje litt tynt, da CleanUp() kunne blitt kalt i
destructoren, men
det hadde vært det samme med f.eks. en device context i Windows.
PS. Kanskje du burde senke farten før svingen, da :-)
Jeg synes det virker som om dere er motstandere av å slenge brackets på
if'en, jeg ;-p
Og du ser ingenting galt med denne API'en, men heller noe med nesting av
if-setninger? Jeg blir litt imponert over den grad av indoktrinering og
hjernevask som Redmond-foretaket klarer å bedrive uten engang å dope ned
folk.
| if (::CreateWindowEx(
| WS_EX_CLIENTEDGE, "MDICLIENT", (LPCTSTR) NULL,
| WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
| r.GetLeft(), r.GetTop(), r.GetWidth(), r.GetHeight(),
| GetHandle(), (HMENU) m_ClientID,
| ::VGetInstanceHandle(), (LPSTR) &ccs))
La meg gjette på at du gjør dette i full form ganske ofte, siden du tar
det opp i en slik sammenheng. Det er rett og slett imponerende at folk
ikke reiser seg i protest og gir til kjenne sin avsky mot denslags
ørkesløs og tanketom dumhet i designet av ting de må arbeide med. Jeg
mener, om du for å svinge bilen din, måtte regne ut en masse komplisert
fysikk og taste inn en mengde vektorer i full fart før du kjørte i en
fjellvegg, autovernet, en bygning, etc, ville man ikke ha utdannet folk
til denslags og syntes det var en kjempelur ting, noen smarte mennesker
ville ha skjønt at man bare kunne finne opp ett analogt ratt og analoge
bremser, selv om det var noe slikt som et romskip som skulle kjøre veldig
fort i veldig vekslende gravitasjonsfelt. En trenger bare se på hvordan
moderne jagerfly styres for å forstå at interfaces til kompliserte ting
kan gjøres fornuftige og enkle. Å se på Windows-kode får meg til å tro
at enkelte mennesker vil tilbake til UUCP heller enn å bruke domener og
direkte adressérbare maskiner. Jeg er egentlig umåtelig imponert over at
ingen har skutt Bill Gates og lagt hele Redmond i ruiner.
> [Holmberg Anders]
> | PS. Informatikk-læreren min her på skolen er også motstander av goto,
> | og han skulle så vise et eksempel som da skulle være mye bedre, men det
> | er den værste spageti-loop programeringa jeg har sett :)
>
> Ta følgende eksempel, jfr. slik som Thore B. Karlsen også nevnte, så
> er goto fin ved trinnvis allokering av ressurser, der alle må
> frigjøres etter tur hvis en allokering feiler.
>
> int init_resources(void) {
>
> if (allocate_rec(1)) goto fail_3;
> if (allocate_rec(2)) goto fail_2;
> if (allocate_rec(3)) goto fail_1;
> if (allocate_rec(4)) goto fail_0;
>
> return OK;
>
> fail_0: free_rec(3);
> fail_1: free_rec(2);
> fail_2: free_rec(1);
> fail_3: return NOT_OK;
> }
>
Alt for mange linjer. Hva med denne koden?
int alloc_stuff(void)
{
int i = alloc(1);
i = i && alloc(2) || i && (Free(1));
i = i && alloc(3) || i && (Free(2), Free(1));
i = i && alloc(4) || i && (Free(3), Free(2), Free(1));
return i;
}
Totalt uforståelig og full av unødige tester. Eksekverer sikkert mange
ganger tregere enn gotokoden, og er vanskelig å vedlikeholde. Men den
virker og har jo en fascinerende symmetri :-)
Kanskje goto har sine bruksområder likevel? hmm...
Bjørn
PS: Free() må alltid returnere 0.
<snip c++ eksempel i en C-diskusjon>
> if(SomethingFailed() == true) CleanUp(ctncup1, ctncup2);
^^^^^^^
Kardinalfeil. Ikke ta mitt ord for det, les her:
http://www.eskimo.com/~scs/C-faq/q9.2.htmlDette ser man dessverre alt
for mange gjøre, selv erfarne programmerere.
--
Roland Kruse
Real e-mail address: rkruse AT online DOT no
Registered Linux user number 142277
<snip c++ kodeeksempel i en c-diskusjon)
> if(SomethingFailed() == true) CleanUp(ctncup1, ctncup2);
^^^^^^^
Kardinalfeil. Ikke ta mitt ord for det, les her:
http://www.eskimo.com/~scs/C-faq/q9.2.html
Dette ser man dessverre alt for ofte, selv av erfarne programmerere.
Ellers synes jeg du skulle forklare eksemplet ditt, jeg skjønte ikke
hvor du vil hen med det (og jeg har programmert C siden ca 1985)
:-)
ja, det var ein floskel. eg prøver å unngå goto, men er ikkje
fanatisk sidan det stundom må det til. eg trur faktisk at labelen
"retry" er vanlegare i mi kode enn "fail"; retry-kode er
svinevanskeleg å få til pent utan goto.
Uff. Fortran koden jeg sloss med, hadde "noen" flere GOTO og
aritmetiske IF. Aritmetisk IF må være djevelens værk nummer 1.
> Enkelte ting er det kanskje best at ikke så mange husker lenger, ja.
Enkelte ting er det ufattelig vanskelig å glemme...halvmeter
tykk program print, full av notater på hva i helvete koden gjorde.
Obfuscated C Contest? OK, her er mitt bidrag
int init_resources (void)
{
return (!alloc_rec(1)
&& (!alloc_rec(2) || (free_rec(1),0))
&& (!alloc_rec(3) || (free_rec(2),free_rec(1),0))
&& (!alloc_rec(4) || (free_rec(3),free_rec(2),free_rec(1),0))) ?
OK : NOT_OK;
}
burde ha testet faenskapet ... men skitt au.
Virkelig? Og å bruke andre verktøy for å gjøre dette enn å skrive ting
manuelt slår deg ikke som en _nødvendighet_? Jeg tror man ville tjene
veldig mye mer om man faktisk klarte å bli kvitt det idiotiske tullet til
Microsoft og ikke minst laget noe oppå skrotet deres som man kunne stole
på og snakke pent med. En må ikke la deres inkompetanse bli ens bane.
| Dette var forøvrig fra en løsning jeg kokte opp for å abstrahere slik
| galskap, slik at jeg slapp å gjøre det i hovedkoden.
Da er du nesten tilgitt, men det er uhyre viktig å forstå at kode som
fjerner problemer og som tillater produktiv abstraksjon ikke behøver å
være vakker og leselig. Tvert imot, hensikten er at annen kode skal bli
vakker og leselig. Klarer du å pakke så mye jævelskap inn i slik kode
som mulig slik at du kan leve i en tryggere, penere verden utenfor (eller
innenfor, alt ettersom), er jo dét bare en fordel. Det er feil å tro at
_all_ kode må være pen. Jeg blåser i om innsiden av søppelkassene i Oslo
er gullende rene -- det er det utenfor jeg synes det er viktig er rent --
det kan faktisk være aldeles forjævlig inni søppeldunkene sålenge parken
den står i er fri for skrot. Det samme kan sies om den nydelige biffen
jeg spiser med et glass fyldig, god rødvin -- skulle jeg ha vært der når
oksen ble skutt i pannen med slaktepistol og partert til akkompagnement
av fossende blod og stinkende innvoller eller de gjødslet vinrankene med
dyredritt og gjæret vinen i illeluktende fabrikker, ville jeg aldri i
livet ha kunnet nyte måltidet. Generelt gjelder at ting som er pent,
ikke er pent å lage. Endel uerfarne programmerere har en tendens til å
tro at det som lager pene ting også må være pent. Det er feil. En slik
holdning gjør at folk som ikke lykkes i å lage pene ting tror de _må_ gi
opp helt og lage aldeles forjævlig stygge ting, istedet. Som Windows.
> eg trur faktisk at labelen
> "retry" er vanlegare i mi kode enn "fail"; retry-kode er
> svinevanskeleg å få til pent utan goto.
En for lite brukt konstruksjon i slike tilfeller er
do ... while.
Ikke dermed sagt at det ikke finnes eksempler på at "goto retry" er den
beste måten (har gjort det selv), men jeg har ofte ved nærmere
ettertanke funnet at det kan uttrykkes penere i en do ... while løkke.
Roland Kruse
--
My real e-mail address is: rkruse AT online DOT no
(the hotmail address is a spambox)
> Ja, for å frigjøre rett ressurser i rett rekkefølge om en feil oppstår.
> Men ingen tør å bruke goto lenger, så da blir det skikkelig ekkel og
> hårete kode istedet.
Jeg tør, og her i avdelingen med 40+ utviklere (Visma/Rubicon) og millioner
av kodelinjer så er det ennå ingen som har funnet en bedre måte og enklere
måte og håndtere opprydding i metoder som har mye ressursallokering. Har
aldri hatt problemer med å forsvare en begrenset bruk av goto i slike
tilfeller. Høres selvfølgelig den vanlige "Men professoren min sa at det
skal man aldri gjøre" osv, men det går fort over.
- Petter
> Jeg tør, og her i avdelingen med 40+ utviklere (Visma/Rubicon) og
> millioner av kodelinjer så er det ennå ingen som har funnet en bedre
> måte og enklere måte og håndtere opprydding i metoder som har mye
> ressursallokering. Har aldri hatt problemer med å forsvare en
> begrenset bruk av goto i slike tilfeller. Høres selvfølgelig den
> vanlige "Men professoren min sa at det skal man aldri gjøre" osv, men
> det går fort over.
<ot><spydig>
Men Rubicon funker jo også svært dårlig dah.... Det er selvfølgelig mulig
at folket her i sjappa har mye fingertrøbbel, men etter hva jeg har
observert er Rubicon (spesielt logistikken) en _smule_ upålitelig...
</spydig></ot>
Sitter fortsatt med en følelse av at gotoer i stor grad brukes der man ser
for lite av systemet til å løse det _egentlige_ problemet, som ofte er
strukturelt.
--
Joachim
> [Kjetil Torgrim Homme]
> | eg trur det er ein smakssak kva for ein variant ein føretrekk. eg
> | likar den eksplisitte nøstinga, spesielt om ein skal flette inn meir
> | kode. her er det også lett å skilje indre delar av nøstinga ut i
> | eigne funksjonar viss funksjonen skulle vekse drastisk.
>
> Jeg synes at mange nøstinger gjør ting betraktelig mer vanskelig å
> lese, og for raringer som meg som har c-basic-offset satt til 8, så er
> ikke dette heller noe godt alternativ. Spesielt hvis det er mye kode
> inne i strukturen synes jeg ting kan bli ganske ille.
>
Grunnen til at vi bruker goto og ikke nøstede if-setninger for allokering
av ressurser bunner egentlig i at C og mange andre språk har en syntaks som
ikke er utvidbar.
F.eks. i programmer som bruker tråder og som allokerer andre ressurser er
det ikke uvanlig at man må ta en eller to låser og allokere en eller to
minneblokker. Ved å bruke 8-tegns indentering blir det håpløst rotete og
verbos kode av at hoveddelen av koden befinner seg helt på høyre side av
skjermen. Løsningen er ikke å redusere indenteringsdybden. Å bruke
8 tegns indentering er en utmerket måte å begrense kompleksiteten det er
naturlig å ha i en funksjon. Med 8 tegns indentering er det ikke naturlig
med mer enn 3 nivåer med indentering - noe som fører til at funksjonene
gjerne blir ganske oversiktlige.
Allokering av en sekvens av n ressurser burde imidlertid ikke føre til at
man trenger n nivåers indentering.
Problemet slik jeg ser det er at man ikke har et godt makrosystem. Hvis
man i C hadde hatt et makrosystem som kunne operert på blokker på en grei
måte kunne man enkelt brukt makrosystemet for å lage de pene nøstede
if-setningene uten at det hadde gått utover lesbarheten. Når vi ikke har et
slikt system blir det nest beste at vi lager enkelte konvensjoner for
hvordan goto skal brukes i forbindelse med allokering av ressurser. Jeg
liker egentlig ikke goto, men når jeg ser goto brukt når man skal returnere
fra en funksjon ser jeg ikke på det som goto, men som en konvensjon for å
lage nøstede blokker som gjør at "brødteksten" i funksjonen blir lettere å
lese.
astor
> Thore B. Karlsen <eigh...@cs.utexas.edu> writes:
>
>> On 24 May 2002 22:56:13 +0200, Bjorn Borud <borud...@borud.no> wrote:
>>
>>>| Uansett er goto og globals store nono's i C/C++.
>>
>>>jeg er ikke helt enig i at label og goto er noe man *aldri* skal
>>>bruke. jeg har sett veldig mye komplett idiotisk kode for f.eks å
>>>komme seg ut av nøstede loop'er der man burde brukt en enkel goto for
>>>å komme seg ut og hoppe til riktig sted på slutten av funksjonen slik
>>>at nødvendig opprydding gjøres før man returnerer.
>>
>> Ja, for å frigjøre rett ressurser i rett rekkefølge om en feil oppstår.
>> Men ingen tør å bruke goto lenger, så da blir det skikkelig ekkel og
>> hårete kode istedet.
>
> Ikke det at jeg skal påstå at linux-kjerna er gjennomgående vakkert
> koda (bare se på #include-kaoset som de diskuterer oppryddinga av på
> lkml for tida), men de tør iallefall bruke goto :)
>
> [ilmari@galadriel linux-2.5]$ grep -r goto .|wc -l
> 17179
>
> Dette er 2.5.17 pluss litt patcher
>
Linux-kjernen er typisk et stykke software hvor goto for opprydding av
allokerte ressurser blir brukt veldig mye. I kjernen er det ofte nødvendig
å ta låser, allokere litt minne, for så å utføre et stykke arbeide,
deallokere minne og låse opp låsene. Bruk av goto for sikker
håndtering av ressursene gjør koden mer leselig.
Nå er det også enkelte andre gotoer i linux-kjernen som jeg ikke synes er
like leselige, men det er ofte i ytelseskritisk kode - f.eks. scheduleren.
Jeg vil tro man kan finne forklaringer/diskusjoner rundt de fleste av disse
pussige gotoene hvis man søker litt på nettet.
astor
Du driver og forteller meg at du har prostituert deg og nyter det, og jeg
kan ikke si jeg liker den innstillingen.
>| Jeg bruker ferdige biblioteker der jeg kan, men sånn bortsett fra det er
>| det rart hva man gjør for å få sponset et green card.
> Du driver og forteller meg at du har prostituert deg og nyter det, og jeg
> kan ikke si jeg liker den innstillingen.
Neida, det gjelder ikke jobben jeg har nå. Jeg trives veldig godt i
denne. Det var den forrige jobben jeg prostituerte meg for, og den ga
meg en lærepenge.
Men om jeg nå ikke hadde tatt en elendig jobb for pengenes skyld så
_hadde_ jeg tatt til takke med en mye dårligere jobb enn jeg har nå for
å slippe å flytte tilbake til Norge. Det er bedre å være deppa bare på
jobb enn å være deppa av hele tilværelsen.
--
Be seeing you.
Det store problemet her er at forward og backward flow (backtracking,
retries, unwinding, exceptions, conditions, etc) ikke har samme struktur.
Dette burde egentlig ha vært rimelig opplagt, men man må kanskje tenke
litt over det før det blir så opplagt.
Hvorfor leter du etter bekreftelser på det du allerede tror? Du har jo
allerede fått et inntrykk fra noe du har sett og skjønt, så hva skal du
med en masse bekreftelser dersom du ikke _aktivt_ ser etter avkreftelser?
Hvis du ikke er helt sikker på om det du tror er sant, er det jo feil å
si at du tror det i utgangspunktet, ikke sant? Du burde være mer ydmyk
og villig til å høre på andre teorier enn å be om stadige bekreftelser på
det du ikke er sikker på, men tror likevel.
> "Bjørn Augestad" <b-au...@online.no> wrote in message
>>
>> Alt for mange linjer. Hva med denne koden?
>>
>>
>> int alloc_stuff(void)
>> {
>> int i = alloc(1);
>> i = i && alloc(2) || i && (Free(1));
>> i = i && alloc(3) || i && (Free(2), Free(1));
>> i = i && alloc(4) || i && (Free(3), Free(2), Free(1));
>> return i;
>> }
>
> Obfuscated C Contest? OK, her er mitt bidrag
>
> int init_resources (void)
> {
> return (!alloc_rec(1)
> && (!alloc_rec(2) || (free_rec(1),0))
> && (!alloc_rec(3) || (free_rec(2),free_rec(1),0))
> && (!alloc_rec(4) || (free_rec(3),free_rec(2),free_rec(1),0))) ?
> OK : NOT_OK;
> }
>
Ikke dum, slett ikke dum :-)
Hva med en liten (utestet) endring?
int init_resources (void)
{
return NOT_OK
|| (!alloc_rec(1)
&& (!alloc_rec(2) || (free_rec(1),0))
&& (!alloc_rec(3) || (free_rec(2),free_rec(1),0))
&& (!alloc_rec(4) || (free_rec(3),free_rec(2),free_rec(1),0)));
}
Skulle funke det og?
Bjørn
> Har du lyst til å oppgi navnet på de kjøtthuene som har gjort noe så
> _ubeskrivelig_ dumt?
Eigentleg skulle vi ikkje hatt strukturert programmering,
berre labels, gotos og enkel if.
Sturla Molden
> [...]
> C har i det minste ikke aritmetisk IF! :-)
Kva er ein "aritmetisk if"?
Asbj.S.
--
"The problem with free speech is that people tend to speak too much"
Gabe M. Wiener
Vel, du har mitt ubegrensede samtykke her.
En IF som tar en verdi og tre labels og hopper til første label hvis
verdien er mindre enn 0, den andre hvis den 0, og den tredje hvis den er
større enn 0. Dette er helt ubeskrivelig nyttig.
> Sitter fortsatt med en følelse av at gotoer i stor grad brukes der man ser
> for lite av systemet til å løse det _egentlige_ problemet, som ofte er
> strukturelt.
Vel, det _egentlige_ problemet, om vi nå skal bli fundamentale, er
ofte at man faktisk sitter og koder i C.
Uansett, selv om det er fantastisk enkelt å finne eksempler på goto
brukt helt feil, betyr ikke det at det ikke er mulig å bruke det
riktig. En eller annen gang bør man komme seg opp på et såpass nivå
at man ser at det finnes unntak selv fra professorale dogmer.
- Lars.
--
And what rough beast, its hour come round at last,
slouches towards Bethlehem to be born?
-- William Butler Yeats: The Second Coming
Da sier vi takk til deg, og sender en kuleramme i posten.
> En IF som tar en verdi og tre labels og hopper til første label
> hvis verdien er mindre enn 0, den andre hvis den 0, og den
> tredje hvis den er større enn 0. Dette er helt ubeskrivelig
> nyttig.
Og sarkasmen skrek i mot oss. Jeg visste heller ikke hva en aritmetisk
IF var, og virket, ut fra det lille jeg ble inspirert til å lese om
dette som en usedvanlig vond, ekkel og unødvendig konstruksjon.
Mulig den kan nyttes til noe positivt, men jeg foretrekker en leselig
if-statement. Jeg er heller ikke glad i ternary operators. Undøvendig
obfuscation, selv om det sparer tregttastende noen få tastetrykk.
--
Arve [ X-No-Archive: No ]
"I suddenly realise that while it's almost acceptable
to carry a photo of one's other half in one's wallet,
exchanging JPEGs is strictly anorak material. " - BOFH
>Mulig den kan nyttes til noe positivt, men jeg foretrekker en leselig
>if-statement. Jeg er heller ikke glad i ternary operators. Undøvendig
>obfuscation, selv om det sparer tregttastende noen få tastetrykk.
Hvis du mener det er obfuscation så er det bare fordi du ikke bruker dem
rett.
--
Be seeing you.
> <ot><spydig>
> Men Rubicon funker jo også svært dårlig dah.... Det er selvfølgelig mulig
> at folket her i sjappa har mye fingertrøbbel, men etter hva jeg har
> observert er Rubicon (spesielt logistikken) en _smule_ upålitelig...
> </spydig></ot>
Vel, regner med du tenker på Rubicon Pro som er et gammelt system. Vi har
nyere ting også da..
- Petter
[ ... ]
> Men om jeg nå ikke hadde tatt en elendig jobb for pengenes skyld så
> _hadde_ jeg tatt til takke med en mye dårligere jobb enn jeg har nå
> for å slippe å flytte tilbake til Norge. Det er bedre å være deppa
> bare på jobb enn å være deppa av hele tilværelsen.
hm, det er fint folk er forskjellige. :)
--
Terje
Vi kan jo merke oss at maskingenerert kode er mye lettere å skrive med
goto enn masse "strukturert programmering". En kan også merke seg at
hardware ikke har strukturert programmering, men goto-basert semantikk.
Dette alene burde faktisk ha medført en viss innsikt i problemstillingen.
| Uansett, selv om det er fantastisk enkelt å finne eksempler på goto
| brukt helt feil, betyr ikke det at det ikke er mulig å bruke det
| riktig. En eller annen gang bør man komme seg opp på et såpass nivå
| at man ser at det finnes unntak selv fra professorale dogmer.
I prinsippet skjer dette når man er en flinkere programmerer enn de som
har laget sproget og vil løse problemer som sproget ikke var forberedt
på. Dersom sproget ikke tillater dette, er arrogansen så himmelhøy at
man burde vurdere å gi designerne psykiatrisk behandling.
> Hvis du mener det er obfuscation så er det bare fordi du ikke
> bruker dem rett.
Ok - det jeg ville frem til er at ternary operators er en shorthand-
form av if-else. Joda, det er lett å skrive, og man vet utmerket
godt hva som foregår når man leser det - men jeg er hvertfall av de
menneskene som heller foretrekker å lese korte og klare kodelinjer.
Men, så tilhører jeg også de som aldri skriver if-ene mine på en
linje, uansett hvor banalt uttrykket er.
Men hvis du kan vise meg et tilfelle der ternary operators er mer
leselig enn en if-else, så skal jeg gladelig spise mine ord.
>> Hvis du mener det er obfuscation så er det bare fordi du ikke
>> bruker dem rett.
>Ok - det jeg ville frem til er at ternary operators er en shorthand-
>form av if-else. Joda, det er lett å skrive, og man vet utmerket
>godt hva som foregår når man leser det - men jeg er hvertfall av de
>menneskene som heller foretrekker å lese korte og klare kodelinjer.
>
>Men, så tilhører jeg også de som aldri skriver if-ene mine på en
>linje, uansett hvor banalt uttrykket er.
>
>Men hvis du kan vise meg et tilfelle der ternary operators er mer
>leselig enn en if-else, så skal jeg gladelig spise mine ord.
Ikke bare mer leselig, men også nødvendig:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
--
Be seeing you.
Hvorfor er ikke instruksjoner som dytter state på stacken sammen med
returadresse før den eksekverer kode et annet sted, for så å returnere
til tilstanden man akkurat hadde pluss resultatet, ikke "strukturerte"
semantiske primitiver? Eller for den saks skyld mange mmu-er, som
egentlig tillater aksesskontroll på klassenivå, dersom noen bare hadde
brukt de slik?
Mulig at jeg er på et lavere nivå enn deg akkurat nå.
Geir
> #define MAX(x,y) ((x) > (y) ? (x) : (y))
Og så den vanlige: Hva skjer hvis du setter inn a++ for x?
Macros are _evil_....
--
Joachim
>> #define MAX(x,y) ((x) > (y) ? (x) : (y))
>Og så den vanlige: Hva skjer hvis du setter inn a++ for x?
Hva skjer om makropolitiet kunne latt være å sprute ut
selvfølgeligheter?
>Macros are _evil_....
Foretrekker du å skrive alt ut fullt hver gang, fremfor å ta det
åpenbare hintet at MAX skrevet med STORE bokstaver er en makro, ikke en
funksjon, og dermed skal brukes som sådan?
--
Be seeing you.
> Hva skjer om makropolitiet kunne latt være å sprute ut
> selvfølgeligheter?
Den der er jækla lett å misse hvis du har det travelt. Tipper det er en god
del som ikke ser den som veldig selvfølgelig også.
>>Macros are _evil_....
>
> Foretrekker du å skrive alt ut fullt hver gang, fremfor å ta det
> åpenbare hintet at MAX skrevet med STORE bokstaver er en makro, ikke en
> funksjon, og dermed skal brukes som sådan?
Inline-funksjoner finnes.... At noe skrevet med STORE BOKSTAVER er en makro
er en vanlig konvensjon, men ikke nødvendigvis universell, og ikke
nødvendigvis fulgt. Som du sier, det er et _hint_. Hint pleier ikke å være
veldig explisitte av seg.
--
Joachim
Fordi man ikke er fornøyd med prosedyrekall for å ha strukturert
programmering.
| Eller for den saks skyld mange mmu-er, som egentlig tillater
| aksesskontroll på klassenivå, dersom noen bare hadde brukt de slik?
Dette vet jeg ingenting om.
| Mulig at jeg er på et lavere nivå enn deg akkurat nå.
Trolig. Hvordan uttrykker du en while-løkke, en if-setning, en unwind-
protect, eller en try-catch blokk? Det meste av dette blir til goto og
andre primitive instruksjoner.
Ville det ha vært greit om if var et uttrykk, og ikke bare en setning?
Altså, noe sånt som: A := if B then C else D; fremfor a = b? c: d;.
Feil lærdom.
Dette er omtrent like lurt som å konkludere av å ha lagt hånden på
komfyren som 4-åring at du skal spise kald mat resten av livet.
Hvis du må bruke argumenter med side-effects og du ikke er sikker
på om det er en funskjon eller en makro kan du vel bare '#undef
identifier' eller sette parantes rundt identifier, for eksempel
'(toupper)(*s++)', for å forsikre deg om at et funksjons-kall
utføres framfor en macro expansion? Finnes den kun som en makro
er det vel best å holde seg unna argumenter med side-effects.
Strengt tatt er det vel "++" og "--" som er evil.
--
It's a dark day for mad science.
> Ville det ha vært greit om if var et uttrykk, og ikke bare en
> setning?
>
> Altså, noe sånt som: A := if B then C else D; fremfor a = b? c:
> d;.
Jeg ser nytten, men har vanligvis, enten av vane,
eller av årsaker jeg ikke kan forklare lest: if(b) a=c else a=d.
Mulig det er fordi jeg har blitt ødelagt av å lese ting som:
obj=((document.all('someId'))&&(!document.getElementById('someId'))?document.all('someId').parentElement:document.getElementById('someId').parentNode;
Fordi jeg sterkt misliker å scrolle horisonalt, kan dette fort
vekk se slik ut:
obj=((document.all('someId')&&(!document.getElementById('someId')))?
document.all('someId').parentElement:document.getElementById('someId')
.parentNode;
Nei, ikke dermed sagt at a?b:c er nedsnødd hele tiden,
men så lenge folk har gode mekanismer for å skyte seg selv
i foten, vil de bruke dem.
Og det jeg dermed _tror_ jeg burde sagt, og ment, helt klart
fra starten av, er at ternary operators i seg selv ikke er obfuskerende,
men at jeg har sett såpass vanvittig bruk, at jeg velger å ligge unna
selv, og at langt fler _burde_ ligge unna.
Poenget mitt var at det fantes et alternativ til goto error; løsningen, uten
for mye ekstra kode.
quote fra linken:
Therefore, the test
if((a == b) == TRUE)
would work as expected (as long as TRUE is 1), but it is obviously silly.
Uansett blir dette noe litt annet, jeg pleier ikke å gjøre det slik ved
sammenlikning, men kun ved funksjoner med booleansk returverdi, bare for å
spesifisere at funksjonen skal returnere true og ikke noe annet.
mackrune
MAX (getc (stream_1), getc (stream_2));
Det er feil at et sprog som tilsynelatende har makroer ikke har støtte
for å opprettholde evalueringsreglene for argumenter til funksjoner.
Riktig løsning på dette problemet er ganske brutalt langt fra C.
Konklusjonen her er imidlertid at max må være en funksjon og at grunnen
til at macroer brukes er et misforstått forsøk på å gjøre kompilatoren en
tjeneste ved å forsøke seg på assembly-level instruksjonsoptimering. Der
hersker ingen tvil om at _dersom_ kompilatoren gjør common subexpression
elimination, vil det ikke spille noen rolle om man har side effects, men
dersom den tolker subexpressions bokstavlig, vil det få betydning. Nå
skal det egentlig litt til å være så kunnskapsløs om sprogdesign at man
klarer å gjøre sånne tabber. Selv i 1970 var ikke dette akkurat nytt.
Dette er jo helt greit hvis du bare har en enkel assignment, men poenget
er liksom at man ikke bruker the ternary operator i enkle assignments,
det er bare mer pedagogisk å vise frem forskjellen slik.
| Mulig det er fordi jeg har blitt ødelagt av å lese ting som:
Det er da veldig til brente barn rundt omkring her.
| Nei, ikke dermed sagt at a?b:c er nedsnødd hele tiden, men så lenge folk
| har gode mekanismer for å skyte seg selv i foten, vil de bruke dem.
Vel, jeg er sportsskytter. Hvis de ikke klarte å lage hull i foten min,
ville de ha vært adskillig mindre effektive til det de skal brukes til.
Poenget er å sikte på målet når man trekker av og ikke ha foten i veien.
Dette er ikke relatert til pistolen, men til vettet til brukeren. Jeg
har vondt for å se hvordan noe annet kan gjelde programmeringssprog.
| Og det jeg dermed _tror_ jeg burde sagt, og ment, helt klart fra starten
| av, er at ternary operators i seg selv ikke er obfuskerende, men at jeg
| har sett såpass vanvittig bruk, at jeg velger å ligge unna selv, og at
| langt fler _burde_ ligge unna.
Ja, jøss, og Aftenposten skriver på lederplass at det er registrerte
våpen (eid av folk med skinnende rent rulleblad!) som er problemet, ikke
de kriminelles våpenbruk. Klart det er operatoren som er problemet og
ikke operatøren!
Jeg tror folk har klart å forville seg inn i en forventning om at verden
liksom skylder dem å være snill mot dem, at det er noe _galt_ med verden
når de møter farer, så når de møter farer, blir de sinte på verden,
fremfor å lære seg å redusere de risiki de nødvendigvis må møte i det
virkelige liv. Det er en konsekvens av å leve i et altfor trygt samfunn.
>> Hva skjer om makropolitiet kunne latt være å sprute ut
>> selvfølgeligheter?
>Den der er jækla lett å misse hvis du har det travelt.
Og hvis man har det så travelt at man glemmer barnelærdom husker man
gjerne gode råd i obskure newsinnlegg?
>Tipper det er en god del som ikke ser den som veldig selvfølgelig også.
De programmerer forhåpentlig ikke i C, da.
>>>Macros are _evil_....
>> Foretrekker du å skrive alt ut fullt hver gang, fremfor å ta det
>> åpenbare hintet at MAX skrevet med STORE bokstaver er en makro, ikke en
>> funksjon, og dermed skal brukes som sådan?
>Inline-funksjoner finnes....
Da er det altså bare å skrive en funksjon for hver ting man vil
sammenligne. Høres mye bedre ut.
--
Be seeing you.
etter mi meining er det ikkje ?-operatoren som er problemet, men
mangel på passande innrykk:
obj = (document.all('someId') &&
document.getElementById('someId'))
? document.getElementById('someId').parentNode
: document.all('someId').parentElement;
(der var ein parentesfeil i koden din, så det kan hende mi tolking er
"feil" :-)
--
Kjetil T. your computer can help researchers understand how
proteins work. http://folding.stanford.edu
> Men hvis du kan vise meg et tilfelle der ternary operators er mer
> leselig enn en if-else, så skal jeg gladelig spise mine ord.
printf("%d is a %s number\n", n, n < 10 ? "small" : "big");
Slike konstruksjoner har den fordelen fremfor tilsvarende
if/else-variant at det er åpenbart at resten av printf()-en er lik.
Man ser forholdsvis greit at det er kun ett felt som varierer, mens om
man hadde to printf()-er, en for store og en for små tall måtte man
lese og sammenligne mer for å finne ut at den aktuelle branchen er
rent kosmetisk. Dette betyr igjen at når man leser koden kan man
raskere forkaste den aktuelle kodelinjen som uinteressant i forhold
til det man faktisk leter etter enn om den var duplisert med if/else.
(Nei, jeg sier ikke at ?: er eneste måte å oppnå dette på.)
>> Men hvis du kan vise meg et tilfelle der ternary operators er mer
>> leselig enn en if-else, så skal jeg gladelig spise mine ord.
>
> printf("%d is a %s number\n", n, n < 10 ? "small" : "big");
*tygge* *svelge* *gulpe* *svelge igjen*
</sult>
Inline finnes ikke C89.
--
Tor <torust AT online DOT no>
Nei. Poenget er at argumentene i MAX makroen _evalueres_ flere
ganger, for en funksjon så gjøres slikt nøyaktig _en_ gang.
Bruker man makroer som erstatning for funksjoner, så
kreves litt innsikt. Makroer kan være nyttige, tenk f.eks.
på denne
#define token(a,b) a ## b
La oss si at noen har lyst til å skrive et API spion
program. Du ønsker trace alle funksjons kall via dette
API'et, dette kan være underliggende moduler (f.eks.
DLL) du ikke har source til, så du kan ikke legge inn
dine egne trace kall og rekompilere denne modulen.
Det er flere måter å implementere et slikt spion program
på, en elegant løsning uten bruk av makroer, vel, du kan
prøve...
Makroer er som det meste i C, farlig for den som ikke
vet hva man driver med...
Mener du at allocate_rec(4) blir kalt istedenfor allocate_rec(3)? Det er jo
åpnebart bare en uskyldig skrivefeil.
mackrune
Jeg tror ikke det. Når det er såpass enkelt og oversiktlig som
goto-eksempelet til Øystein Svendsen, kanskje. Men i en større sammenheng
vil ihvertfall jeg gi opp ganske fort å lete etter feil hvis goto hoppet
fram og tilbake i koden som det passet seg.
mackrune
On Sat, 25 May 2002, Øystein Svendsen wrote:
> [Holmberg Anders]
> | PS. Informatikk-læreren min her på skolen er også motstander av goto, og han
> | skulle så vise et eksempel som da skulle være mye bedre, men det er den
> | værste spageti-loop programeringa jeg har sett :)
>
> Ta følgende eksempel, jfr. slik som Thore B. Karlsen også nevnte, så
> er goto fin ved trinnvis allokering av ressurser, der alle må
> frigjøres etter tur hvis en allokering feiler.
>
> int init_resources(void) {
>
> if (allocate_rec(1)) goto fail_3;
> if (allocate_rec(2)) goto fail_2;
> if (allocate_rec(3)) goto fail_1;
> if (allocate_rec(4)) goto fail_0;
>
> return OK;
>
> fail_0: free_rec(3);
> fail_1: free_rec(2);
> fail_2: free_rec(1);
> fail_3: return NOT_OK;
> }
>
> Hvis du har tid så hadde det vært interessant om du kunne finne ut
> hvordan læreren din vil la ovenstående snutt se ut på en mer lettlest
> og elegant måte, uten bruk av goto.
>
Enkelt:
int arci(int a){
free_rec(a);
return NOT_OK;
}
int icra(int a,int b){
return a==b?OK:allocate_rec(a)?arci(a):icra(a+1,b)==OK?OK:arci(a);
}
int init_resources(void){
return icra(1,5);
}
Ingen bruk av goto, continue, break, switch, if, eller annet
goto-lignende svineri.
--
Ble det ikke nevnt et eller annet sted i denne tråden at litt av
grunnlaget var at en _ikke_ kunne bruke den samme rutinen for allokering
av hver enkelt datakilde? Mao. rekursjon er ikke anvendbart, med mindre enn
omskriver allocate_rec til å håndtere hver enkelt type allokering.
Og angående utsagnet 'ingen bruk av ... if, eller annet goto-lignende
svineri', synes du virkelig en trippel ?: er mye bedre? I min verden
er ikke din funksjon icra() veldig leselig, og ville vært mer forståelig
med bruk av if-setninger.
Begynner, egentlig i strid med egne preferanser, å se at i enkelte
spesielle konstruksjoner kan det være nødvendig/kjekt å bruke goto.
Vennlig hilsen
Even Holen
PS! Hvis du gikk for å omskrive allocate_rec, så vil ikke den
subfunksjonen eller det totale bildet bli så mye bedre enn
utgangspunktet... ;-)
--
<>< Even Holen, ev...@pvv.ntnu.no, http://www.pvv.ntnu.no/~evenh/ :-)