[M3devel] [M3commit] CVS Update: cm3

Mika Nystrom mika at async.async.caltech.edu
Tue Jul 6 08:34:58 CEST 2010


Jay, I agree with the general premise that splitting declaration and
initialization is bad coding style.  I use WITH or the initialization
of a procedure entry as much as possible to declare my variables.
And if they have to change during the course of their lifetime,
I do try to initialize them in the VAR.

But... you're wrong :-)

Imagine you have a variable whose initial value (i.e., the value it has
before the first time it is used) is critical for the correctness of
your algorithm.  The initial value depends on something else, something
that has to be computed.  In this case, which does happen, at least
in my code, there is no static value that is better than any other.
VAR x : INTEGER; BEGIN is the right way to code that.  VAR x := 0; BEGIN
accomplishes exactly one thing: it obfuscates the code---it misleads the
reader into thinking that x=0 is somehow relevant to the code, without
adding anything at all to its correctness.  As I said, the declaration
that isn't initialized is to be used *sparingly* and whenever it is
used it should be a giant red flag to the reader that the variable x is
going to be initialized with a value that the programmer doesn't know
at the time of declaration.  What on earth do you gain from x := 0?
A "little correctness"? 

     Mika

Jay K writes:
>
>Programmers are notorious for making mistakes.
>
>
>When you write VAR a:INTEGER=3B
>you make the human proofreading your code have to work much harder
>to do the data/control flow analysis to make sure you didn't
>use the uninitialized value.
>
>
>Using the a :=3D 0 value might still be "wrong"=2C but is it at least consi=
>stent
>and the penalty for getting it wrong is generally less severe.
>
>Now=2C I don't want there to be a bug either way=2C but I feel that a consi=
>stent 0 is much "safer"
>than uninitialized. Either is typesafe=2C sure=2C but type safe is just the=
> bare minimum expectation
>for my code. It must not only be type safe=2C but act correctly.
>
>Again=2C compiler isn't generally a program proofer=2C but the little it ca=
>n do=2C let it do.
>
>
>
>Here is how I write C code:
>
>void function_with_two_temporary_buffers()
>{
>=A0 void* p =3D { 0 }=3B
>=A0 void* q =3D { 0 }=3B
>
>=A0 if (!(p =3D malloc(...)))
>=A0=A0=A0 goto exit=3B
>
>=A0 if (!(q =3D malloc(...)))
>
>=A0=A0=A0 goto exit=3B
>
>
>
>...
>
>exit:
>=A0=A0 free(p)=3B
>=A0=A0 free(q)=3B
>}
>
>or
>void function_that_returns_two_buffers(void** a=2C void** b)
>{
>=A0 void* p =3D { 0 }=3B
>=A0 void* q =3D { 0 }=3B
>=A0=20
>=A0 *a =3D p=3B
>=A0 *b =3D q=3B
>
>=A0 if (!(p =3D malloc(...))
>=A0=A0 goto Exit=3B
>
>=A0 if (!(q =3D malloc(...))
>
>=A0=A0 goto Exit=3B
>
>
>
>=A0=A0=A0 ....
>=A0 *a =3D p=3B
>=A0=A0 p =3D 0=3B
>=A0=A0 *b =3D q=3B
>=A0=A0 q =3D 0=3B
>
>Exit:=20
>=A0 free(p)=3B
>=A0 free(q)=3B
>
>}
>
>In reality malloc is generally a function that returns an integer=2C negati=
>ve for success.
>So it is more like:
>#define CHECK(expr) do { if ((status =3D (expr)) < 0) goto Exit=3B } while(=
>0)
>
>
>=A0 CHECK(MemoryAlloc(...=2C &q))=3B
>
>See=2C the style is written to be easy for a human to verify the correctnes=
>s of.
>Locals are always initialized. Ownership of resources is always clear.
>
>This is contrast with other styles:
>
>=A0if (p =3D malloc(...))
>=A0 {
>=A0=A0=A0=A0=A0 ...
>=A0=A0=A0=A0 if (q =3D malloc(...))
>=A0=A0=A0 {
>=A0=A0=A0=A0=A0=A0=A0=A0 ...
>=A0=A0=A0=A0=A0=A0=A0 free(q)=3B
>=A0=A0=A0 }
>=A0=A0 free(p)=3B
>}
>
>where one has to follow the ever further indented blob of ifs.
>It doesn't scale. Every resource allocation makes the code incrementally ha=
>rder for a human to read.
>Whereas the style that includes initializing all locals has no such increme=
>ntal cost.
>
>(And this hard to read style is in fact somewhat encouraged by the "with" f=
>eature of Modula-3.
>C++'s equivalent -- declaring variables anywhere -- doesn't suggest ever in=
>creasing indentation.
>)
>
>
>=A0- Jay
>
>
>
>----------------------------------------
>> To: jay.krell at cornell.edu
>> Date: Mon=2C 5 Jul 2010 22:58:33 -0700
>> From: mika at async.async.caltech.edu
>> CC: m3devel at elegosoft.com
>> Subject: Re: [M3devel] [M3commit] CVS Update: cm3
>>
>>
>> As I've said before=2C
>>
>> When I write:
>>
>> VAR
>> a : INTEGER=3B
>> BEGIN
>>
>> ...
>>
>> .... a :=3D .. ...
>>
>> ...
>>
>> END
>>
>> that means I am putting you=2C the reader=2C on notice that I have no
>> particularly meaningful idea of what a's initial value is.
>>
>> If I were to write
>>
>> VAR
>> a :=3D 0=3B
>> BEGIN
>> ...
>> END
>>
>> I would mislead you into thinking that 0 is a somehow important
>> initial value. Which it's not. It's just garbage=2C and it better
>> not show up in the computation!
>>
>> Programs are mainly meant to be read by humans=2C not computers.
>>
>> Mika
>>
>>
>> Jay K writes:
>> >--_d2468f3b-9666-4291-98b5-5414421f54d9_
>> >Content-Type: text/plain=3B charset=3D"iso-8859-1"
>> >Content-Transfer-Encoding: quoted-printable
>> >
>> >
>> >We are going in circles.
> 		 	   		  =



More information about the M3devel mailing list