From: Robert A Duff on
"Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:

> On Sun, 08 Jun 2008 17:19:11 -0400, Robert A Duff wrote:
>
>> Maciej Sobczak <see.my.homepage(a)gmail.com> writes:
>>
>>> After all, with the possibility to initialize the new variable with
>>> arbitrarily complex expression (including function call), this is
>>> already the case and the whole declare-begin-end block is just
>>> reflecting some artificial separation.
>>
>> I agree. I suppose it comes from Pascal, where declarations and
>> executable code are completely separated. It makes no sense in
>> Ada, where declarations are just as executable as statements.
>
> I disagree. I think it does make sense because it clearly defines the scope
> of the declared variable. Expression (result) /= named object. And
> reversely, if you don't need the variable, you are free to put expressions
> anywhere outside the declaration part.

If Ada allowed:

for I in A'Range loop
X : constant Character := F(A(I)); -- Not Ada!
Do_Something(X);
end loop;

the scope of X is clear -- it's the entire loop body.

for I in A'Range loop
declare
X : constant Character := F(A(I));
begin
Do_Something(X);
end;
end loop;

does not clarify (in my opinion). It just adds noise.

You could still say:

for I in A'Range loop
begin
X : constant Character := F(A(I)); -- Not Ada!
Do_Something(X);
end;
Do_Something_Else;
end loop;

in my circus, if you want to further limit the scope of X
(to smaller than the whole loop body).

- Bob
From: Robert A Duff on
Georg Bauhaus <rm.dash-bauhaus(a)futureapps.de> writes:

> Robert A Duff schrieb:
>> Maciej Sobczak <see.my.homepage(a)gmail.com> writes:
>>
>>> You did not state it explicitly, but I presume that you allow mixing
>>> declarations with executable code ("as in Java and other languages")?
>> Yes, if I ran the circus, I would allow that. I really find it
>> annoying
>> that I have to add 3 useless lines of code (declare/begin/end) and an
>> extra level of indentation, when all I wanted to do was declare
>> a very-local object.
>
> I find it annoying when I have to search other people's
> procedures for variables. A typical sequence of statements is
> sprinkled with declarations (Java, C, Perl, ...) and no oher
> indication of the newly introduced variables other than
> two identifiers before "=" or ";".

I suppose it's a matter of taste, at least in part.

But the situation in C-style languages is different -- declarations
don't stand out very well. In Ada, the declaration syntax is clear
enough without adding "declare/begin/end".

Besides, even with "declare/begin/end", you still have to search all
over the place to find declarations -- they can be in various packages,
and in any outer block, procedure, etc.

> As Dmitry says, there is an *implicit* scope only.
> When I'm up the wall I speculate whether this viewpoint on language
> use is driven by a desire to achieve income by obfuscation?
> The tempting quick hack?

Not at all. IMHO, "declare/begin/end" obfuscates, by pretending that
the stuff between declare and begin is just declarations, no executable
code.

> To me, ad hoc variables between statements and Java classes fully
> named in source but without "import" at the head of the source file
> are similar in character.

They seem completely different, to me. I agree with you that importing
without saying so up front is not good.

> The good news is: computers can help us with getting the
> necessary "paper work" (declare block etc.) done; use a
> good editor.

Sure, I do use a good editor. That's not the point -- I'm not
complaining about how much work it is to type in "declare/begin/end" --
I'm complaining about how much work it is to _read_ that extra clutter.
The blocks of code we're talking about are often just 2 or 3 lines
of code, so adding several nested declare blocks can easily double
the size of the procedure.

- Bob
From: Robert A Duff on
Britt Snodgrass <britt.snodgrass(a)gmail.com> writes:

> I very much agree. The requirement for an explicit declaritive region
> is a very good thing for reasons of readability and maintainability.
> If variables could be declared anywhere in a procedure then it really
> would be a circus.

But you have not explained why you think declare blocks aid readability
and maintainability. I don't think they do. Is it just a matter of
taste, or a matter of what one is used to?

- Bob
From: Dmitry A. Kazakov on
On Sun, 15 Jun 2008 15:38:08 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:
>
>> On Sun, 08 Jun 2008 17:19:11 -0400, Robert A Duff wrote:
>>
>>> I agree. I suppose it comes from Pascal, where declarations and
>>> executable code are completely separated. It makes no sense in
>>> Ada, where declarations are just as executable as statements.
>>
>> I disagree. I think it does make sense because it clearly defines the scope
>> of the declared variable. Expression (result) /= named object. And
>> reversely, if you don't need the variable, you are free to put expressions
>> anywhere outside the declaration part.
>
> If Ada allowed:
>
> for I in A'Range loop
> X : constant Character := F(A(I)); -- Not Ada!
> Do_Something(X);
> end loop;
>
> the scope of X is clear -- it's the entire loop body.

