From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=BAYES_00,INVALID_MSGID, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fac41,9a0ff0bffdf63657 X-Google-Attributes: gidfac41,public X-Google-Thread: 1108a1,9a0ff0bffdf63657 X-Google-Attributes: gid1108a1,public X-Google-Thread: f43e6,9a0ff0bffdf63657 X-Google-Attributes: gidf43e6,public X-Google-Thread: 103376,4b06f8f15f01a568 X-Google-Attributes: gid103376,public From: John Volan Subject: Re: Software landmines (loops) Date: 1998/09/01 Message-ID: <35ECBA42.5931F9B2@ac3i.dseg.ti.com>#1/1 X-Deja-AN: 387003614 Content-Transfer-Encoding: 7bit References: <902934874.2099.0.nnrp-10.c246a717@news.demon.co.uk> <6r1glm$bvh$1@nnrp1.dejanews.com> <6r9f8h$jtm$1@nnrp1.dejanews.com> <6renh8$ga7$1@nnrp1.dejanews.com> <6rf59b$2ud$1@nnrp1.dejanews.com> <6rfra4$rul$1@nnrp1.dejanews.com> <35DBDD24.D003404D@calfp.co.uk> <6sbuod$fra$1@hirame.wwa.com> <35f51e53.48044143@ <904556531.666222@miso.it.uq.edu.au> <35EAEC47.164424A7@s054.aone.net.au> <35EBBFAF.DE38C061@s054.aone.net.au> <35EC28BD.351F33DF@s054.aone.net.au> Content-Type: text/plain; charset=us-ascii Organization: Raytheon Systems Company, Advanced C3I Systems Mime-Version: 1.0 Reply-To: johnvolan@sprintmail.com Newsgroups: comp.lang.eiffel,comp.object,comp.software-eng,comp.lang.ada Date: 1998-09-01T00:00:00+00:00 List-Id: [Woops! Sorry for the re-post folks, want to fix some egregious typos:] Loryn Jenkins wrote: > > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > from > Result := (l.count = r.count) > l.start; r.start > until > not Result or l.off > loop > Result := (l.item = r.item) > l.forth; r.forth > end > end This has a certain elegance, but note that: (1) If Result is False after the first assignment, then the 'start' calls are executed unnecessarily. (2) If Result is False after the second assignment (in the body of the loop), then the 'forth' calls and the 'off' test are executed unnessarily. This is inefficient (as you point out) but at least it is harmless ... in this case. (More on that in a moment.) However, suppose Eiffel allowed mid-body loop exits, say with the following sort of syntax: equal (l, r: LIST): BOOLEAN is require l /= Void and r /= Void do Result := (l.count = r.count) if Result then from l.start; r.start until l.off loop Result := (l.item = r.item) until not Result then l.forth; r.forth end end end The 'if' statement avoids the extraneous 'start' calls. The mid-body 'until' clause terminates the loop immediately if its condition holds, avoiding the extraneous 'forth' calls, as well as the 'off' test at the top of the loop. Can anybody demonstrate whether or not this sort of language extension would have an adverse affect on Eiffel's principle of DBC, for the case of loops? There are situations where extraneous calls in the final loop iteration would not be so harmless. For instance, suppose you wished to implement an 'out' function for a LIST class that generated strings of the form: "{}" for an empty list "{A}" for a list with one element "A" "{A, B}" for a list with two elements "A" and "B" etc... In other words, separate the elements by commas, but only if there is more than one element. Here's a first attempt at a solution: out: STRING is do Result := "{"; from start until after loop Result.append (item.out) Result.append (", "); forth end Result.append ("}"); end Unfortunately, this is incorrect, because it places an extraneous comma after the last element. To correct this, we could add a test within the body: out: STRING is do Result := "{"; from start until after loop Result.append (item.out) forth if not after then Result.append (", "); end end Result.append ("}"); end Unfortunately, this causes the same 'after' test to be called twice on each iteration! To avoid this, we must unroll the loop: out: STRING is do Result := "{"; if not empty then from start Result.append (item.out) forth until after loop Result.append (", "); Result.append (item.out) forth end end Result.append ("}"); end Unfortunately, we've been forced to duplicate code. But suppose you could place an 'until' clause in mid-body: out: STRING is do Result := "{" if not empty then from start loop Result.append (item.out) forth until after then Result.append (", ") end end Result.append ("}") end This would seem the most elegant solution. But again, does this pose any difficulty for DBC in Eiffel? I can't see any problem, but I'm only a newbie with Eiffel. (Just now in the process of devouring OOSC2 from one cover to the other...) -- indexing description: "Signatures for John Volan" self_plug: "Ex Ada guru", "Java 1.1 Certified", "Eiffelist wannabe" two_cents: "Java would be even cooler with Eiffel's generics, % %assertions/DBC, true MI, feature adaptation, % %selective export, uniform access, etc., etc..." class JOHN_VOLAN_SIGNATURE inherit SIGNATURE invariant disclaimer: not (opinion implies employer.opinion) end -- class JOHN_VOLAN_SIGNATURE