Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
En kom je vanaf een taal zoals pascal (heeft een string type, GEEN string object!) dan blijft de C aanpak ook nog vaag.MSalters schreef op 31 juli 2002 @ 15:10:
[...]
C heeft wel degelijk strings. Alleen is C geen OO-taal. Als je met een OO-achtergrond dus een string object verwacht is C een verassing. Kom je daarentegen vanuit assembly dan is de C aanpak (array van chars ) logisch.
Booleans daarentegen bestaan wel gewoon, zie _Bool (maar ze zijn pas 3 jaar oud in C). Dat je ze "nodig" hebt is natuurlijk onzin; geen enkele nieuwe CPU heeft directe ondersteuning voor single-bit variabelen. En toch werken die CPUs.
Naar mijn idee heeft C geen stringtype, maar ter "vervanging" kan een array van char's (of eigenlijk een pointer naar char) gebruikt worden.
in pascal kan je string1:=string2+string3 doen.. in C ook, maar dit geeft niet het goede resultaat, en een mem-leak (de originele ref. naar string1 ben je kwijt)
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Volgens mij is een bool type niets anders dan een integer type en dat op veel plekken in de code ook nog een integer wordt geaccepteerd ipv een boolean, bv een ifstatement.MSalters schreef op 31 juli 2002 @ 15:10:
Booleans daarentegen bestaan wel gewoon, zie _Bool (maar ze zijn pas 3 jaar oud in C).
Wat er gebeurd is dat je het ifstatement die integer waarde laat interpreteren als een boolean. En dat is het gene wat zo slecht is, want een boolean is toch van een heel ander type dan een numerieke waarde. Jouw boolean in c is niet hetzelfde als een boolean in de meeste andere talen zoals: pascal, modula, java, c#, delphi.
Dat duidt misschien wel op een groot verschil tussen jouw en mij. Ik vind die cpu totaal niet relevant en het is eigelijk niets anders dan een dom stuk gereedschap die uiteindelijk mijn code uitvoert, en hoe hij dat doet is onbelangrijk. Wat ik wel erg belangrijk vind is dat ik veel ondersteuning kan krijgen vanuit de runtime en/of de compiler. Ik probeer met oa booleans een bepaalde typering ergens aan te geven, en dan moet ik mij daar bij het gebruiken ook aan houden.Dat je ze "nodig" hebt is natuurlijk onzin; geen enkele nieuwe CPU heeft directe ondersteuning voor single-bit variabelen. En toch werken die CPUs.
Waarom dacht je anders dat types uitgevoerd zijn? Om jouw te helpen hoor, en niet de computer. Voor de computer is alles een 1 of een 0, en die zal het echt een worst zijn dat het een auto record is of een boolean. Die programmeer taal is er dus voor jouw en om jouw zo veel mogelijk te ondersteunen (door eventueel streng te zijn).
Verwijderd
Bah, die MS propaganda ook altijd. Nothing personal, maar met dit soort uitspraken laat je zien dat je nog helemaal niks van programmeren snapt... C is niet dood, C is de basis van zowat alle unices in de wereld (dus ook MacOS X) en mijn Linux systeem bestaat voor 75% uit programma's die in C zijn geschreven (Gnome als desktop). C++ is net zomin dood. C# bestaat nog niet eens fatsoenlijk en heeft al helemaal geen status. En om het als opvolger neer te poten is net zoiets als zeggen dat ik de nieuwe Einstein ben. Come and get me, universiteiten, slechts $999/uur. Special offer because you are my friend.axis schreef op 29 juli 2002 @ 10:03:
Waarom zou je nu met een taal gaan beginnen die al aan het uitfaseren is? Waarom niet de opvolger, C#!? Lijkt me logischer.
Ja, zo ken ik er nog een. x = 10^2 geeft geen 100 in C/C++, ohwee, C/C++ is vast enorm klote. Dat operators anders zijn betekent niet dat de taal opeens onlogisch is. Dat is 't zelfde als zeggen dat MacOS X kut is vergeleken met Windows omdat de taakbalk boven zit in plaats van onder.Creepy schreef op 31 juli 2002 @ 15:14:
in pascal kan je string1:=string2+string3 doen.. in C ook, maar dit geeft niet het goede resultaat, en een mem-leak (de originele ref. naar string1 ben je kwijt)
De taal werkt anders, maar dan is ie niet automatisch slechter.
Genoeg cynisme.
Wie heeft het hier over slechter???????????????????? Ik krijg het gevoel dat je je aangevallen voelt, omdat je veel in C programmeert???? Kan je alvast vertellen dat dat wat mij betreft niet zo is. Ik prog net zo makkelijk in C als in PascalVerwijderd schreef op 31 juli 2002 @ 20:54:
[...]
Ja, zo ken ik er nog een. x = 10^2 geeft geen 100 in C/C++, ohwee, C/C++ is vast enorm klote. Dat operators anders zijn betekent niet dat de taal opeens onlogisch is. Dat is 't zelfde als zeggen dat MacOS X kut is vergeleken met Windows omdat de taakbalk boven zit in plaats van onder.
De taal werkt anders, maar dan is ie niet automatisch slechter.
Het gezever ala "Nee, C is beter..... nee Pascal is beter.. nee man.. java is beter...... blaat" ga ik echt niet aan beginnen hoor.. ben geen ego-trippende-super-l33t3-coole-puber-die-net-(insert willekeurige prog taal hier)-heeft-geleerd of een-echte-programmeur-klopt-code-in-fortran-figuur.
Feit blijft dat een char[] of * char niet hetzelfde zijn als een native string type. In bijv pascal kan je ook een array van char's of een pointer naar een (array van) char maken, toch is er ook nog een string type. Ik heb het hier dus niet puur over syntactische verschillen alleen!
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Verwijderd
Hm, ik overdreef... sorry.Creepy schreef op 31 juli 2002 @ 21:17:
[...]
Wie heeft het hier over slechter???????????????????? Ik krijg het gevoel dat je je aangevallen voelt, omdat je veel in C programmeert???? Kan je alvast vertellen dat dat wat mij betreft niet zo is. Ik prog net zo makkelijk in C als in Pascal
Hangt er (m.i.) maar net vanaf hoe je er gebruik van maakt.... pascal/c++: String string3 = String string1 + String string2 [ + String string3 ...]; C/glib: gchar *string3 = g_strconcat(gchar *string1, gchar *string2, [gchar *string3, ...] NULL);Feit blijft dat een char[] of * char niet hetzelfde zijn als een native string type. In bijv pascal kan je ook een array van char's of een pointer naar een (array van) char maken, toch is er ook nog een string type. Ik heb het hier dus niet puur over syntactische verschillen alleen!
Maargoed, nu doe ik het alweer - ik neuzel.
Om even bot te zijn, wat er volgens jou in C zit boeit niet. C heeft dus wel een boolean type, _Bool. Je had gelijk gehad voor 1999, toen C nog met ints moest werken.Alarmnummer schreef op 31 juli 2002 @ 16:45:
[...]
Volgens mij is een bool type niets anders dan een integer type en dat op veel plekken in de code ook nog een integer wordt geaccepteerd ipv een boolean, bv een ifstatement.
Wat er gebeurd is dat je het ifstatement die integer waarde laat interpreteren als een boolean. En dat is het gene wat zo slecht is, want een boolean is toch van een heel ander type dan een numerieke waarde. Jouw boolean in c is niet hetzelfde als een boolean in de meeste andere talen zoals: pascal, modula, java, c#, delphi.
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
source http://www.comeaucomputing.com/techtalk/c99/#boolC99 now supports a boolean type _Bool and also bool via <stdbool.h>. Consider:
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38#include <stdio.h> int main() { // _Bool can hold 0 or 1 // _Bool is an unsigned integer type _Bool b = 1; struct xyz { _Bool mem : 1; // _Bool bitfields allowed }; printf("%d\n", b); // 1 b = 0; printf("%d\n", b); // 0 _Bool *pb = &b; // If the expression evaluates to 0, then it converts to _Bool as 0, else 1 b = pb; printf("%d\n", b); // 1 b = -1; printf("%d\n", b); // 1 b = (pb == 0); printf("%d\n", b); // 0 return 0; } // #define's bool, true, false, __bool_true_false_are_defined macros // as _Bool, 1, 0, and 1 respectively #include <stdbool.h> void foo() { int this = 99; int that = -99; bool b; if (this || that) b = true; else b = false; }
ziet er toch vrij interig uit, dus volgens mij moet int a=true+false; wel lukken. Dit betekend dat _Bool dus geen type is. Ik wist trouwens niet dat ze een remake hebben gedaan voor c, dit vind ik persoonlijk een erg goeie zaak.
[ Voor 0% gewijzigd door Alarmnummer op 01-08-2002 10:36 . Reden: quotes vergeten. ]
Ik geloof dat ze met c# ook nagenoeg zo`n constructie hebben: delegate.
Hogere orde functies zijn erugh handig hoor
In java is het btw ook mogelijk dmv java.util.Reflection. Ik dacht dat je de method dan dmv een proxy kon invoken.
Verwijderd
Alarmnummer schreef op 01 augustus 2002 @ 10:34:
C99 now supports a boolean type _Bool and also bool via <stdbool.h>.
[..]
ziet er toch vrij interig uit, dus volgens mij moet int a=true+false; wel lukken. Dit betekend dat _Bool dus geen type is.
Je kan toch zelf wel nagaan dat een true+false toch nergens op slaat? De enigste reden dat jij er iets zinnigs van kan maken is dat jij weet dat de een true 1 is en false 0, dus 1+0 =1. Maar dit zijn alleen maar afspraken waar een programmeur in principe helemaal geen weet van mag hebben.
Die optelling zou niet toegestaan mogen worden, en dat is precies wat je met een type kan regelen. Daarmee kan je bepaalde operaties op basis van hun formele argument types afkeuren op basis de actuele argumenttypes. Aangezien je dat bij _BOOL dus niet kan doen, en een _BOOL dus een integer is, is _BOOL dus geen type zoals hij behoort te zijn.
bool a = true + true.Verwijderd schreef op 01 augustus 2002 @ 13:09:
[...]
Dit slaat op oorlog. Als je met booleans kunt rekenen is het geen type? Waarom mag bool a= true | false; wel, maar bool a= true + false; niet? (En wat is het verschil tussen die operaties...)
Wat is a nu? 2? En is dat ook nog true dan?
Voordat erweer gedacht wordt dat ik de ene taal beter vindt dan de andere (zwaai zwaai Beelzebubu
Goed.. dat ben ik kwijt
In Pascal geeft dit een mooie compiler error:
1
2
3
4
| var blaat: boolean;
begin
blaat:=true + false;
end; |
De melding is dat deze operator (+) niet toegepast kan worden op het type (boolean).
Met _bool kan dit blijkbaar wel.
En om ff antwoord te geven op mijn eigen vraag:
Wel is het zo dat een _bool altijd 0 of 1 is. Dus _bool b = true + true + true levert op dat _bool b==true
Waarom _bool stiekum een int type kan wezen is omdat in C 0 gezien wordt als false, en al het andere als true (vandaar ook dat dat een _bool op 1 wordt gezet als deze NIET 0 is).
MI ben ik het met Alarmnummer eens, dat een _bool geen eigen type is, maar eigenlijk een int type, die op 0 staat, of op 1 wordt gezet als deze geen 0 is. Het komt wel erg dicht in de buurt van een boolean type.
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Verwijderd
Iedereen die wat formele logica gehad heeft, weer dat een booleaanse "OR" gelijk is aan numeriek optellen, en dat de booleaanse "AND" gelijk is aan numeriek vermenigvuldigen.Creepy schreef op 01 augustus 2002 @ 13:36:
[...]
bool a = true + true.
Wat is a nu? 2? En is dat ook nog true dan?
Dus: bool a= true + false; is volledig equivalent met bool a= true | false;
en bool a= true * false; is volledig equivalent met bool a= true & false;
Ja en? Dat betekent alleen dat C99 meer orthogonaliteit biedt dan Pascal, maar je kunt dit toch niet gebruiken als argument dat C99 geen bool type kent, terwijl de specs duidelijk zeggen dat er wel een eigen bool type is.In Pascal geeft dit een mooie compiler error:
De melding is dat deze operator (+) niet toegepast kan worden op het type (boolean).
Met _bool kan dit blijkbaar wel.
Wat je hier beschrijft is een boolean type, een binaire waarheidswaarde waar je binair mee kunt rekenen. Hoe deze door de compiler intern gerepresenteerd worden zal mij worst wezen.Waarom _bool stiekum een int type kan wezen is omdat in C 0 gezien wordt als false, en al het andere als true (vandaar ook dat dat een _bool op 1 wordt gezet als deze NIET 0 is).
MI ben ik het met Alarmnummer eens, dat een _bool geen eigen type is, maar eigenlijk een int type, die op 0 staat, of op 1 wordt gezet als deze geen 0 is. Het komt wel erg dicht in de buurt van een boolean type.
Ik zou deze aanpak van _BOOL in andere talen verwerpelijk vinden omdat je dus operaties uitvoert op een type dat daar niet geschikt voor is, en als je dicht op de hardware zit dan is dit misschien gebruikelijk.
Ik denk dat we het daar beiden over eens zijn.
[edit]
float a = false*sin(true>4)
Verwijderd
Hoezo? C doet nooit bewerkingen op types die daar niet geschikt voor zijn, het type wordt altijd (automatisch) gecast naar een geschikt type.Alarmnummer schreef op 01 augustus 2002 @ 14:06:
Ik zou deze aanpak van _BOOL in andere talen verwerpelijk vinden omdat je dus operaties uitvoert op een type dat daar niet geschikt voor is, en als je dicht op de hardware zit dan is dit misschien gebruikelijk.
Ik denk dat jij meer problemen hebt met twee designfeatures van C:
• (bijna) elke construct is een expressie (en heeft dus een rvalue).
• het default type is int (en er wordt dus standaard geupcast/downcast naar int).
En dan met name het 2e punt, jij verwacht het gedrag van een bondage-and-discipline taal bij het combineren van types in een expressie (maw. een foutmelding), terwijl C dan aan het casten slaat om er toch nog iets van te maken.
En dat slaat juist nergens op. Wiskundig gezien is een boolean een heel ander type dan een integer. De verzameling van boolean waarden = {true,false} en die van integer = {..-1,0,1,...} Zoals je ziet hebben ze geen enkel gemeenschappelijke waarde. En het casten van een boolean type is onmogelijk tenzij je afweet dat low level een boolean geintepreteerd wordt als een integer. C doet bewerking op een type die wiskundig gezien fout is, maar wordt geaccepteerd omdat de compiler weet dat hij een boolean ziet als een integer.Verwijderd schreef op 01 augustus 2002 @ 15:14:
Hoezo? C doet nooit bewerkingen op types die daar niet geschikt voor zijn, het type wordt altijd (automatisch) gecast naar een geschikt type.
Ik denk dat jij meer problemen hebt met twee designfeatures van C:
• (bijna) elke construct is een expressie (en heeft dus een rvalue).
Aha, dus ik zou dan ook zo maar een string of record mogen casten naar een integer omdat dit een basis type is? Het is heel leuk voor c dat een integer ergens voor de meeste dingen gebruikt wordt. Maar je bent hierdoor te ruim met de typering van je expressies. Op zich kan dat heel handig zijn, maar fouten zijn heel lastig te detecteren.• het default type is int (en er wordt dus standaard geupcast/downcast naar int).
Je kan dus kiezen voor een taal die ruim is met typeringen zodat sommige wiskundig foute dingen toch naar correcte types worden gecast. Hierdoor kan onduidelijkheid onstaan, en je kan minder strenge software schrijven omdat het type systeem te ruim is.
Of je kan kiezen voor een programmeer taal die streng is met zijn typering, en waarin iedere expressie wiskundig gezien correct is. Je verliest eventueel wat uitdrukking kracht, maar dat wordt gecompenseerd door een betere type ondersteuning van de taal.
Ik kies persoonlijk voor het laatste omdat ik eigelijk nooit lowlevel bezig ben en de computer een medium is geworden om allerlei ideeen in de praktijk te brengen. Ik verwacht zoveel mogelijk ondersteuning vanuit de taal als ik iets fout doe.
Als ik iets doe wat die compiler een beetje onduidelijk vind, dan moet hij eruit knallen met een foutmelding en niet zelf aan het verhelpen gaan in de geest van 'dat zal hij wel bedoelt hebben'. Met c loop je het risico dat je een programmeer fout over het hoofd ziet omdat de compiler ruim is met het accepteren van types. Het probleem aan deze fouten is dat je ze vrij lastig kan opsporen. Je ontwikkeld door de loop van de tijd allerlei idiomen om correct hier mee om te gaan. Ik heb persoonlijk het boek 'de ten commandments for C programmers' niet gelezen, maar het schijnt dat de 1e 5 niets anders zijn om tekortkomingen aan het type systeem van c te compenseren.En dan met name het 2e punt, jij verwacht het gedrag van een bondage-and-discipline taal bij het combineren van types in een expressie (maw. een foutmelding), terwijl C dan aan het casten slaat om er toch nog iets van te maken.
Verwijderd
Ik weet WEL een goed boek om te beginnen met C/C++:
Aan de slag met C++
Gertjan Laan
Academic Service
ISBN 90 395 1084 9
NUGI 852
Ik moest het hebben voor school. De eerste helft van het boek gaat over gewoon programmeren wat in structuur hetzelfde is als BASIC. De andere helft is een stuk abstracter en gaat over Object georienteerd (OO) programmeren. Ik verzeker je dat dit een heel fijn boek is, omdat het nederlandstalig is, goeie begrijpbare uitleg en sourcecode voorbeelden bevat. Al is de leercurve soms wel wat stijl, ikzelf heb verschillende hoofdstukken een paar keer vaker moeten lezen voor ik het begreep.
Ik kan nu (jaar of anderhalf later) al redelijk C++ programmeren (vind ik), dwz. ik kan al goeie audioapplicaties maken, ben nu bijvoorbeeld bezig met een audiogame via DirectX
En laat je als beginner niet al te druk maken over de verschillen in C/C++, het is nagenoeg hetzelfde, behalve dat je in C++ ook nog object georienteerd kan programmeren, wat in windows te vaak gedaan wordt. De meeste compilers zijn voor zover ik weet alleen maar C EN C++, dus het is niet erg om van beide te weten, zodat je ook andermans C code kunt hergebruiken bijvoorbeeld.
Mocht je niet in het bezit kunnen komen van illegale shit zoals Metroworks Codewarrior of Microsoft Visual Studio of Borland zooi, dan kun je altijd nog gratis complete compiler pakketten downloaden van bijvoorbeeld www.delorie.com/djgpp , www.bloodshed.net (Dev-C++). Daar moet je al een eind mee kunnen komen, al wil je voor de echt professionelere dingen die je in het begin nog helemaal niet nodig hebt toch liever de eerstgenoemde pakketten hebben.
Man dat boek is niets meer dan een regelrechte rip van z'n Java boek. Het behandeld net een beetje de syntax. Wat heb je daar nou aan? Geen patterns geen structures en vreselijke slechte vertaling van de engelse termen!Verwijderd schreef op 01 augustus 2002 @ 21:54:
Hier een tip van iemand die is overgeschakeld ook vanuit o.a. BASIC.
Ik weet WEL een goed boek om te beginnen met C/C++:
Aan de slag met C++
Gertjan Laan
Academic Service
ISBN 90 395 1084 9
NUGI 852
En die hoorcolleges van hem waren nog veeeel slechter
• De programmeertaal C (al kelley / ira pohl ) - uitgeverij Addison Wesley
• C leerboek (kenneth a. barclay) - uitgeverij Academic Service (oorspronkelijke titel is overigens 'ANSI C: problem solving and programming') - een iets moeilijker boek dan de bovenstaande, maar (voor zover ik daarover kan oordelen) wel een goeie...
Ik heb dat java boek eens ingezien en vond het inderdaad niet geweldig om er in de toekomst ook iets aan te hebben. Het dient alleen ter introductie.Glimi schreef op 01 augustus 2002 @ 22:11:
[...]
Man dat boek is niets meer dan een regelrechte rip van z'n Java boek. Het behandeld net een beetje de syntax. Wat heb je daar nou aan?
De meeste docenten die kijken je een beetje vreemd aan als je het woord pattern in de mond neemt. En een pattern is pas handig als je de taal begrijpt, en daarom ook onnodig bij een introductie.Geen patterns
nederlande vertaling van performance: performantieen vreselijke slechte vertaling van de engelse termen!
De volgende keer tomaten meenemen dusEn die hoorcolleges van hem waren nog veeeel slechter
Maar om weer even in te haken bij de off-topic discussie over Booleans.
Standaard C werkt in zijn if statements met de volgende boolean:
0 == FALSE
!= 0 == TRUE
Alle boolean types die hier in praktijk uitvloeien zijn hierop gebaseerd.
Het grote voordeel hiervan is dat de expressies in de statements eenvoudig kunnen blijven, je hoeft ze namelijk niet
meer te reduceren tot 1.
bv if (karakters_aanwezig) ipv
if (karakters_aanwezig != 0) of erger if (karakters_aanwezig/aantal_karakters_aanwezig)
waarbij karakters_aanwezig het aantal karakters in bv een string teruggeeft.
Ik ben het een beetje met je eens dat deze boolean definitie iets anders is dan je ergens anders tegenkomt (0 & 1)
doch het is wiskundig correct.
Verder kun je gewoon met booleans rekenen alsof het integers zijn, terwijl het ook voor booleans blijft kloppen.
Je kan je beperken tot de 0,1 definitie als je dat graag wilt en mentaal kun je gerust doen alsof C het ook zo doet. (of 0,42 als je liever wilt). Maar als je de integer definitie gebruikt blijken booleans ineens een stuk krachtiger te worden.
Nu nog iets over strings:
karakters zijn in C integers (ASCII waarden). Een string is dus een array van deze ASCII waarden. Het grote voordeel hiervan is dat computers nu met characters kunnen gaan rekenen (wat ze igv een aparte structuur in principe (zonder vertaalslag) niet zouden kunnen). (bv in functies als toupper, isalphnum etc)
Een ander voordeel van alles op dezelfde grondstructuur baseren is dat de taal ineens een stuk eenvoudiger wordt. In feite heb je alleen maar functies nodig die met deze basisstructuur (of de samengestelde varianten) hoeven te werken. Dit ipv alles 10 keer opnieuw te moeten doen.
Natuurlijk is dit iets waar je van moet houden. Als je liever op een hoger niveau werkt staat het je vrij om en taal te nemen die voor elke structuur zijn regels ingebouwd heeft. (en dus automatisch alles vertaald)
Maar het feit dat C dat niet (direct) doet maakt van C juist een enorm krachtige en toch simpele taal. (De taal legt maar een minimum vast en beperkt de programmeur daarmee minimaal)
Dit is dus zowel een voordeel als een nadeel en het is aan eenieder zelf om daar zijn/haar keus op te baseren.
adres werkt dus niet, ben nog aant zoeken
Verwijderd
Dat slaat juist wel op een heleboel. Wiskundig gezien is een boolean een numeriek type; en wel een type dat exact één binaire digit kan opslaan. Dat men die binaire waardes in programmeertalen representeert als false en true wil niet zeggen dat boolean daarom geen numeriek type is.Alarmnummer schreef op 01 augustus 2002 @ 20:16:
En dat slaat juist nergens op. Wiskundig gezien is een boolean een heel ander type dan een integer. De verzameling van boolean waarden = {true,false} en die van integer = {..-1,0,1,...} Zoals je ziet hebben ze geen enkel gemeenschappelijke waarde.
Fout. Elk statement, muv. control-statements en declaraties/definities, is een expressie in C. Het heeft met onze booleans te maken in die zin dat een boolean naar een int gecast kan worden terwijl een (onervaren) programmeur dat niet verwacht.Volgens mij klopt dit niet. Expressies zijn er genoeg in c, maar lang niet alles is een expressie en daarom heeft ook niet alles een return type. Het enigste waar ik van afweet dat alles een type heeft zijn sommige functionele programmeer talen, maar in c heeft bv een statement verder geen return type. Ik snap verder ook niet wat dit met het boolean verhaal te maken heeft.
Je bent niet te ruim, je bent gewoon ruim. Dat is nu net het verschil tussen een bondage-and-discipline taal en een language-of-choice. Een B&D taal dwingt je tot het programmeren volgens een bepaalde stijl of methodiek, die door de ontwikkelaar van de taal als zaligmakend getypeerd wordt.Aha, dus ik zou dan ook zo maar een string of record mogen casten naar een integer omdat dit een basis type is? Het is heel leuk voor c dat een integer ergens voor de meeste dingen gebruikt wordt. Maar je bent hierdoor te ruim met de typering van je expressies. Op zich kan dat heel handig zijn, maar fouten zijn heel lastig te detecteren.
Nonsense. Rekenen met booleans, pointers en what-have-you is niet wiskundig incorrect. Er bestaan meer algebra's dan jij of ik kunt opnoemen, en een voorbeeldje van een hele bekende algebra is nu juist de booleaanse algebra...Je kan dus kiezen voor een taal die ruim is met typeringen zodat sommige wiskundig foute dingen toch naar correcte types worden gecast.
Dit is het kritieke punt. De ontwikkelaar van een B&D-taal kiest er dus bewust voor zijn taal te "castreren" zodat mensen in zijn optiek "netjes programmeren". Bijna alle B&D talen beginnen dan ook hun bestaan als talen voor onderwijs-doeleinden, en zijn (in hun oorspronkelijke vorm) van weinig practisch nut (pascal is een goed voorbeeld).Of je kan kiezen voor een programmeer taal die streng is met zijn typering, en waarin iedere expressie wiskundig gezien correct is. Je verliest eventueel wat uitdrukking kracht, maar dat wordt gecompenseerd door een betere type ondersteuning van de taal.
Fout? Dat vind ik wat sterk uitgedrukt.mietje: Fout. Elk statement, muv. control-statements en declaraties/definities, is een expressie in C. Het heeft met onze booleans te maken in die zin dat een boolean naar een int gecast kan worden terwijl een (onervaren) programmeur dat niet verwacht.
Je zegt: "Elk statement, muv. control-statements en declaraties/definities, is een expressie in C.". Eerlijk gezegd ken ik geeneen statement in C die een expressie is. Statements zijn namelijk geen expressies. Expressies (zoals een methode aanroep of een vermenigvuldiging) kan je wel gebruiken als een statement: een statement expression. 1 van de statements is dus een statement expression. Expressies worden zo 'geinjecteerd' in statements en absoluut niet andersom (statements als expressies dus). Hooguit kan je aanvoeren dat de verzameling expressies erg groot is: prima, maar dat komt voornamelijk door het grote aantal operatoren.
Hetzelfde zie je terug in alle talen die stevig lenen van C: C++, C#, Java enz. C heeft geen veel ruimer gebrip van expressie dan bijvoorbeeld Java. Als je vind dat bijna alles in C een expressie is, kan je dit ook vinden over bijna elke veel gebruikte imperatieve taal.
Er zijn talen waar er een mindere scheiding is tussen statements en expressies (die in C dus vrij groot is). Zo is er in C bijvoorbeeld een aparte syntax voor een conditionele expressie en een aparte syntax voor een if-then-else constructie. Als C als visie zou hebben dat alles een expressie is, zou je toch minstens verwachten dat dat verschil niet aanwezig is.
Het meest extreem zie je een volledig opheffing van wat voor scheiding dan ook in functionele talen (Haskell, Clean) of talen die daar veel van we hebben (Stratego bijv). In functionele talen is alles een functie en het gebruik van de term 'alles' is hier een stuk beter op zijn plaats dan in je bewering dat in C alles een expressie is.
Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment
Wiskundig gezien is een boolean dus geen numerieke waarde. Maar toevallig gaan de meeste cpu`s er zo mee om, omdat zij werken met bits/bytes. Logisch gezien is een boolean dus een true of een false, en niet een 1 of een 0. In de (normale) logica. is deze uitspraak fout: 1 and true, omdat de and operator alleen is gedefinieerd voor bools.Verwijderd schreef op 05 augustus 2002 @ 18:45:
Dat slaat juist wel op een heleboel. Wiskundig gezien is een boolean een numeriek type; en wel een type dat exact één binaire digit kan opslaan.
Jij gaat precies de verkeerde kant op. Dat de boolean door de cpu wordt gezien als een bit, wil niet zeggen dat een boolean ook een numeriek type is. In de logica wordt over het algemeen heel duidelijk een onderscheid aangebracht tussen numerieke en boolean waardes.Dat men die binaire waardes in programmeertalen representeert als false en true wil niet zeggen dat boolean daarom geen numeriek type is.
Ik denk dat we nu een beetje op een welles nietes verhaal uitkomen. In c wordt een heel duidelijk onderscheid aangebracht tussen expressies en statements (pak maar eens een syntax beschrijving erbij). Alleen uit de naamgeving van de producties zou je kunnen afleiden dat je dus statements en expressies hebt. Verder hebben statements in c ook geen type, dus geven ze geen waarde terug waar iets meegedaan kan worden. Ik ben ze namelijk nog nooit tegen gekomen in een expressie, dus: int x = 10 + if(true){..};Fout. Elk statement, muv. control-statements en declaraties/definities, is een expressie in C. Het heeft met onze booleans te maken in die zin dat een boolean naar een int gecast kan worden terwijl een (onervaren) programmeur dat niet verwacht.
Als je een api ontwikkeld dan zet je een contract op tussen ontwerper en gebruiker van de api. Als de api zegt dat je een boolean moet meesturen, dan mag je geen integer meesturen, omdat je dan het contract verbreekt. Mbv zo`n b&d taal kan jij dat contract beter opdwingen en vroegtijdig dmv compile fouten een error opwerpen dat het contract verbroken is. Ik vind zo`n contract handig om mee te werken omdat dit mij veel tijd bespaard en dingen niet verkeerd geintepreteerd worden en je dus zelf expliciet een coersion moet maken. Ik neem aan dat je verder ook geen gebruikt maakt van dbc? Zijn ook van die zaligmakende technieken die hun nut steeds meer bewijzen, puur om iemand zich nog beter aan zijn contract te laten houden.Je bent niet te ruim, je bent gewoon ruim. Dat is nu net het verschil tussen een bondage-and-discipline taal en een language-of-choice. Een B&D taal dwingt je tot het programmeren volgens een bepaalde stijl of methodiek, die door de ontwikkelaar van de taal als zaligmakend getypeerd wordt.
Dat ligt er maar net aan op welke manier je er tegen aankijkt. Als je bv een electronicaman vraagt dan zal hij het zien als een bit(reeks), maar als je het een logicus vraagt dan zal hij een boolean als een true, false waarde zien. En als je aan een logicus het volgende voorlegt a=10+true dan zal hij zeggen dat er hier een typefout is opgetreden (dus wiskundig foute uitspraak). Ik heb verder in de klassieke logica`s (oa propositie en predicaten) ook nog nooit een bit als boolean geintepreteerd gezien, alleen als je meer richting hardware gaat zul je dit meer tegenkomen.Nonsense. Rekenen met booleans, pointers en what-have-you is niet wiskundig incorrect. Er bestaan meer algebra's dan jij of ik kunt opnoemen, en een voorbeeldje van een hele bekende algebra is nu juist de booleaanse algebra...
Zoals ik boven al hebt vermeld, vind ik dit geen castreren, maar een hulpmiddel om fouten op te lossen omdat er iets gebeurt wat schijnbaar de bedoeling niet was. En verder zijn imperatieve b&d talen zoals java, c#, delphi toch vrij bekend, er bestaan schijnbaar nog meer talen dan c.Dit is het kritieke punt. De ontwikkelaar van een B&D-taal kiest er dus bewust voor zijn taal te "castreren" zodat mensen in zijn optiek "netjes programmeren". Bijna alle B&D talen beginnen dan ook hun bestaan als talen voor onderwijs-doeleinden, en zijn (in hun oorspronkelijke vorm) van weinig practisch nut (pascal is een goed voorbeeld).
Verwijderd
Nu potverdorie, lees eens wat ik schrijf. In de wiskunde is een boolean een numerieke waarde, en er bestaat een complete algebra om met die waardes te rekenen: boolse algebra. Doe eens een google op boolean algebra en lees enkele van de meer dan 106000 hits...Alarmnummer schreef op 05 augustus 2002 @ 20:57:
Wiskundig gezien is een boolean dus geen numerieke waarde. Maar toevallig gaan de meeste cpu`s er zo mee om, omdat zij werken met bits/bytes. Logisch gezien is een boolean dus een true of een false, en niet een 1 of een 0. In de (normale) logica. is deze uitspraak fout: 1 and true, omdat de and operator alleen is gedefinieerd voor bools.
<edit>
deze link is relevant en duidelijk, je ziet in een oogopslag hoe er met logische waardes gerekend wordt.
</edit>
If is dus een control-statement. Statements als x= 3 + 5; gedragen zich als expressies in C. Voor de duidelijkheid, de eigenlijke expressie is "3 + 5", maar het resultaat van die expressie wordt door het statement heen gepropageerd zodat dingen als y= x= 3 + 5; mogelijk zijn. Dat kan alleen als het statement "x= 3 + 5" als een expressie wordt geevalueerd.Verder hebben statements in c ook geen type, dus geven ze geen waarde terug waar iets meegedaan kan worden. Ik ben ze namelijk nog nooit tegen gekomen in een expressie, dus: int x = 10 + if(true){..};
Maar waarom nu toch? Het is zuiver een (taal)conventie of het contract wel gebroken is. Als de taalconventie is dat een integer naar een boolean gedowncast kan worden, dan is er geen breech-of-contract. Je redeneert dus vanuit jouw favoriete taal, en overal waarin C verschilt van het bondage-gedrag van jouw taal zie jij een fout in het design van C. Dat is natuurlijk niet zo, het zijn gewoon talen die ontworpen zijn met een verschillend doel voor ogen: net als in het werkelijke leven, is de docent voor de klas vaak strenger en conservatiever dan de baas op het werk.Als je een api ontwikkeld dan zet je een contract op tussen ontwerper en gebruiker van de api. Als de api zegt dat je een boolean moet meesturen, dan mag je geen integer meesturen, omdat je dan het contract verbreekt. Mbv zo`n b&d taal kan jij dat contract beter opdwingen en vroegtijdig dmv compile fouten een error opwerpen dat het contract verbroken is.
[ Voor 0% gewijzigd door Verwijderd op 05-08-2002 23:59 . Reden: link toegevoegd ]
Nee, een statement als x= 3 + 5; gedraagt zich niet als expressie. Een expressie gevolgd door een ; is een statement. x=5+3 /*geen ; */ is dus een expressie, net zoals x en 5+3 en 5.Verwijderd schreef op 05 augustus 2002 @ 23:35:
[...]
Statements als x= 3 + 5; gedragen zich als expressies in C. Voor de duidelijkheid, de eigenlijke expressie is "3 + 5", maar het resultaat van die expressie wordt door het statement heen gepropageerd zodat dingen als y= x= 3 + 5; mogelijk zijn. Dat kan alleen als het statement "x= 3 + 5" als een expressie wordt geevalueerd.
De exacte regels waarom in y=x=5+3 zowel x als y 8 worden verschillen lichtelijk tussen C en C++ (o.a. omdat in C++ x en y objecten kunnen zijn, met user-defined operator=), maar geen van beide werkt precies zoals je beschrijft. In C is int a[x=3+5]; iirc een legaal non-statement die de expressie evengoed evalueert, en de waarde aan x toewijst. Zonder de x is het triviaal. Dus voor expressie-evaluatie is een statement niet verplicht.
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Ik ben het met je eens dat een boolse algebra een 0 en 1 heeft voor een true en false, en dat + en * operatoren worden gebruikt om een or en and te maken. Maar dat wil niet zeggen dat je die types met elkaar kan combineren omdat ze toevallig dezelfde characters gebruiken. True en false zijn vollig andere concepten dan de waarden 0 en 1!Verwijderd schreef op 05 augustus 2002 @ 23:35:
[...]
Nu potverdorie, lees eens wat ik schrijf. In de wiskunde is een boolean een numerieke waarde, en er bestaat een complete algebra om met die waardes te rekenen: boolse algebra. Doe eens een google op boolean algebra en lees enkele van de meer dan 106000 hits...
Wat c doet is er een rommeltje van maken waarin bv een rekenkundige plus operator wordt gebruikt ipv een boolse plus operator.
1
2
3
4
5
6
| rekenkundig bools true true 1 1 //conversie -(1)=-1 -(1)=0 // negatie -1+1=0 0+1=1 // +1 (rekenkundig:1 erbij, bools:or true) false true |
Zoals je ziet gaat het behoorlijk fout als je je rekenkundige operaties loslaat op boolse waarden omdat ze volledig andere types zijn. Dit probleem had voorkomen kunnen worden door een boolean type hiervan te maken (zodat ook de juiste boolse operaties waren gekozen) zoals vele andere talen dit wel hebben gedaan.
Maar ik zal c niet volledig afvallen. C is een bloedsnelle taal omdat programmeurs allerlei shortcuts kunnen nemen. C is daarom ook nog steeds de taal voor driver development en os`en en alle andere dingen die bloedsnel moeten zijn. Je moet gewoon weten wanneer je het gebrek aan typesafety(en toegenomen kans op fouten) op prijs gaat stellen in ruil voor snelheid.
Dat hoeft niet, je zou dit gerust kunnen maken als productie regel:If is dus een control-statement. Statements als x= 3 + 5; gedragen zich als expressies in C. Voor de duidelijkheid, de eigenlijke expressie is "3 + 5", maar het resultaat van die expressie wordt door het statement heen gepropageerd zodat dingen als y= x= 3 + 5; mogelijk zijn. Dat kan alleen als het statement "x= 3 + 5" als een expressie wordt geevalueerd.
1
2
3
| assignment
= (variable '=')+ expression
; |
Zoals je ziet hoeft zo`n declaratie helemaal geen expressie te zijn.
Het gaat niet zozeer om een taal conventie, maar het gaat om het zo veel mogelijk de gebruiker(mezelf ook) helpen en daardoor minder tijd nodig ben om allerlei triviale fouten te moeten oplossen.Maar waarom nu toch? Het is zuiver een (taal)conventie of het contract wel gebroken is. Als de taalconventie is dat een integer naar een boolean gedowncast kan worden, dan is er geen breech-of-contract. Je redeneert dus vanuit jouw favoriete taal, en overal waarin C verschilt van het bondage-gedrag van jouw taal zie jij een fout in het design van C. Dat is natuurlijk niet zo, het zijn gewoon talen die ontworpen zijn met een verschillend doel voor ogen: net als in het werkelijke leven, is de docent voor de klas vaak strenger en conservatiever dan de baas op het werk.
Ik ben op dit moment bezig met een taal die nog veel strenger is dan java. Het is jou ook vast wel eens overkomen dat je een nullpointer fout hebt gekregen (in het geval van c eventueel 'gek' gedrag). Dit komt omdat je voor ieder adres een null of een non null waarde mag krijgen. Vaak wordt op een of andere manier die null een super type gemaakt van veel types of hij wordt weggestreept in het typemechanisme.
Het probleem is dat je dus geen onderscheid meer kan maken tussen null en non null waardes wat inhoud dat je dus een null binnen kan krijgen terwijl dit volgens het contract niet mag. Vaak worden er precondities gebruik (in dit geval een null check) om alsnog voor te zorgen dat het contract niet verbroken kan worden.
Maar het zou nog veel handiger zijn om aan te geven in het type of je wel of geen null aankan. Je zou bijvoorbeeld kunnen zeggen dat een object waarde nooit null kan zijn (object heeft dus per definitie een non null waarde). Als je dan de volgende methode hebt: add(Persoon p) dan weet je dat p nooit null kan zijn, omdat Persoon nooit null kan zijn.
Als je bv wel een null accepteerd dan zou je ook een union type kunnen maken (union type is een type de zich kan gedragen als type A of als type B ). Als je nu het volgende union type gaat maken: union(Persoon,NULL), dan weet je nu dat je dus een null waarde aankan of een echte persoon. Dan zou je als volgt een methode kunnen maken die wel een null aankan:
add(union(Persoon,NULL) p)
en dit zou je kunnen vereenvoudigen mbv syntactisch suiker tot:
add(Persoon? p).
Dezelfde '?' zou je ook kunnen toepassen in de rest van de taal.
(voor de duidelijkheid NULL is het type van null)
Stel nu dat je de volgende methode hebt:
void add(Persoon p){
...
}
en het volgende stukje aanroepende code:
Persoon? jan = ...;
add(jan)
dan krijg je een compiletime type foutmelding, omdat het type van jan ruimer is dan het type van p (jan is dus null of non null, en de methode kan alleen non null aan).
Dit is een klein voorbeeldje hoe je door strengere typering compile time voor safety kan zorgen. In dit geval zal het dus nooit meer voorkomen dat je een methode aanroept met een null als hij daar niet voor gebouwd is, want je krijgt nu compile time al een foutmelding.
Over het algemeen kun je met een strenger type systeem veel elegantere code in elkaar zetten omdat je code niet meer 'vervuild' raakt met allerlei preconditie code of gammel worden door gebrek aan. Maar het belangrijkste punt aan mijn verhaal is dat code een middel is om een systeem te modeleren, en ik wil zoveel mogelijk ondersteuning om de correctheid van dat model te garanderen zodat ik kan garanderen dat de software ook doet wat het moet doen.
MSalters zei het al prima (en ik schreef eerder ook al wat hierover) maar misschien dat een beetje grammatica het nog duidelijk maakt. Ik schets het even globaal, zonder exact alle varianten en toestanden in C te noemen.mietje: If is dus een control-statement. Statements als x= 3 + 5; gedragen zich als expressies in C. Voor de duidelijkheid, de eigenlijke expressie is "3 + 5", maar het resultaat van die expressie wordt door het statement heen gepropageerd zodat dingen als y= x= 3 + 5; mogelijk zijn. Dat kan alleen als het statement "x= 3 + 5" als een expressie wordt geevalueerd.
Een assignment is een expressie (overigens met de laagste prioriteit van alle expressies):
1
| LValue AssignOp AssignExpr -> AssignExpr |
Deze productie regel uit een C grammatica is zwaar vekracht om prioriteiten goed te regelen. AssignExpr is een expressie, waarbij deze non-terminal in het leven is geroepen om de prioriteiten van expressies goed te kunnen controleren. Als je prioriteiten los kunt definieren krijg je een duidelijkere regel:
1
| LValue AssignOp Expr -> Expr |
Expressies mag je gebruiken als statements:
1
| Expr ";" -> Stm |
'Echte' statements ontstaan niet uit de toepassing van deze productie regel op expressie. 'Echte' statements zijn dus eigenlijk de statements, die wel statement moeten zijn omdat ze geen expressie zijn. Productie regels voor deze statements produceren direct een non-terminal statement.
Een paar voorbeelden (uit een Java grammatica, heb geen mooi voor C bij de hand):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| "{" BlockStm* "}" -> Block {cons("Block")}
Block -> Stm
LocalVarDec -> BlockStm
Stm -> BlockStm
Type {VarDec ","}+ ";" -> LocalVarDec {cons("LocalVarDec")}
Expr ";" -> Stm {cons("Expr")}
";" -> Stm {cons("Empty")}
Id ":" Stm -> Stm {cons("Labeled")}
"assert" Expr ";" -> Stm {cons("Assert")}
"assert" Expr ":" Expr ";" -> Stm {cons("Assert")}
"if" "(" Expr ")" Stm -> Stm {cons("If")}
"if" "(" Expr ")" Stm "else" Stm -> Stm {cons("If")}
"while" "(" Expr ")" Stm -> Stm {cons("While")}
"do" Stm "while" "(" Expr ")" ";" -> Stm {cons("DoWhile")}
"for" "(" ForInit? ";" Expr? ";" ForUpdate? ")" Stm -> Stm {cons("For")}
LocalVarDec -> ForInit
{StmExpr ","}+ -> ForInit
{StmExpr ","}+ -> ForUpdate
"break" Id? ";" -> Stm {cons("Break")}
"continue" Id? ";" -> Stm {cons("Continue")}
"return" Expr? ";" -> Stm {cons("Return")}
"throw" Expr ";" -> Stm {cons("Throw")}
"try" Block CatchClause+ -> Stm {cons("Try")}
"try" Block CatchClause* "finally" Block -> Stm {cons("Try")}
"catch" "(" FormalParam ")" Block -> CatchClause {cons("Catch")}
"synchronized" "(" Expr ")" Block -> Stm {cons("Synchronized")}
"switch" "(" Expr ")" SwitchBlock -> Statement {cons("Switch")} |
De hele stelling dat alles in C een expressie is, wordt wat mij betreft voornamelijk verkracht door het feit dat er een aparte syntax is voor conditionele expressies en conditionele uitvoering van statements. De scheiding in 2 (meer eigenlijk, maar goed) productie-regels is nodig omdat er dus andere statements zijn die niet als expressie te gebruiken zijn, maar dit is wat mij betreft geen excuus om ook een andere syntax te kiezen. Overigens zou ik in Java ook veel meer zaken als expressie willen zien. Met name de if-then-else uiteraard, maar ook bijvoorbeeld de try-catch. Alles zou pas echt een expressie zijn als alle statements grammaticaal gezien een expressie zouden kunnen zijn (ook de for en while loops dus). Semantische analyse zou dit gebruik dan kunnen uitsluiten omdat het uiteraard niet bepaald logisch is om een for loop als expressie te gebruiken.
Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment
Ik vind 'strenger' niet echt een juiste term voor de taal waar jij op doelt, maar ik begrijp wat je bedoeltAlarmnummer :Ik ben op dit moment bezig met een taal die nog veel strenger is dan java.
Bij Alarmnummer moet hij er uiteraard achter in plaats van ervooren dit zou je kunnen vereenvoudigen mbv syntactisch suiker tot: add(Persoon? p).
Dezelfde '?' zou je ook kunnen toepassen in de rest van de taal.
Ik zie 'strenger' liever als correcter of krachtiger. Het type-systeem van functionele talen is zo krachtig dat je je werkelijk volledig uit kunt leven. Dit heeft niet zozeer met strengheid te maken, maar vooral met de logica, uitgebreidheid en geavanceerdheid van het type-systeem.Over het algemeen kun je met een strenger type systeem veel elegantere code in elkaar zetten
Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment
We hadden het over streng zijn van talen, dus het was nog niet zo erg misplaatstmbravenboer schreef op 06 augustus 2002 @ 02:52:
[...]
Ik vind 'strenger' niet echt een juiste term voor de taal waar jij op doelt, maar ik begrijp wat je bedoelt. Voor de niet Javahova bezoeker: het gaat hier om features die we tegen kwamen in Nice .
Bij Alarmnummer moet hij er uiteraard achter in plaats van ervoor
Nice is Nice
Sorry, maar JIJ maakt er een zooitje van. Booleaanse algebra heeft geen unaire operator-Alarmnummer schreef op 06 augustus 2002 @ 00:53:
[...]
Wat c doet is er een rommeltje van maken waarin bv een rekenkundige plus operator wordt gebruikt ipv een boolse plus operator.
code:
1 2 3 4 5 6 rekenkundig bools true true 1 1 //conversie -(1)=-1 -(1)=0 // negatie -1+1=0 0+1=1 // +1 (rekenkundig:1 erbij, bools:or true) false true
(tenzij je'm defineert als de identity operator, in welk geval de resultaten identiek zijn aan de rekenkundige operator )
Zo ken ik ook nog wat wiskunde die aantoont dat -1==1.
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Verwijderd
Het is me in de laatste dagen regelmatig dat ik een post van meer dan 50 regels kwijtraak door dit amateuristische gesleutel aan een live forum.Fatal error: Cannot instantiate non-existent class: timer in /mnt/atlas/web/react/got/react/global/non-www/classes/engine.class.inc.php on line 294
Als het stabiel loopt post ik wel verder.
Het forum loopt inderdaad nog niet zoals het moet. Ik edit al mijn berichten in notepad en dan plaatst ik het hierin. Ik heb het ook al te vaak meegemaakt dat ik mijn post ben kwijt geraakt. En verder vind ik ik slecht editen in dat kleine rotschermpje van GoT.Verwijderd schreef op 06 augustus 2002 @ 14:20:
Ik krijg verdomme ALWEER foutmeldingen bij het posten van een reaktie op dit forum!
[...]
Het is me in de laatste dagen regelmatig dat ik een post van meer dan 50 regels kwijtraak door dit amateuristische gesleutel aan een live forum.
Moet ik wachten om verder te bekvechtenAls het stabiel loopt post ik wel verder.
Dat true en false in C/C++ gewoon getallen zijn is dus volledig volgens boole's beschrijving. Dat ze gebruikt kunnen worden in dezelfde wiskundige stellingen als 'gewone' wiskundige bewerkingen is fout.
Localhost, sweet localhost
[edit]
Ik was ff te voorbarig. Ik ben het met je eens, dat booleans niet gebruikt kunnen worden in normale integer expressies.
Verwijderd
Nee, laat dat uitleggen maar, want je beweringen kloppen gewoon niet.Alarmnummer schreef op 06 augustus 2002 @ 15:45:
Het mag dan wel volgens de beschrijving zijn dat het een 1 en een 0 is, maar een int is niet van het boolean type en een andere getal dan 1 of 1 heeft in boolse algabra geen betekenis terwijl het toch mogelijk is als je een int gebruikt. Daarnaast is er een verschil tussen een boolse + (een or dus) en een rekenkundige +. Ik hoop niet dat ik dit keer op keer hoef uit te leggen!!!
Een boolean 1 en 0 werken exact hetzelfde in boolse algebra als een 1 en een 0 in een integer algebra. 1 is in zowat alle algebra's het eenheidselement, waarvoor geldt x * 1 = x, en 0 is het nulelement waar in bijna algebra's voor geldt x * 0 = 0. De boolse + en * zijn ook volledig congruent met de integer + en
Wat ik in mijn vorige post wilde schrijven: je hakt er op in dat een boolean wordt gecast naar een integer, maar je vindt het geen probleem dat integers naar floating-points worden gecast en vice versa? Een float is ook echt een ander numeriek type dan een int, en de operatoren werken ook niet exact het zelfde, hoewel ze algebraisch de zelfde definitie hebben.
[ Voor 0% gewijzigd door Verwijderd op 06-08-2002 16:13 . Reden: typo ]
integer.MAX_VALUE+integer.MAX_VALUE
echt een fout opleveren, want je raakt buiten het domein van de integer. Dit geld ook voor die 1+1 met bits, want een 2 valt buiten het domein van de bit. Bij een boolse operator zal dit wel goed gaan. Ik hoop dat ik je nu (eindelijk)
Verder is ieder natuurlijk getal een reeel getal. Daarom is in principe ook iedere int een float en derhalve kan die conversie ook gemaakt worden.
1
| array[ size / 2] |
Als ik nou zou zeggen:
1
2
3
4
5
| int i=0; int j=5; float f = 2.0; i = j / 2 * f; |
Wat is dan de waarde van i? (4 of 5?)
Ik ben van mening dat een compiler dit hoort te weigeren, of er in ieder geval voor moet waarschuwen. (ik neem aan dat je compileert met -wall)
[ Voor 0% gewijzigd door kvdveer op 06-08-2002 16:24 . Reden: brak forum ]
Localhost, sweet localhost
Verwijderd
/me zucht.Alarmnummer schreef op 06 augustus 2002 @ 16:18:
Als je gaat rekenen met normale integers, dan zal dit.
integer.MAX_VALUE+integer.MAX_VALUE
echt een fout opleveren, want je raakt buiten het domein van de integer. Dit geld ook voor die 1+1 met bits, want een 2 valt buiten het domein van de bit. Bij een boolse operator zal dit wel goed gaan. Ik hoop dat ik je nu (eindelijk)kan laten inzien dat de werking van een boolse + niet hetzelfde is als een integer +.
Ik heb het over algebra's, niet over de beperkingen van computerimplementaties van getallen. Een bool operatie kan per definitie geen overflow hebben omdat de cardinaliteit van de boolse verzameling 2 is, en een operator een bewerking is die een domeinverzameling afbeeldt op een gelijke bereikverzameling. Als je dus de verzameling { 0, 1 } afbeeldt op { 0, 1 } dan kun je nooit een overflow krijgen (in de vorm van 2 ofzo).
Op een zelfde manier kan er binnen de verzameling van integers algebraisch nooit een overflow optreden. Die overflows zijn er het resultaat van dat je met de beperkte opslagcapaciteit van computers geen oneindige verzameling kunt afbeelden.
Je kunt overflows dus nooit gebruiken om te bewijzen dat algebra's verschillen, want in de algebra bestaan er geen overflows.!
En net zo is elke boolean een integer, de verzameling van booleans is een deelverzameling van de verzameling van integers, net zo als de verzameling van integers een deelverzameling is van de reals.Verder is ieder natuurlijk getal een reeel getal. Daarom is in principe ook iedere int een float en derhalve kan die conversie ook gemaakt worden.
Als je nog een keer kijkt naar die + operator dan zou je hem kunnen definieren voor Z, maar je zou hem net zo goed kunnen definieren voor A. Als je hem defnieerd voor Z en het return type kan ook Z zijn, dan weet je dat je nooit een overflow krijgt. Maar als je wilt dat het resultaat van het type A is, dan kan het wel voorkomen dat overflow foutmelding krijgt omdat de som van 2 waardes niet altijd element is van A.
Dit is geen fout van de computer, maar dit is gewoon de definitie van die plus operator. Ik kan A ook als [10..25] definieren. Je weet nu zeker dat het resultaat van in een 8 bits integer past, en alle plus operatories door de computer uitgevoerd kunnen worden, maar in sommige gevallen is het type van de som niet gelijk aan A en moet je een foutmelding krijgen.
Ok. Dit is een heel verhaal waarmee ik duidelijk wil maken dat je heel goed met types en operatoren kan werken waarmee je soms wel overflows kan en wil krijgen en dat ermeer integer types zijn dan alleen de alles omvattende integer type:Z en dat er ook een menselijke behoefte is aan die andere integer types. En het belangrijkste punt is dat deze overflows niet ontstaan door een tekortkoming aan de pc, maar alleen ontstaan door de definitie van een operator. Ik hoop dat je het tot zover met me eens bent.
Nu ga ik nog een keer de stap ondernemen om terug te gaan naar type Bit:[0,1] (dit is een integer type). Ik ga nu nog een keer de + operator definieren waarvoor moet gelden dat het resultaat ook van het type Bit is.
0+0=0
0+1=1
1+0=1
1+1=overflow.
Ik zal nog nog een keer duidelijk uitleggen waarom hier dus wel een overflow optreed. Het resultaat van 1+1 is dus 2, maar aangezien 2 geen element van Bit, moet je dus een foutmelding opwerpen. Het is dus onjuist om te zeggen dat je 1+1 dan 1 moet maken omdat dit in strijd is met de definitie van een plus operator in het algemeen.
Nu hoop ik echt dat je het met mee eens bent, want anders loop ik dit allemaal voor niets te typen.
Nu ga ik nog een keer de + operator definieren voor de bool.
0+0=0
0+1=1
1+0=1
1+1=1
Zoals je ziet krijg je dus bij de boolean versie geen overflow omdat dit nergens op zou slaan.
1
2
3
4
| 1+1 true or true //vertaling true //tautologie 1 //terug vertalen |
je ziet nu dus dat er een verschil in definitie is voor de bit + en de boolse +
Verder vind ik ook nog steeds dat een bool een volledig ander concept is dan een integer, en dit verschil dwing ik ook op in api`s. Ik denk ook niet dat we elkaar kunnen overtuigen, maar persoonlijk vind ik het typesysteem van C te zwak en dit maakt de taal onnodig gecompliceerd en foutgevoeliger. Ik denk ook niet dat ik je verder kan overtuigen en ik heb er eigelijk ook geen zin meer in om tijd eraan te verspillen.
Verwijderd
Nee, dat is niet de reden voor overflows. Als je gewoon afbeeldt van A => A, dan is er technisch gesproken geen overflow! Het probleem ontstaat doordat je stelt dat A = Z, terwijl dat niet zo is. De overflow vindt dus plaats omdat je met verzameling A werkt, terwijl je een element uit verzameling Z verwacht. Dát is een overflow!Alarmnummer schreef op 06 augustus 2002 @ 18:40:
Als je nog een keer kijkt naar die + operator dan zou je hem kunnen definieren voor Z, maar je zou hem net zo goed kunnen definieren voor A. Als je hem defnieerd voor Z en het return type kan ook Z zijn, dan weet je dat je nooit een overflow krijgt. Maar als je wilt dat het resultaat van het type A is, dan kan het wel voorkomen dat overflow foutmelding krijgt omdat de som van 2 waardes niet altijd element is van A.
Het is niet strijdig met de + operator. Ik heb je al uitgelegd dat een operator een domein afbeeldt naar een gelijk bereik, en aangezien "overflow" geen element is van het domein, kan het ook niet in het bereik terecht komen. Het is dus onjuist om te stellen dat 1 + 1 = 2, dat ligt aan de algebra waarin je rekent! Snap dat nu toch!Ik zal nog nog een keer duidelijk uitleggen waarom hier dus wel een overflow optreed. Het resultaat van 1+1 is dus 2, maar aangezien 2 geen element van Bit, moet je dus een foutmelding opwerpen. Het is dus onjuist om te zeggen dat je 1+1 dan 1 moet maken omdat dit in strijd is met de definitie van een plus operator in het algemeen.
Ik bedoel dit serieus en niet om je te beledigen, maar ik zou er nog eens wat wiskunde op naslaan als ik jou was. Het klopt namelijk gewoon niet wat je stelt, de eigenschappen van zowel de + als de * operator zijn exact gelijk in de boolse en de integer algebra. Exact gelijk!Nu hoop ik echt dat je het met mee eens bent, want anders loop ik dit allemaal voor niets te typen.
onzin:Ik heb je al uitgelegd dat een operator een domein afbeeldt naar een gelijk bereik
Er gaat bij jouw iets fout om te stellen dat het return type van een operator altijd gelijk is aan het type van zijn argumenten. Stel ik heb het volgende type [m..n] dan weet ik dat het type van de inc functie : [m..n] -> [m+1..n+1].
Als je gaat stellen dat het type van inc [m..n]->[m..n] is, dan kan je voor n geen waarde terug sturen, omdat het resultaat (n+1) geen element is van [m..n] In dit geval geef je dus een foutmelding omdat de waarde niet gedefinieerd is binnen het result type. Dit doe je ook omdat 2 niet is gedefinieerd binnen het return type Bit.
Schijnbaar het je problemen met overflows en type fouten. Ik denk dat je daar echt even in moet verdiepen. Ik raad je de volende literatuur aan:+ als de * operator zijn exact gelijk in de boolse en de integer algebra
On understanding types, data abstraction, and polymorphism
Verwijderd
Moehaha
NEEEEEEEEEEEE. Ten eerste is "inc" algebraisch geen operator maar een functie, namelijk "f(x) = x + 1". Dan hebben we het dus over de operator + en die beeldt wel degelijk { 0, 1, 2, ... } => { 0, 1, 2, ... } af, kijk maar:Er gaat bij jouw iets fout om te stellen dat het return type van een operator altijd gelijk is aan het type van zijn argumenten. Stel ik heb het volgende type [m..n] dan weet ik dat het type van de inc functie : [m..n] -> [m+1..n+1].
0 + 0 = 0
1 + 0 = 1
2 + 0 = 2
enz.
Als je gaat stellen dat het type van inc [m..n]->[m..n] is, dan kan je voor n geen waarde terug sturen, omdat het resultaat (n+1) geen element is van [m..n] In dit geval geef je dus een foutmelding omdat de waarde niet gedefinieerd is binnen het result type. Dit doe je ook omdat 2 niet is gedefinieerd binnen het return type Bit.
+ en * exact gelijk in de booleaanse en integer algebra?
1+1 = 1 (want true or true = true) en 1+1=2
1+1+1+1+1+1+0+1 = 1 en 1+1+1+1+1+1+0+1 = 7
1*1 = 1 (want true and true = true) en 3*3=9 (ik pak een 3 ja.. "willekeurig" element uit de integer algebra)
Ik zie niet in wat hier hetzelfde aan is. Tenzij je afspreekt dat als je buiten het bereik komt, je het laatste element gebruikt (net als in C want 0= false =0 , 1 = true = 1 en 4235 = true = 1). maar die afspraak is in de booleaanse algebra toch niet gemaakt, aangezien in de booleaanse algebra alleen maar gebruik gemaakt wordt van 0 en 1.
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
functie is prefix geschreven operator. It`s all the same. Ik zal het nog gekker stellen. In principe hoef je helemaal geen operatoren en operanden te hebben, maar alleen nog maar functies.
En verder beeld een inc functie [m..n] niet af op [m..n] maar op [m+1..n+1]
lees nou dat stuk nou eerst maar eens door.
Je snapt het uistekendCreepy schreef op 06 augustus 2002 @ 21:02:
ik ga hier volgens mij totaal de mist in omdat ik iets mis.. maaruh...
+ en * exact gelijk in de booleaanse en integer algebra?
1+1 = 1 (want true or true = true) en 1+1=2
1+1+1+1+1+1+0+1 = 1 en 1+1+1+1+1+1+0+1 = 7
1*1 = 1 (want true and true = true) en 3*3=9 (ik pak een 3 ja.. "willekeurig" element uit de integer algebra)
Ik zie niet in wat hier hetzelfde aan is. Tenzij je afspreekt dat als je buiten het bereik komt, je het laatste element gebruikt (net als in C want 0= false =0 , 1 = true = 1 en 4235 = true = 1). maar die afspraak is in de booleaanse algebra toch niet gemaakt, aangezien in de booleaanse algebra alleen maar gebruik gemaakt wordt van 0 en 1.
Verwijderd
Ok, ik probeer het nog simpeler uit te leggen.Creepy schreef op 06 augustus 2002 @ 21:02:
ik ga hier volgens mij totaal de mist in omdat ik iets mis.. maaruh...
+ en * exact gelijk in de booleaanse en integer algebra?
1+1 = 1 (want true or true = true) en 1+1=2
1+1+1+1+1+1+0+1 = 1 en 1+1+1+1+1+1+0+1 = 7
In de boolse algebra zijn er maar twee numerieke waardes, het eenheidselement en het nulelement. Maw. in de boolse algebra reken je maar met twee waardes: "iets" (1) en "niets" (0); alle operaties kunnen alleen "iets" of "niets" als resultaat hebben.
Zo is dus "iets" + "iets" + "iets" + ... = "iets"; want het is meer dan "niets", en er kan alleen "iets" of "niets" uitkomen.
Op precies de zelfde manier kun je bv. nooit een gebroken getal krijgen als je twee natuurlijke getallen met elkaar optelt of vermenigvuldigt; als je twee natuurlijke gatallen optelt of vermenigvuldigt komt daar altijd een natuurlijk getal uit. Het enige verschil is dat er maar twee boolse getallen zijn { 0, 1 } terwijl er oneindig veel natuurlijke getallen zijn { 0, 1, 2, ... }
Als je nu eens in "iets" en "niets" denkt ipv. "true" en "false"; dan zul je zien dat de operatoren exact het zelfde werken en hoeveelheden beschrijven, zowel in de integer als in de boolse algebra.
ps.
ik denk dat jij je je wiskunde er nog even goed bij moet pakken. Want een operator hoeft echt niet op hetzelfde type af te beelden als het type van zijn argument. bv:
10 realdiv 20 = 0.5
Je gaat hier heel duidelijk van (2) integers naar een float.
Ga je maar eens verdiepen in functionele programmeertalen ed en dan praten we wel weer.
Tsja, het wil niet echt lukken hè.Alarmnummer schreef op 06 augustus 2002 @ 21:16:
in jouw geval zijn in de normale (dus niet boolse) algebra 1+1 ook 1 zijn omdat iets + iets is iets.
In de niet-booleaanse algebra is 0 het (enige) identiteits-element van de + functie. Als 1+1 =1 dan is dus 1 gelijk aan 0, wat in tegenspraak is met het axioma van de unieke 0.
In boolean algebra is er geen uniek identiteits element van +
In C en C++ heeft + zo'n indenteits element dan en slechts dan als het niet voor booleaanse algebra wordt gebruikt.
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Verwijderd
Nope, want in het normale geval heb je als domein en bereik { 0, 1, 2, ... } en niet { 0, 1}Alarmnummer schreef op 06 augustus 2002 @ 21:16:
in jouw geval zijn in de normale (dus niet boolse) algebra 1+1 ook 1 zijn omdat iets + iets is iets.
Geloof me alsjeblieft, ik verkoop hier geen lulkoek. De term "algebra" houdt intrensiek in dat er met waardes, hoeveelheden wordt gerekend. Met welke waardes er gerekend wordt, hangt af van de verzameling waarop men die algebra loslaat. Daarom krijg je verschillende resultaten als je gelijk gedefinieerde operatoren in de verzamelingen B, N, Z, Q, R of C gebruikt.
Maar dan benoem je dus de 0 uit de normale algebra "niets", en al het andere uit de normale algebra "iets".Verwijderd schreef op 06 augustus 2002 @ 21:14:
[...]
Ok, ik probeer het nog simpeler uit te leggen.
In de boolse algebra zijn er maar twee numerieke waardes, het eenheidselement en het nulelement. Maw. in de boolse algebra reken je maar met twee waardes: "iets" (1) en "niets" (0); alle operaties kunnen alleen "iets" of "niets" als resultaat hebben.
Zo is dus "iets" + "iets" + "iets" + ... = "iets"; want het is meer dan "niets", en er kan alleen "iets" of "niets" uitkomen.
Op precies de zelfde manier kun je bv. nooit een gebroken getal krijgen als je twee natuurlijke getallen met elkaar optelt of vermenigvuldigt; als je twee natuurlijke gatallen optelt of vermenigvuldigt komt daar altijd een natuurlijk getal uit. Het enige verschil is dat er maar twee boolse getallen zijn { 0, 1 } terwijl er oneindig veel natuurlijke getallen zijn { 0, 1, 2, ... }
Als je nu eens in "iets" en "niets" denkt ipv. "true" en "false"; dan zul je zien dat de operatoren exact het zelfde werken en hoeveelheden beschrijven, zowel in de integer als in de boolse algebra.
In C is dit geldig: true-false. Bestaan in booleaanse algebra de -?
Goed...dat bestaan over de - laten we achterwege, en we rekenen met de booleans net zo als met integers (want zoals jij het stelt werken de + en * operatoren exact hetzelfde in de normale en de booleaanse algebra.. Als dat zo is mogen we de - en / toch ook gebruiken??)
true - false = true (want 1 - 0 = 1)
1 - false = true (want alweer 1 - 0 =1)
true - true = false (want 1 - 1 = 0)
Wat is nu 99 - true? Is dat true (want 99-1 = 98) of is dat toch false want true - true = false?
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Verwijderd
Ik ben het met je eens dat je als je in N of Z werkt 10/20 een 0 eruit krijgt. Maar stel nu dat ik niet in N of Z werk, maar in [10..20]. 10/20 levert een 0 op, en dat element komt niet voor in [10..20], dus je kan geen waarde terug sturen, dus dan een foutmelding.
Als [10..20] een type was zoals N het ook is, zou je het dan met me eens zijn?
Verwijderd
Informatietechnisch heb je natuurlijk volledig gelijk, je kijkt dan tegen enorme algebraische gaten aan, en het is nogal practisch te signaleren dat je in zo'n gat gevallen bent.
Maar wat vind jij dan van deze uitspraak? bool a = 2;
heeft dit een betekenis in boolean algebra?
[ Voor 0% gewijzigd door Alarmnummer op 06-08-2002 21:58 . Reden: kromme zin ;) ]
Verwijderd
Nee, het heeft net zo weinig betekenis als int i = 2.0; in integer algebraAlarmnummer schreef op 06 augustus 2002 @ 21:57:
Ok, we komen dichter bij het eindstation
Maar wat vind jij dan van deze uitspraak? bool a = 2;
heeft dit een betekenis in boolean algebra?
Waar we dan langs omwegen door de wondere wereld der verzamelingenleer op terug komen, is het impliciete cast-gedrag van een programmeertaal
Jij bent van het strenge soort en vervloekt alle downcasts, omdat er bij een downcast gegevensverlies kan optreden. Ik ben van de soepele soort, die zegt dat mensen in de praktijk constant met verschillende numerieke types door elkaar rekenen en daarbij impliciet downcasten, en dat het daarom niet gek is als een programmeertaal dat ook kan, ipv. het als een fout af te doen.
Verwijderd
Begin met C en ga verder naar C++ zou ik zeggen.
Maar ja... opinions are like assholes, everybody's got one. En als het op programmeren aankomt geldt dat extra sterk.
My 2 cts dus.
Ik heb zelf ook een tijd in c geprogrammeerd en mij is het wel opgevallen dat je veel langer bezig bent om fouten op te sporen tov java. Je leest heel makkelijk over een semantisch fout, syntactisch correct stukje code heen.
Daarnaast ben ik geinteresseerd in functionele programmeertalen en ben nu bezig met een type systeem te schrijven. En dan zie je allerlei tekortkomingen in allerlei talen. Zelf het typesysteem van java vind ik nu onnodig beperkt
Ik wil zelf gewoon zoveel mogelijk compile time uitdrukkingskracht tot mijn beschikking hebben. En soms moet je daarvoor wel eens 'omslachtig en streng zijn', maar ik denk dat je dit dubbel en dwars terug krijgt
1
2
3
4
| public int inc(int i){
if(i<10||i>20)foutmelding
return i++;
} |
Maar op deze manier krijg je geen compile time foutmelding als je inc(40) aanroept. Als je een krachtiger type systeem had dan zou je dit als volgt bv kunnen verhelpen:
1
2
3
| public void int([10..20] i){
return i++;
} |
Als je nu de volgende aanroept hebt: int(40) dan krijg je een foutmelding. Zoals je ziet kan je met een krachtiger typesysteem beter modeleren wat je bedoelt en daardoor hoef je minder checks uit te voeren, en daardoor wordt oa je code nog duidelijker.
Anyway, ik ben het volkomen met Alarmnummer eens.
Logica neemt een aparte plaats in in de wiskunde en staat los van de klassieke algebra. De boolse algebra die mietje aanhaalt is een electrotechnisch begrip, niet wiskundig. Wiskundigen hebben geen behoefte aan een dergelijk concept omdat de klassieke logica uitstekend voldoet.
Ik zal morgen eens kijken of ik het een en ander ook wiskundig hard kan maken, want dat lijkt het enige te zijn wat mietje kan overtuigen.
De logische operatoren als AND, OR, NOT zijn gewoon gedefineerd op de twee booleaanse waarden TRUE en FALSE. Dat er vervolgens allerlei interessante interpretaties worden gehangen aan logische operatoren op integers of integer operatoren op booleans is een bekend concept, dat heet operator overloading, erg geliefd bij electrotechnici en informatici, maar het heeft geen enkele wiskundige basis.
He who knows only his own side of the case knows little of that.
Verwijderd
Klopt, het kan per ongeluk misgaan, maar is dat een fout van de programmeur of van de taal? C is een taal die zeker niet bedoeld is voor beginnende programmeurs (dit bedoel ik niet persoonlijk), en iemand die "per ongeluk" met booleans rekent is voor mij niet bepaald ervaren. In C krijg je overigens voor dit soort impliciete downcasts optioneel een warning, die je ook nog eens per optie kunt veranderen in een error.Alarmnummer schreef op 06 augustus 2002 @ 22:30:
Ik ben inderdaad tegen downcast omdat ze namelijk ook per ongeluk kunnen gebeuren. In java bv moet je altijd expliciet converteren naar een boolean als die gevraagd wordt. Hierdoor zul je zelf goed na moeten denken over allerlei coersions ipv dit per ongeluk gebeurt.
Ik heb me een tijd lang bezig gehouden met FP, maar ik vind het (nog?) niet echt geschikt voor practische toepassingen, tenminste in runtime. FP in compile-time bewijst zijn nut in talen als C++ (dmv. templates).Daarnaast ben ik geinteresseerd in functionele programmeertalen en ben nu bezig met een type systeem te schrijven. En dan zie je allerlei tekortkomingen in allerlei talen. Zelf het typesysteem van java vind ik nu onnodig beperktMaarja.. zullen ze toendertijd ook wel een reden voor hebben gehad.
Mja, ik ontken niet dat een streng typesysteem voordelen heeft, maar het heeft ook nadelen. Wat jij als uitdrukkingskracht typeert, kan ook sterk tegen je werken. Als je bv. alle impliciete downcasts verbiedt, dan is dat "programmeurtje martelen" van het ergere soort: in een OO-taal moet een programmeur dan alle gesubclasste types expliciet downcasten naar het baseclass-type...Ik wil zelf gewoon zoveel mogelijk compile time uitdrukkingskracht tot mijn beschikking hebben. En soms moet je daarvoor wel eens 'omslachtig en streng zijn', maar ik denk dat je dit dubbel en dwars terug krijgt
Er bestaan overigens al verschillende talen die pre- en postcondities toelaten, en dat is wat jij in principe wilt met je type-systeem: precondities vastleggen. Het is de vraag of je voor elke mogelijke preconditie een apart type moet specificeren, of dat je een andere mogelijkheid bedenkt ze toe te laten zonder dat dat een programmeur kilometers code extra kost.
Verwijderd
Sorry Rick, maar de boolse algebra is werkelijk een volledige algebra in de verzamelingenleer. En in de verzamelingenleer zijn er massa's algebra's, de "klassieke" algebra is er daar maar een van. En voor al die algebra's bestaan er operatoren, dat heeft niets met "overloading" te maken.RickN schreef op 06 augustus 2002 @ 23:22:
Logica neemt een aparte plaats in in de wiskunde en staat los van de klassieke algebra. De boolse algebra die mietje aanhaalt is een electrotechnisch begrip, niet wiskundig. Wiskundigen hebben geen behoefte aan een dergelijk concept omdat de klassieke logica uitstekend voldoet.
Doe dat, ik heb de papers uit mijn studietijd nl. al voor meIk zal morgen eens kijken of ik het een en ander ook wiskundig hard kan maken, want dat lijkt het enige te zijn wat mietje kan overtuigen.
Verder werk ik zelf altijd met precondities, zodat ik weet dat iedere methode goeie argumenten krijgen. Maar je krijgt dan altijd zo`n kliederzooi in je methodes, en dat kan je hier voor veel van de gevallen goed oplossen.
En functioneel programmeren is trouwens iets anders dan templates. Wat jij bedoelt is geparametriseerde polymorphisme, en dat is veel krachtiger dan wat je kan met templates in c++.
En een beetje programmeurtje pesten is leuk om te doen
Verwijderd
Ik bedoel dus zoiets:
void doe_iets(char letter <[ 'a' .. 'z' ]>, int dag <[ 1 .. 7 ]>);
typedef int <[1 .. 12]> maand;
Hier staan hele leuke dingen in die je toch een heel ander perspectief op de huidige aanpak van types geven. Zo gauw nice echt bruikbaar gaat worden, ga ik er zeker mee spelen.
ps: wat heb je trouwens gestudeerd?
Verwijderd
Hehehe, nice, leukAlarmnummer schreef op 06 augustus 2002 @ 23:55:
En het voordeel aan deze aanpak is dus dat je veel problemen compile time op kan lossen, terwijl dit op dit moment runtime nog gedaan moet worden. Anders moet je deze maar eens doorkijken: Nice Safety in Nice Dit is een hele leuke taal die gewoon naar java byte code compileerd, zodat je het kan gebruiken op een normale vm.
C++ implementeert dit op een vergelijkbare wijze:
- collections:
std::stack<int, std::list<int> > my_stack;
definieert een typesafe stack van integers, die intern opgebouwd is uit een double-linked list. - multiple dispatch:
template <class T> bool equal(const T& a, const T& b) { return a == b; }
definieert een multiple dispatch equal functie met default implementatie. - null pointers:
Het gebruik van references, een reference is een impliciete pointer die nooit null kan zijn (tenzij je hem daar keihard toe forceert). Men garandeert dit door te eisen dat er geen ongeinitialiseerde references mogen voorkomen (en die initialisatie dus af te dwingen). Zie bv. die equal functie boven, a en b zijn twee references die gegarandeerd nooit null worden.
Eerst een jaartje astrofysica, maar ik ben helaas gestrand op QM. Daarna heb ik (theoretische) informatica gestudeerd.ps: wat heb je trouwens gestudeerd?
En als je nu inc(20) aanroept dan krijg je dus geen foutmelding terwijl het resultaat niet representeerbaar is in het domein [10..20] ?!Alarmnummer schreef op 06 augustus 2002 @ 22:47:
...code:
1 2 3 4public int inc(int i){ if(i<10||i>20)foutmelding return i++; }
Maar op deze manier krijg je geen compile time foutmelding als je inc(40) aanroept. Als je een krachtiger type systeem had dan zou je dit als volgt bv kunnen verhelpen:
code:
1 2 3public void int([10..20] i){ return i++; }
Als je nu de volgende aanroept hebt: int(40) dan krijg je een foutmelding.
Die inc die jij beschrijft is een operatie met type int[10..20]->int[11..21]. Nu kan de compiler dit nog wel checken, maar iha loop je het risico van halting probleem op statische pre/post conditie checks.
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Als je meer wilt weten over de geparameterizeerde typen in .NET en Java zijn deze twee linkjes misschien handig. Ik probeer hier de beste bronnen op dit gebied te verzamelen:
http://www.mbravenboer.org/dotnet_resources.xhtml
http://www.mbravenboer.org/java_resources.xhtml
Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment
Verwijderd
Klopt, "templating" is een ruimer begrip dan "geparametriseerde types"mbravenboer schreef op 07 augustus 2002 @ 11:31:
Alhoewel de overeenkomsten tussen templates en geparameterizeerde typen groot lijken, zijn er qua compilatie methode en mogelijkheden grote verschillen. De meeste generic Java proposals compileren namelijk niet door code-generatie voor elke instantie van een 'template' of geparameterizeerd type, maar via type erasure.
Een interessante ontwikkeling vind ik het beschouwen van geparametriseerde types (collections) als frist-class types. (Dit maakt het voor de programmeur eenvoudig om bv. een linked list naar een tree te casten.) Ik vind dit een tweesnijdend zwaard: het verhoogt de orthogonaliteit van de taal, maar ik vrees dat het tot zeer inefficiente code in de praktijk gaat leiden: zulke casts zijn veel duurder in rekentijd dan een gewone cast, terwijl dat op deze manier voor de programmeur niet duidelijk is.
RickN schreef op 06 augustus 2002 @ 23:22:
Als ik in D2k's noodkreet topic niet had gelezen dat er ergens een interessante discussie rondzwierf, anders had ik dit nooit gelezen.
kijk weer een tevreden klant
let maar niet op mij, dit is dus een van de topics met een beetje niveau erin
Doet iets met Cloud (MS/IBM)
Ik ben inderdaad vergeten het return type op te geven. Als het return type [11..21] is, dan zijn er geen problemen. Als het returntype [10..20] is, zul je bij invoer van 20 een foutmelding op moeten werpen. En verder loop je niet het risico op een een oneindige lus omdat je of een antwoord terug geeft in het juiste antwoord domein, of een foutmelding. Het is dus altijd beslisbaar.MSalters schreef op 07 augustus 2002 @ 07:51:
[...]
En als je nu inc(20) aanroept dan krijg je dus geen foutmelding terwijl het resultaat niet representeerbaar is in het domein [10..20] ?!
Die inc die jij beschrijft is een operatie met type int[10..20]->int[11..21]. Nu kan de compiler dit nog wel checken, maar iha loop je het risico van halting probleem op statische pre/post conditie checks.
Trouwen die [10..20] zijn niet zozeer precondities, maar het is een nieuwe type zoals byte, int en long dat ook zijn. Als je een formeel byte argument aan gaat roepen met een int argument dan zou je een foutmelding moeten krijgen. Hetzelfde geld voor:
[0..200] a = ...
int(a)
Dit geeft compile time al een foutmelding omdat het type van a geen subtype is van [10..20] (het is een supertype).
Generics in java worden compile time al opgelost en heb je runtime dus geen overhead van.Verwijderd schreef op 07 augustus 2002 @ 12:23:
[...]
zulke casts zijn veel duurder in rekentijd dan een gewone cast, terwijl dat op deze manier voor de programmeur niet duidelijk is.
En kan je in c++ wel een restrictie aanbrengen op typevariablen?
vb:
1
2
3
| public class PersoonList<P extends Persoon>{
...
} |
Je kunt nu alleen maar gaan parametriseren over subclasses van Persoon.
Verwijderd
Euhhh?Alarmnummer schreef op 07 augustus 2002 @ 13:49:
[...]
Generics in java worden compile time al opgelost en heb je runtime dus geen overhead van.
In C++ heb je verschillende opties zoals bv. traits, die de eigenschappen van een type beschrijven. Jouw voorbeeld:En kan je in c++ wel een restrictie aanbrengen op typevariablen?
class BasePersoon { ... };
typedef std::list<BasePersoon*> PersoonList;
Dit is trouwens behoorlijk XXX, het zou eleganter zijn die BasePersoon* te wrappen in een reference class.
Mijn fout. Ik had even te snel gelezen en bedoelde op runtime overhead door aanwezigheid van generics in java.Verwijderd schreef op 07 augustus 2002 @ 14:13:
Euhhh?kun je mij vertellen hoe je in compile-time een linked list naar een tree cast? Er zal toch echt een runtime component moeten zijn die die de elementen van de list naar de tree copieert (en hoeveel elementen er in zo'n collection zitten is meestal niet bekend in compile-time).
Verwijderd
Schrijf anders maar eens een functie in c, die de getallen [10.20] 1 kan verhogen, en bij de rest kan hij dat niet. Zo zou je het aan kunnen pakken:
code:
--------------------------------------------------------------------------------
public int inc(int i){
if(i<10||i>20)foutmelding
return i++;
}
Deze twee functies zijn verschillend van aard. Zo heeft de eerste een identiek domein en bereik, de tweede niet (nog afgezien van het feit dat jij onterecht een void een int[11..21] laat returnenpublic void int([10..20] i){
return i++;
}
Of je moet natuurlijk de operator ++ overloaden voor het type int[10..20], zodat deze altijd een resultaat oplevert in int[10..20]... (mogelijk natuurlijk, maar niet wenselijk om dat steeds te moeten doen voor al die verschillende subdomeinen van int die je wilt gebruiken)
Verder ben ik het NIET met mietje eens dat de + operator voor integers en booleans gelijk is (zeker niet wiskundig)
Een van de axioma's van de booleaanse algebra is
Dit is dus PERTINENT NIET WAAR voor integer-algebra!!! (maar een specifieke eigenschap van booleaanse algebra). Dat verschil zit 'em niet in het domein (een integer subdomein [0..1] geld deze regel namelijk ook niet voor) maar in de algebra zelf (in dit geval de defenitie van de + operator)Axiom #6: Distributive
* is distributive over + and + is distributive over *
a * (b + c) = (a * b) + (a * c), and
a + (b * c) = (a + b) * (a + c)
Verwijderd
Ja, maar niet op die (constraints through derivation) manier, en niet met behulp van een speciaal daarvoor bedoelde language feature.Alarmnummer schreef op 07 augustus 2002 @ 13:49:
En kan je in c++ wel een restrictie aanbrengen op typevariablen?
Bezwaren tegen 'constraints through derivation' staan beschreven in 15.4.1 van The Design and Evolution of C++.
De [url="http://boost.org/libs/concept_check/concept_check.htm"]Boost Concept Check Library[/url] biedt een framework voor het gebruik van concept checking classes. Door een template een concept checking class te laten gebruiken worden duidelijkere error messages gegenereerd wanneer een gegeven type het gewenste concept niet implementeerd, en worden constraints die anders extern gedocumenteerd zouden moeten worden overzichtelijk vastgelegd in de code (overigens is documentatie alsnog wenselijk
Ik zal ook al dat het return type misteVerwijderd schreef op 07 augustus 2002 @ 15:59:
Deze twee functies zijn verschillend van aard. Zo heeft de eerste een identiek domein en bereik, de tweede niet (nog afgezien van het feit dat jij onterecht een void een int[11..21] laat returnen)
int p = inc(20);
Ik zou persoonlijk kiezen voor de 2e aanpak omdat daar dus geen informatie verloren gaat en je kan het zonder problemen in een ruimer type plaatsen.
[0..100] p = inc(20); //dit kan je niet zeggen met de 1e aanpak.
Ik weet verder niet hoe handig dit is in de praktijk en het ligt er ook heel erg aan welk domein je zit. Maar ik merk wel dat ik wel enorm veel checks zou kunnen verwijderen als ik een krachtiger typesysteem tot mijn beschikking heb. Verder kan je er gewoon beter in kenbaar maken wat je wilt:
1
2
3
| public String toDag([0..6] dagIndex){
...
} |
Dit is erg duidelijk.
Nee, het return type kan geen [10..20] zijn. Wat jij beschrijft is (naast [11..21]) [11..20, foutmelding]. Dat is een andere set uitkomsten. Wat voor wiskundige resultaten wil je daar op loslaten?Alarmnummer schreef op 07 augustus 2002 @ 13:39:
[...]
Ik ben inderdaad vergeten het return type op te geven. Als het return type [11..21] is, dan zijn er geen problemen. Als het returntype [10..20] is, zul je bij invoer van 20 een foutmelding op moeten werpen. En verder loop je niet het risico op een een oneindige lus omdat je of een antwoord terug geeft in het juiste antwoord domein, of een foutmelding. Het is dus altijd beslisbaar.
(Ik denk dat we nu op lattices uitkomen - en dan laat ik het aan mbravenboer over denk ik)
Je mist het grote probleem van algebras op deze nieuwe types. Zoals al eerder opgemerkt heb je gewoon geen normale + op deze types, omdat het identiteitselement ontbreekt. ( Booleaanse algebra op [0..1] heeft die dus welTrouwen die [10..20] zijn niet zozeer precondities, maar het is een nieuwe type zoals byte, int en long dat ook zijn. Als je een formeel byte argument aan gaat roepen met een int argument dan zou je een foutmelding moeten krijgen. Hetzelfde geld voor:
[0..200] a = ...
int(a)
Dit geeft compile time al een foutmelding omdat het type van a geen subtype is van [10..20] (het is een supertype).
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Het return type is wel [10..20] (tenminste als je dat zo opgeeft) want een foutmelding is dus geen return waarde en dus geen element van een type. De functie wordt volledig afgebroken en zul je op hoger nivo weer moeten afvangen. Trouwens dit heeft niet meer zoveel te maken met wiskunde, maar dit is meer bedoelt voor in programmeertalen.MSalters schreef op 07 augustus 2002 @ 17:08:
[...]
Nee, het return type kan geen [10..20] zijn. Wat jij beschrijft is (naast [11..21])
[11..20, foutmelding]. Dat is een andere set uitkomsten. Wat voor wiskundige resultaten wil je daar op loslaten?
ps:
je kan dat afbreken dus vergelijken met het opgooien van een exception. Een exception is ook geen element van het return type, maar een andere manier om de methode te verlaten.
pps:
en je kan voor de subtypes exact dezelfde wiskundige regels erop loslaten als op int. Maar alleen in het geval dat de berekende waarde niet in dat type past, krijg je een foutmelding.
Mietje schreef al eerderAlarmnummer schreef op 07 augustus 2002 @ 17:13:
[...]
Het return type is wel [10..20] (tenminste als je dat zo opgeeft) want een foutmelding is dus geen return waarde en dus geen element van een type. De functie wordt volledig afgebroken en zul je op hoger nivo weer moeten afvangen. Trouwens dit heeft niet meer zoveel te maken met wiskunde, maar dit is meer bedoelt voor in programmeertalen.
ps:
je kan dat afbreken dus vergelijken met het opgooien van een exception. Een exception is ook geen element van het return type, maar een andere manier om de methode te verlaten.
pps:
en je kan voor de subtypes exact dezelfde wiskundige regels erop loslaten als op int. Maar alleen in het geval dat de berekende waarde niet in dat type past, krijg je een foutmelding.
En dat geldt dus nog steeds. We waren bezig om algebra's te vergelijken, in het bijzonder die modulo MAX_INT, die modulo 2 en Booleaanse algebra. Die [10..20] is een moeilijk geval omdat je geen normale algebraische operator+ kunt definieren met een identiteits element. Sowieso worden identiteits elementen een probleem als je resultaat verzameling niet dezelfde is als je bron verzameling.Nee, ons probleem is dat ik algebraisch argumenteer, terwijl jij informatie-technisch argumenteert.
Een algebra heeft ook geen exceptions, anders dan als "bijzondere" resultaten. Zelfs als we dat negeren zit 10 nog niet in de resultaat set.
Wat pps betreft, je geeft daar een beschrijving van de 'functie' in termen van een mapping naar int gevolgd door een normale operatie in N en vervolgens een mapping van int naar de set [11..20, exception]. Dat hadden we wel zo'n beetje begrepen. Volgens mij mis je de essentie van de verschillen tussen + in algebra's met en zonder identiteits element. Daarmee samenhangend mis je dan ook (nog steeds volgens mij) de verschillen tussen een + waarvan de argumenten en het resultaat uit dezelfde verzamling komen, en jouw voorbeelden waar dat niet het geval is.
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Ik zou eerlijk gezegd niet weten wat daaraan informatie technisch verschillend aan is . Ik hoop dat je me dat even kan uitleggen zodat ik begrijp wat ik schijnbaar niet zie.Dat hadden we wel zo'n beetje begrepen. Volgens mij mis je de essentie van de verschillen tussen + in algebra's met en zonder identiteits element.
Informatie technisch zie ik geen enkel probleem. Maar als dit wel zo is, zou je me dan kunnen uitleggen wat ik dan over het hoofd zie?Daarmee samenhangend mis je dan ook (nog steeds volgens mij) de verschillen tussen een + waarvan de argumenten en het resultaat uit dezelfde verzamling komen, en jouw voorbeelden waar dat niet het geval is.
Verwijderd
Ik neem het weer overAlarmnummer schreef op 07 augustus 2002 @ 23:52:
Ik zou eerlijk gezegd niet weten wat daaraan informatie technisch verschillend aan is . Ik hoop dat je me dat even kan uitleggen zodat ik begrijp wat ik schijnbaar niet zie.
Je kunt informatietechnisch heel goed stellen dat je "twee integers optelt waarvan het resultaat in het interval 10 .. 20 moet liggen", maar dan is dat algebraisch geen + operator, mede omdat je een verzameling getallen definieert door het herhaald optellen van het eenheidselement, en dat eenheidselement zich niet in het bereik van die optel-operator bevindt...
Het is gewoon een definitiekwestie, algebraisch mag je niet zomaar elke functie een operator noemen. Een algebraische operator is als volgt gedefinieerd:Informatie technisch zie ik geen enkel probleem. Maar als dit wel zo is, zou je me dan kunnen uitleggen wat ik dan over het hoofd zie?
Voor ons is nu alleen f: An -> A; belangrijk, want daarin zie je duidelijk dat het een afbeelding is van een aantal argumenten uit verzameling A naar opnieuw verzameling A.Een n-aire operatie over een verzameling A is een functie
f: An -> A;
n is het aantal argumenten van f (n >= 0)
n n-air
0 nullair
1 unair
2 binair
3 ternair
Een nullaire operatie f: A0 -> A wordt geheel bepaald door het element f = f( ) = f( < > ) van A;
een nullaire operatie heet ook een constante.
[ Voor 0% gewijzigd door Verwijderd op 08-08-2002 02:58 . Reden: typo in quote (papier is primitief, cut&paste werkt niet) ]
Verwijderd
Verwijderd
Ben ik niet met je eens. Een optelling waarvan het resultaat in [10..20] moet liggen is wel degelijk algebraisch gezien een optelling, er worden hier alleen restricties aan het bereik gesteld (en dus impliciet restricties dat het domein van de functie). De 'gewone' + operator definieren voor de ruimte [10..20] is denk ik wel een probleem, aangezien de afbeeldingsverzameling niet gelijk is aan de bronverzameling (en het dus volgens jouw defenitie uberhaupt geen operator genoemd kan worden)Je kunt informatietechnisch heel goed stellen dat je "twee integers optelt waarvan het resultaat in het interval 10 .. 20 moet liggen", maar dan is dat algebraisch geen + operator, mede omdat je een verzameling getallen definieert door het herhaald optellen van het eenheidselement, en dat eenheidselement zich niet in het bereik van die optel-operator bevindt...
Dat je een verzameling getallen definieert door het herhaald optellen van het eenheidselement is natuurlijk onzin : {2,5,14} is ook een verzameling getallen, heet wat jij hier bedoelt niet een volledige verzameling?
Verwijderd
inc is dus in ieder geval geen operator, want deze beeld de verzameling [10..20] af naar [11..21]. Ook is de 'gewone algebra' plus hier geen operator, wantMet die definitie zou je dus de '+' wel degelijk als algebraische operator kunnen zien. In jouw definitie is geen definitie gegeven voor de verzamelingen An en A, waardoor je daarmee niet de inc functie over {10,20} elimineert.
x in [10..20]
y in [10..20]
x + y niet in [20..40]
Je zou hiervoor dus een equivalent van de 'booleaanse algebra' moeten verzinnen waardoor je toch de + operator houdt, maar ik weet niet of dat mogelijk is...
Verwijderd
Verwijderd