No, then it should better be something like:

for I in A'Range;
X : constant Character := F(A(I)); -- Not Ada!
loop
Do_Something(X);
end loop;

The declarative part of a loop is between "for" and "loop."

However I find nested declare/begin/end more readable because it clearly
disambiguates between the scope of the loop and the scope of one iteration
of.

> You could still say:
>
> for I in A'Range loop
> begin
> X : constant Character := F(A(I)); -- Not Ada!
> Do_Something(X);
> end;
> Do_Something_Else;
> end loop;

But what would happen if I said:

begin
raise Foo_Error;
X : constant Character := F(A(I)); -- Not Ada!
Do_Something (X);
exception
when Foo_Error =>
Do_Something_Interesting (X);
end;

---------------
What I miss is things like:

procedure Foo (X : T'Class) is
begin
case X is
when S_X : S'Class =>
Do_S_Method (S_X);
when others =>
Do_Something_Else;
end case;
end Foo;

procedure Bar (Ptr : access T'Class) is
begin
case Ptr is
when Ref : not null access T =>
Ref.Foo; -- No more checks
when others =>
null;
end case;
end Bar;

case I is
when Checked_I : A'Range =>
... A (Checked_I) ... -- No range checks
...
end case;

case L - 123 is
when Sum : Positive =>
-- Sum = L - 123 and it is positive
...
when Sum : Integer =>
-- Sum = L - 123 and it is not positive
...
when others =>
-- It would overflow, but no exception was propagated
...
end case;

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Robert A Duff on
"Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:

> On Sun, 15 Jun 2008 15:38:08 -0400, Robert A Duff wrote:
>
>> "Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:
>>
>>> On Sun, 08 Jun 2008 17:19:11 -0400, Robert A Duff wrote:
>>>
>>>> I agree. I suppose it comes from Pascal, where declarations and
>>>> executable code are completely separated. It makes no sense in
>>>> Ada, where declarations are just as executable as statements.
>>>
>>> I disagree. I think it does make sense because it clearly defines the scope
>>> of the declared variable. Expression (result) /= named object. And
>>> reversely, if you don't need the variable, you are free to put expressions
>>> anywhere outside the declaration part.
>>
>> If Ada allowed:
>>
>> for I in A'Range loop
>> X : constant Character := F(A(I)); -- Not Ada!
>> Do_Something(X);
>> end loop;
>>
>> the scope of X is clear -- it's the entire loop body.
>
> No, then it should better be something like:
>
> for I in A'Range;
> X : constant Character := F(A(I)); -- Not Ada!
> loop
> Do_Something(X);
> end loop;
>
> The declarative part of a loop is between "for" and "loop."

I don't see why a loop needs a declarative part.
My idea is that every statement list is a scope.

> However I find nested declare/begin/end more readable because it clearly
> disambiguates between the scope of the loop and the scope of one iteration
> of.

I don't get it. You declare something inside a loop body, or the 'then'
part of an 'if' -- it's local to that.

>> You could still say:
>>
>> for I in A'Range loop
>> begin
>> X : constant Character := F(A(I)); -- Not Ada!
>> Do_Something(X);
>> end;
>> Do_Something_Else;
>> end loop;
>
> But what would happen if I said:
>
> begin
> raise Foo_Error;
> X : constant Character := F(A(I)); -- Not Ada!
> Do_Something (X);
> exception
> when Foo_Error =>
> Do_Something_Interesting (X);
> end;

As I said earlier, exception-handler regions deserve their own syntax,
not connected with declaration blocks.

> ---------------
> What I miss is things like:

Not sure how these are related to local decls...

> procedure Foo (X : T'Class) is
> begin
> case X is
> when S_X : S'Class =>
> Do_S_Method (S_X);
> when others =>
> Do_Something_Else;
> end case;
> end Foo;
>
> procedure Bar (Ptr : access T'Class) is
> begin
> case Ptr is
> when Ref : not null access T =>
> Ref.Foo; -- No more checks
> when others =>
> null;
> end case;
> end Bar;
>
> case I is
> when Checked_I : A'Range =>
> ... A (Checked_I) ... -- No range checks
> ...
> end case;
>
> case L - 123 is
> when Sum : Positive =>
> -- Sum = L - 123 and it is positive
> ...
> when Sum : Integer =>
> -- Sum = L - 123 and it is not positive
> ...
> when others =>
> -- It would overflow, but no exception was propagated
> ...
> end case;

- Bob