Discussion:
Optimization question
(too old to reply)
Xcriber51
2007-11-02 13:01:52 UTC
Permalink
Hi

A very minor detail.

If I used a for loop as below, referring to a string 's' (whose length
doesn't change in the routine),...

FOR i := 0 TO LEN(s$)-1 DO...

..does BlackBox optimize the expression "LEN(s$)-1" so that it doesn't
recalculate it at every iteration, or do we have to eliminate that
manually thus...

len := LEN(s$)-1;
FOR i := 0 TO len DO ...

?

Thanks!


-- Ken

--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
Stefano Ferrari
2007-11-02 13:38:18 UTC
Permalink
Post by Xcriber51
Hi
A very minor detail.
If I used a for loop as below, referring to a string 's' (whose length
doesn't change in the routine),...
FOR i := 0 TO LEN(s$)-1 DO...
..does BlackBox optimize the expression "LEN(s$)-1" so that it doesn't
recalculate it at every iteration, or do we have to eliminate that
manually thus...
len := LEN(s$)-1;
FOR i := 0 TO len DO ...
?
Thanks!
-- Ken
--
Message posted usinghttp://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information athttp://www.talkaboutprogramming.com/faq.html
I don't think it can optimize; s is not invariant in the FOR loop

Regards
Xcriber51
2007-11-02 20:14:23 UTC
Permalink
Can't exactly follow what you mean by that, Stefano, but I've tried my
"poor man's" method:

PROCEDURE ForOptimize*(s: ARRAY OF CHAR);
VAR i, j, len: INTEGER;
t1, t2: LONGINT;
ch: CHAR;
BEGIN
t1 := Services.Ticks();
FOR i := 0 TO 0FFFFH DO
FOR j := 0 TO LEN(s$)-1 DO ch := s[j] END
END ;
t2 := Services.Ticks();

StdLog.IntForm(t2-t1,10,5,' ',FALSE); StdLog.Ln;

t1 := Services.Ticks();
FOR i := 0 TO 0FFFFH DO
len := LEN(s$)-1;
FOR j := 0 TO len DO ch := s[j] END
END ;
t2 := Services.Ticks();

StdLog.IntForm(t2-t1,10,5,' ',FALSE); StdLog.Ln;

END ForOptimize;

Calling this with a 75-character string yielded "31" for both loops.

I know this is unmathematical and inelegant, but it's good enough for me.

The reason I've asked this is, due to my C habits I've recently run into a
problem that took an inordinate amount of time to spot -- probably because
it just wasn't obvious to me. Oberon does away with Pascal-like array
indexing (i.e. defining array indeces to start and end in any number you
like, a feature which, although superficially nice, probably wasn't worth
the effort in light of what it bought) so arrays are 0-based by default.
It also adds a C-like feature to strings terminating them with a null
character used as a sentinel -- again, probably because it is easier to
deal with. But there's one thing that escaped me.

The gotcha I mentioned a while ago was this: when we (those used to using
C) iterate over a string in C using an index, we naturally code it as
this:

for (i = 0; i<strlen(s); i++) ... etc.

You can replace the "strlen" call with a precalculated value, that is not
important. The important thing is, the predicate for the loop's
continuation says "while the index is smaller than the length of the
string." When you do this with Oberon like so...

FOR i := 0 TO LEN(s$) DO ... etc.

..you forget that "TO" means the length of the string will be used as the
last index value which doesn't exist as part of the string but is used for
the sentinel null character. So you have to remember to do this:

FOR i := 0 TO LEN(s$)-1 DO ... etc.

You may say this is a non-issue, but it's one of those typical tiny things
that gets on your nerves since it is so hidden-in-plain-sight that it runs
you up the wall.

With C's "for," you define how you continue the loop, which can be (and
frequently is) used to define the termination condition based on an index.
But then, with pointers, C is internally tuned to the null character so you
can write the above loop as:

for (; *s; s++){ ... } etc.

-or- with a while loop as...

while (*s) {
... etc.
s++;
}

..and you don't have to remember to refer to the length of the string and
subtract one from it not to go off the end. C will do it for you, and
terminate the loop by using that null character. This was what confused
me. (i.e. My mind is used to treating the sentinel as a convenient way to
avoid having to calculate a length value.)

Maybe with a while loop I wouldn't fall into this trap, such as:

i := 0;
WHILE i < LEN(s$) DO
...

INC(i)
END ;

..but not only does this require remembering to put that incrementation
at the bottom, in either case you feel the length is being recalculated so
you're tempted to create a "len" variable and calculate it beforehand. But
then, the little detail to remember is reversed in the loops:

len := LEN(s$)-1; (*exclude the last character from the
length*)

FOR i := 0 TO len DO... (*now you can include it in the loop index*)

i := 0;
WHILE i <= len DO... (*here, however, we have to say "<=" in the
predicate*)

Anyway, for those of you who are Oberon experts, these mundane things must
be well beneath your daily concern. I posted this following Chris's advice
so that other newbies can avoid this kinda frustration.


-- Ken


--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
Xcriber51
2007-11-03 08:55:25 UTC
Permalink
Heck, here's how to do this without calculating the length -- this was,
again, hidden in plain sight. Just refer to the sentinel to check the
current item of the loop (as in C):

i := 0;
WHILE (s[i] # 0X) DO
...
INC(i)
END

That's it!


-- Ken


--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
L
2008-10-26 00:12:47 UTC
Permalink
Post by Xcriber51
Heck, here's how to do this without calculating the length -- this was,
again, hidden in plain sight. Just refer to the sentinel to check the
i := 0;
WHILE (s[i] # 0X) DO
...
INC(i)
END
That's it!
-- Ken
This code does not clearly describe what you are doing, and looks like
clever tricks and hard to decipher code IMO. Programmers should not
write code that looks clever.. if the language is forcing one to do that
then.. well the language is too simple.

In delphi one is at least able to write something elegant:

for i:= 1 to length(s) do ..
...

As the null character is ignored and is not part of the string in
delphi. A string is treated slightly different than an array.

Myself, I am deciding whether Oberon is too "annoying" to use by
learning from these newsgroups and other places. So far, it does not
look good. "Simpler, but no simpler" my ass.
L
2008-10-26 00:32:50 UTC
Permalink
Post by L
Post by Xcriber51
Heck, here's how to do this without calculating the length -- this was,
again, hidden in plain sight. Just refer to the sentinel to check the
i := 0;
WHILE (s[i] # 0X) DO ... INC(i)
END
That's it!
-- Ken
This code does not clearly describe what you are doing, and looks like
clever tricks and hard to decipher code IMO. Programmers should not
write code that looks clever.. if the language is forcing one to do that
then.. well the language is too simple.
for i:= 1 to length(s) do ..
...
To add to my comments above:

By the way, Dijkstra always talked about how great counting from zero
was. I disagree with Dijkstra strongly on the counting from zero issue,
even though I agree with most of his other philosophies.

Counting from zero causes numerous bugs in software, such as the above
problem that people are spending paragraphs and paragraphs on. Counting
from zero helps some other issues in programming - but on the other hand
it creates never ending confusions for programmers in other places! Is
counting at zero worth it? No it is not.

If I have zero apples in the fruit bowl.. does this mean that I actually
have one apple in the fruit bowl, or zero? Let us please leave zero to
be what it is: zero. Let us not start pretending that zero is now one,
and that one is now two, and that the number 9 is actually 25. And what
pray tell is -1 ? -1 must be zero! Yes that makes everything clearer. Sure!

This "counting at zero" fad is the most ridiculous confusion causing
idiocy known to man (despite the advantages of counting at zero, trust
me I have thought it out long and hard).

If I have one character in a string, I expect it to be at position one.
How obvious is that. How sensible and logical is that. If I have zero
characters in a string, I do not expect to start deciphering whether
zero means 1, or zero means zero! Complete idiocy.
August Karlstrom
2008-10-26 14:06:02 UTC
Permalink
Post by L
By the way, Dijkstra always talked about how great counting from zero
was. I disagree with Dijkstra strongly on the counting from zero issue,
even though I agree with most of his other philosophies.
Counting from zero causes numerous bugs in software, such as the above
problem that people are spending paragraphs and paragraphs on. Counting
from zero helps some other issues in programming - but on the other hand
it creates never ending confusions for programmers in other places! Is
counting at zero worth it? No it is not.
If I have zero apples in the fruit bowl.. does this mean that I actually
have one apple in the fruit bowl, or zero?
Counting from zero makes sense when we are dealing with positions or
distances from origo if you like. We say things like "the first element
is at position zero." Apples in a fruit bowl do not represent positions.


August

Chris Burrows
2008-10-25 23:44:42 UTC
Permalink
Post by L
Post by Xcriber51
Heck, here's how to do this without calculating the length -- this was,
again, hidden in plain sight. Just refer to the sentinel to check the
i := 0;
WHILE (s[i] # 0X) DO ... INC(i)
END
That's it!
-- Ken
This code does not clearly describe what you are doing, and looks like
clever tricks and hard to decipher code IMO. Programmers should not write
code that looks clever.. if the language is forcing one to do that then..
well the language is too simple.
This code describes EXACTLY what you are doing - counting characters until a
zero character is encountered. However, most Oberon implementations would
provide a Strings library which includes a Length function to hide the
details from you if that is what you prefer.
Post by L
for i:= 1 to length(s) do ..
...
I question the use of 'Delphi' and 'elegant' in the same sentence. Delphi's
(mis)handling of strings is a particularly good example.

<quote>
Strings are a bit of a mystery to most Delphi developers. The fact that new
features are added in almost every new release probably does not help the
situation. For example, few developers know the difference between string,
ShortStrings, long strings, AnsiStrings, WideStrings, openstrings etc..
</quote>

http://www.codexterity.com/delphistrings.htm

However, that is not the whole story. Now with Delphi 2009's support for
Unicode strings the complexity has increased by another order of magnitude
...

However, I believe that no one tool is suitable for every job. I currently
use Delphi, Component Pascal, Oberon and C# - each has their strengths and
weaknesses - you just need to know what they are and choose appropriately.
Hence, for example, I wouldn't dream of using Delphi for embedded
development on an ARM system - give me a language where I can see exactly
what is going on behind the scenes.

--
Chris Burrows
Armaide: Oberon-07 for ARM Development System
http://www.armaide.com
August Karlstrom
2008-10-26 13:40:47 UTC
Permalink
Post by L
Post by Xcriber51
i := 0;
WHILE (s[i] # 0X) DO ... INC(i)
END
That's it!
This code does not clearly describe what you are doing, and looks like
clever tricks and hard to decipher code IMO. Programmers should not
write code that looks clever.. if the language is forcing one to do that
then.. well the language is too simple.
It is not a clever trick, it is an programming idiom. In this case it is
an idiom that is also known to every C programmer. Each programming
language has its idioms.
Post by L
for i:= 1 to length(s) do ..
...
As the null character is ignored and is not part of the string in
delphi. A string is treated slightly different than an array.
But that probably also means that costly string operations are taking
place behind the scenes.
Post by L
Myself, I am deciding whether Oberon is too "annoying" to use by
learning from these newsgroups and other places. So far, it does not
look good. "Simpler, but no simpler" my ass.
I view Oberon as a "sufficiently" high level language comparable with
(but superior to) C and C++.


August
Chris Burrows
2007-11-02 23:22:33 UTC
Permalink
Post by Xcriber51
Hi
A very minor detail.
If I used a for loop as below, referring to a string 's' (whose length
doesn't change in the routine),...
FOR i := 0 TO LEN(s$)-1 DO...
..does BlackBox optimize the expression "LEN(s$)-1" so that it doesn't
recalculate it at every iteration, or do we have to eliminate that
manually thus...
len := LEN(s$)-1;
FOR i := 0 TO len DO ...
I haven't inspected the code generated or checked the compiler source but if
BlackBox was not optimizing the for loop then it would not be in conformance
with the Component Pascal Language report. The definition of a FOR loop in
Section 9.8 of the report is:

==============================
FOR v := beg TO end BY step DO statements END

is equivalent to

temp := end; v := beg;
IF step > 0 THEN
WHILE v <= temp DO statements; INC(v, step) END
ELSE
WHILE v >= temp DO statements; INC(v, step) END
END

==============================

i.e. the end value is only evaluated once before the loop starts.

--
Chris Burrows
CFB Software
http://www.cfbsoftware.com/gpcp
Loading...