!standard 5.5(6.2/6) 19-04-09 AI12-0327-1/03 !standard 4.3.3(21) !standard 4.3.5(0) !standard 4.5.8(6/4) !standard 4.5.10(0) !class Amendment 19-04-05 !status Amendment 1-2012 19-04-09 !status WG9 Approved 22-06-22 !status ARG Approved 11-0-0 19-04-09 !status work item 19-04-05 !status received 19-03-18 !priority Low !difficulty Easy !subject Clarify iterator filter wording for aggregates !summary The Iterator filter wording for aggregates and quantified expressions is made more explicit. !problem The wording in 5.5 that discusses how loop_parameter_specification and iterator_specification work in contexts other than loop_statements never describes how the values assigned to the loop parameter turn into values "produced by" the iterator. In addition, none of the wording in the uses of these iterators (in aggregates, reductions, and quantified expressions) ever makes it clear that the filter plays a role. We need wording that explains what is actually happening, rather than wording that leaves everything to the imagination of the reader. !proposal (See Summary.) !wording [The paragraph numbers in this AI are for draft 19 of the RM - Editor.] Replace 5.5(6.2/5) with: The /filter/ of an /iterator construct/ (a loop_parameter_specification, iterator_specification, or procedural_iterator) is defined to be /satisfied/ when there is no iterator_filter for the iterator construct, or when the condition of the iterator_filter evaluates to True for a given iteration of the iterator construct. If a sequence_of_statements of a loop_statement with an iterator construct is said to be /conditionally executed/, then the statements are executed only when the filter of the iterator construct is satisfied. The loop iterators loop_parameter_specification and iterator_specification can also be used in contexts other than loop_statements (for example, see 4.3.5 and 4.5.8). In such a context, the iterator *conditionally produces* values in the order specified for the associated construct below or in 5.5.2. The values produced are the values given to the loop parameter when the filter of the iterator construct is satisfied for that value. Redundant[No value is produced when the condition of an iterator_filter evaluates to False.] Modify 4.3.3(20.4/5): 2. A second iteration is performed for each of the iterator_specifications, in the order given in the aggregate, and for each value {conditionally} produced {by the iteration (see 5.5 and 5.5.2)}, the associated expression is evaluated, its value is converted to the component subtype of the array type, and used to define the value of the next component of the array starting at the low bound and proceeding sequentially toward the high bound. A check is made that the second iteration results in an array length no greater than the maximum determined by the first iteration; Constraint_Error is raised if this check fails. Modify 4.3.5(47/5): * for a container_element_association with an iterated_element_association, first the iterated_element_association is elaborated, then an iteration is performed{, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2)}[ as described in 5.5 or 5.5.2, and for each value of the loop parameter of the iteration] the Add_Named procedure is invoked with the anonymous object A as the first parameter, the result of evaluating the expression as the third parameter, and: Modify 4.3.5(53/5): 2. an iteration is performed{, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2)}[ as described in 5.5 or 5.5.2, and for each value of the loop parameter of the iteration, ]the Add_Unnamed procedure is invoked, with the anonymous object A as the first parameter and the result of evaluating the expression as the second parameter. Modify 4.5.8(6/4): For the evaluation of a quantified_expression, the loop_parameter_specification or iterator_specification is first elaborated. The evaluation of a quantified_expression then {performs an iteration, and }evaluates the predicate for {each value conditionally produced by the iteration (see 5.5 and 5.5.2)} [the values of the loop parameter in the order specified by the loop_parameter_specification (see 5.5) or iterator_specification (see 5.5.2)]. {AARM Ramification: The order of evaluation of the predicates is that in which the values are produced, as specified in 5.5 or 5.5.2.} Modify 4.5.10(27/5): For the evaluation of a value_sequence, the iterated_element_association is elaborated, then an iteration is performed[as described in 5.5 or 5.5.2], and for each value {conditionally} produced by the [iterator]{iteration (see 5.5 and 5.5.2)}, the associated expression is evaluated with the loop parameter having this value, to produce a result that is converted to Value_Type, and used to define the next value in the sequence. !discussion This wording makes where the values come from explicit. The 4.3.5 wording was OK in this respect (since it talked about the loop parameter), but the other wording was not. We make all of the wording consistent in order to ease future maintenance, even the 4.3.5 wording (since it did not clearly describe the role of the filter). !corrigendum 4.3.3(21) @drepl The evaluation of an @fa of a given array type proceeds in two steps: @dby For an @fa that contains only @fas that are @fas with @fas, evaluation proceeds in two steps: @xhang<@xterms<1.>Each @fa is elaborated (in an arbitrary order) and an iteration is performed solely to determine a maximum count for the number of values produced by the iteration; all of these counts are combined to determine the overall length of the array, and ultimately the limits on the bounds of the array (defined below);> @xhang<@xterms<2.>A second iteration is performed for each of the @fas, in the order given in the @fa, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2), the associated @fa is evaluated, its value is converted to the component subtype of the array type, and used to define the value of the next component of the array starting at the low bound and proceeding sequentially toward the high bound. A check is made that the second iteration results in an array length no greater than the maximum determined by the first iteration; Constraint_Error is raised if this check fails.> The evaluation of any other @fa of a given array type proceeds in two steps: !corrigendum 4.3.5(0) @dinsc A fake to force a conflict; the actual text is in the conflict file. !corrigendum 4.5.8(6/3) @drepl For the evaluation of a @fa, the @fa or @fa is first elaborated. The evaluation of a @fa then evaluates the @fa for the values of the loop parameter in the order specified by the @fa (see 5.5) or @fa (see 5.5.2). @dby For the evaluation of a @fa, the @fa or @fa is first elaborated. The evaluation of a @fa then performs an iteration, and evaluates the @fa for each value conditionally produced by the iteration (see 5.5 and 5.5.2). !corrigendum 4.5.10(0) @dinsc A fake to force a conflict; the actual text is in the conflict file. !corrigendum 5.5(7) @drepl For the execution of a @fa, the @fa is executed repeatedly, zero or more times, until the @fa is complete. The @fa is complete when a transfer of control occurs that transfers control out of the loop, or, in the case of an @fa, as specified below. @dby The @i of an @i (a @fa, @fa, or @fa) is defined to be @i when there is no @fa for the iterator construct, or when the @fa of the @fa evaluates to True for a given iteration of the iterator construct. If a @fa of a @fa with an iterator construct is said to be @i, then the statements are executed only when the filter of the iterator construct is satisfied. The loop iterators @fa and @fa can also be used in contexts other than @fas (for example, see 4.3.5 and 4.5.8). In such a context, the iterator @i values in the order specified for the associated construct below or in 5.5.2. The values produced are the values given to the loop parameter when the filter of the iterator construct is satisfied for that value. No value is produced when the @fa of an @fa evaluates to False. For the execution of a @fa, the @fa is executed zero or more times, until the @fa is complete. The @fa is complete when a transfer of control occurs that transfers control out of the loop, or, in the case of an @fa, as specified below. !ASIS No ASIS change, this is just wording. !ACATS test No additional ACATS tests are needed, this is just clarifying the intent. !appendix From: Randy Brukardt Sent: Monday, March 18, 2019 9:12 PM I'm putting AI12-0250-1 into the draft RM, and as usual that means reading the wording more carefully than before. 4.3.3(20.4/5) is modified as follows: 2. A second iteration is performed for each of the iterator_specifications, in the order given in the aggregate, and for each value produced, the associated expression is evaluated, its value is converted to the component subtype of the array type, and used to define the value of the next component of the array starting at the low bound and proceeding sequentially toward the high bound. A check is made that the second iteration results in [the same} {an} array length {no greater than the maximum determined by the first iteration}; Constraint_Error is raised if this check fails. Nothing in this wording implies that the part about evaluating the "associated expression" is conditional on the filter. One could apply the Dewar rule here (having a filter and ignoring it doesn't make sense), but that's horrible. Tucker added the following sentence to 5.5 to "fix" this problem: In contexts where a loop_parameter_specification or iterator_specification is used to produce a sequence of values (see 4.3.3 and 4.3.5), if an iterator_filter is present, the sequence of values will contain only the values for which the iterator_filter is satisfied. But this doesn't make a lot of sense: (1) As this is written, it doesn't appear to apply to 4.5.8 or 4.5.10. The rewording of 4.5.10 also uses the "for each value produced" wording, and it might arguably "produce a sequence of values", but the lack of a cross-reference means that one isn't sure. (It doesn't read like examples of places where this happens, it seems like a complete list.) For 4.5.8, the wording is "the predicate is evaluated for the values of the loop parameter in the order specified ..." - "produced" doesn't appear either. In none of these four places does the word "sequence" appear, so there is no strong tie to the places as to where this wording applies - it pretty much is whatever the reader wants it to be. (2) In the cases of the aggregates, the "sequence of values" of interest is that of the components of the array or elements of the container. It's not at all clear how one leaps from those to the (virtual) sequence of values created by the iterator. (3) The wording is very different from the loop statement case, where all of the values are generated and then the sequence_of_statements is conditionally executed. Given that the "sequence of values" is derived from that wording purely by hand waving (the wording for loop statements talks about the successive values of the loop parameter, how that somehow morphs into a "sequence of values" is never described anywhere), having the wording being presented differently just adds to the confusion. (4) There's no indication at the point of use (that is, in 4.3.3, 4.3.5, 4.5.8, and 4.5.10) that the values are anything other than those provided directly by the iterator. At a minimum, there ought to be some clear terminology that makes it clear that there is more going on than just providing the values in turn. (5) I'd rather avoid talking about "sequences of values" outside of reductions, since such an idea is more formally presented there and doing so elsewhere is going to be confusing (particularly when the semantics differs). -- OK, I've griped enough. I suppose I have to propose something (especially with Tucker on vacation). This is a hard problem, and I think we need to do more to describe where the values come from. (I've been griping about that for years -- since the introduction of quantified expressions -- without getting anything done.) So, rather than having a single sentence, I think we need a paragraph on this topic. So, perhaps delete the sentence noted above and create a new paragraph instead: The constructs loop_parameter_specification and iterator_specification can also be used in contexts other than loop_statements. Redundant[They can be used, for instance, in container aggregates (see 4.3.5) and quantified expressions (see 4.5.8).] In such a context, the iterator *conditionally produces* values in the order specified for the associated construct below or in 5.5.2. The values produced are the values given to the loop parameter when there is no iterator_filter or the iterator_filter evaluates to True. Redundant[No value is produced when the iterator_filter (if any) evaluates to False.] Then, we would change each of the places involved to clearly use the wording "conditionally produced" with a cross-reference. Thus, in 4.3.3(20.4/5) above, we would make the following minor change: 2. A second iteration is performed for each of the iterator_specifications, in the order given in the aggregate, and for each value {conditionally} produced {by the iteration (see 5.5 and 5.5.2)}, the associated expression is evaluated, its value is converted to ... (I added both cross-references here rather than just 5.5 for the new term; the other locations already have references to 5.5.2 and it seems valuable everywhere.) We'd make similar (but somewhat larger) changes to 4.3.5(47/5), 4.3.5(53/5), 4.5.8(6/4), and 4.5.10(27/5). [Draft 18 numbering, these may be different in draft 19 because of the addition of AI12-0250-1 wording.] Assuming that there isn't a lot of pushback on this idea, I'll write something up for the next meeting. Thoughts? Improvements? Brickbats? **************************************************************** From: Randy Brukardt Sent: Monday, March 18, 2019 10:41 PM I probably should have used Tucker's "satisfied" wording in this paragraph, it's more specific about the evaluation of the iterator_filter. That would shorten it a touch to: The constructs loop_parameter_specification and iterator_specification can also be used in contexts other than loop_statements. Redundant[They can be used, for instance, in container aggregates (see 4.3.5) and quantified expressions (see 4.5.8).] In such a context, the iterator *conditionally produces* values in the order specified for the associated construct below or in 5.5.2. The values produced are the values given to the loop parameter when there is no iterator_filter or the iterator_filter is satisfied. Redundant[No value is produced when the iterator_filter is not satisfied.] [Aside: I'm not sure why Tucker didn't simply define "satisfied" in such a way that if there is no filter, it is satisfied. That would reduce the wording further, both here and in the loop_statement case. I suppose it is because of the oddity of talking about syntax that isn't there. But we could get around that by talking about the "filter" of an iterator. Something like: The /filter/ of an /iterator construct/ (a loop_parameter_specification, iterator_specification, or procedural_iterator) is defined to be /satisfied/ when there is no iterator_filter for the iterator construct, or when the condition of the iterator_filter evaluates to True for a given iteration of the loop iterator. Then: The term /conditionally executed/ when referring to the sequence_of_statements of a loop_statement means that the statements are executed only when the filter of the iterator construct is satisfied. And the above: The loop iterators loop_parameter_specification and iterator_specification can also be used in contexts other than loop_statements. Redundant[They can be used, for instance, in container aggregates (see 4.3.5) and quantified expressions see 4.5.8).] In such a context, the iterator *conditionally produces* values in the order specified for the associated construct below or in 5.5.2. The values produced are the values given to the loop parameter when the filter of the iterator construct is satisfied for that value. Redundant[No value is produced when the condition of an iterator_filter evaluated to False.] I'm not a fan of "iterator construct" as a term, but we need something shorter than "loop_parameter_specification, iterator_specification, or procedural_iterator" all over the place. I didn't want to just use "iterator", as that would seem to conflict with more specific terminology in 5.5.2. End Aside] **************************************************************** From: Randy Brukardt Sent: Tuesday, April 9, 2019 11:32 PM You guys couldn't decide on any wording fix for the 5.5(6.2/5) change, and dumped that back on me. Thanks a lot. I already had my best shot: When we say that a sequence_of_statements of a loop_statement is /conditionally executed/, the statements are executed only when the filter of the iterator construct is satisfied. "When we say that" was disliked, and then we went into a series of increasingly bad rewordings, ending up at: A sequence_of_statements of a loop_statement with an iterator construct is said to be /conditionally executed/ if the statements are executed only when the filter of the iterator construct is satisfied. This still doesn't read like a definition. My only idea is to go back my original idea, and simply drop the "we say that" part: When a sequence_of_statements of a loop_statement is /conditionally executed/, the statements are executed only when the filter of the iterator construct is satisfied. Is that good enough, or does someone else have an idea?? **************************************************************** From: Jean-Pierre Rosen Sent: Wednesday, April 10, 2019 1:52 AM My suggestion: A sequence_of_statements of a loop_statement is said to be /conditionally executed/ if the statements are executed only when the filter of the iterator construct is satisfied. **************************************************************** From: Tucker Taft Sent: Wednesday, April 10, 2019 7:29 AM > A sequence_of_statements of a loop_statement with an iterator > construct is said to be /conditionally executed/ if the statements > are executed only when the filter of the iterator construct is satisfied. > > This still doesn't read like a definition. I don't see why you say this doesn't read like a definition. It certainly reads like a definition to me. We have italics. We have "said to be." How could it be interpreted as anything but a definition? > My only idea is to go back my > original idea, and simply drop the "we say that" part: > > When a sequence_of_statements of a loop_statement is /conditionally > executed/, the statements are executed only when the filter of the > iterator construct is satisfied. This feels less like a definition than the one above, and suffers from the problem that "iterator construct" is not defined for while loops and infinite loops. > Is that good enough, or does someone else have an idea?? I prefer the "said to be" wording. JP suggested: "A sequence_of_statements of a loop_statement is said to be /conditionally executed/ if the statements are executed only when the filter of the iterator construct is satisfied." My problem with this is that "the iterator construct" is not well defined if the loop_statement doesn't have one (e.g. a "while" loop or an "infinite" loop). So I would go with the one above that you feel is not "definition-like" since from my perspective it is clearly a definition. **************************************************************** From: Jeff Cousins Sent: Wednesday, April 10, 2019 5:28 AM That seems clearer to me. **************************************************************** From: Tullio Vardanega Sent: Wednesday, April 10, 2019 8:42 AM >> This still doesn't read like a definition. That reads like a definition to me and I would be fine with it. [...] **************************************************************** From: Randy Brukardt Sent: Wednesday, April 10, 2019 5:07 PM > > A sequence_of_statements of a loop_statement with an iterator > > construct is said to be /conditionally executed/ if the statements > > are executed only when the filter of the iterator construct is satisfied. > > > > This still doesn't read like a definition. > > I don't see why you say this doesn't read like a definition. > It certainly reads like a definition to me. We have italics. > We have "said to be." How could it be interpreted as anything but a > definition? I agree that the set-up looks like a definition, but the actual definition does not read like a definition. "if the statements are executed" sounds to me like something that's happening now, as opposed to something definitional. Think of it as a dictionary entry: conditionally executed (for a sequence_of_statements): If the statements are executed only when the filter of the iterator construct is satisfied. This definition doesn't make any sense. The "if" does not belong here; one needs some other word or punctuation to connect the description of the term to the actual definition. But I can't find one that works. "When ... then ..." works, but you say you don't like that. Secondly, I thought that the complaint about the original wording was the use of "say". Changing "say" to a different form of the same work "said" doesn't seem responsive to that complaint. > > My only idea is to go back my > > original idea, and simply drop the "we say that" part: > > > > When a sequence_of_statements of a loop_statement is /conditionally > > executed/, the statements are executed only when the filter of the > > iterator construct is satisfied. > > This feels less like a definition than the one above, and suffers from > the problem that "iterator construct" is not defined for while loops > and infinite loops. I'm not sure why you say this feels less like a definition; I can't rebut "feel" (especially when it's wrong ;-). Try the dictionary test again: conditionally executed (for a sequence_of_statements): The statements are executed only when the filter of {an}[the] iterator construct is satisfied. That's not ideal either (although its better with the noted change), but I'm out of ideas. In any case, it is fine to use "iterator construct" in this definition. We do not use "conditionally executed" for other kinds of loops. It wouldn't make sense to do that, because they have no filter -- regardless of how the wording is defined. Specifically, the term is used in 5.5(9/5) (which is specifically describing the execution of loops with loop_parameter_specifications". 5.5(7/5) and 5.5(8) (which define infinite and while loops, respectively) do not use the term at all. Similarly, all of the uses in 5.5.2 have to do with various kinds of iteration. There's no need for the term to be related to other kinds of loops, just to iterators, so it is fine to use "iterator construct". So I still prefer the above. We could literally add a qualification to the first part if it makes you feel better: When a sequence_of_statements of a loop_statement with an iterator construct is /conditionally executed/, the statements are executed only when the filter of the iterator construct is satisfied. An alternative would be use "If" rather than "when": If a sequence_of_statements of a loop_statement with an iterator construct is /conditionally executed/, then the statements are executed only when the filter of the iterator construct is satisfied. But of course that doesn't make the definition part read any better. ... > JP suggested: > > "A sequence_of_statements of a loop_statement is said to be > /conditionally executed/ if the statements are executed only when the > filter of the iterator construct is satisfied." > > My problem with this is that "the iterator construct" is not well > defined if the loop_statement doesn't have one (e.g. a "while" loop or > an "infinite" loop). Which, as described above, is irrelevant, and easily fixable as well. But J-P's version doesn't fix the problem that the definition (rather than the description of the term) doesn't make sense as a definition (as it is the same as the original, and doesn't change the part I object to). **************************************************************** From: Jean-Pierre Rosen Sent: Thursday, April 11, 2019 12:55 AM The problem may be that we are trying to define "conditionally executed" rather than "conditionally executed sequence of statements". Trying the dictionary test again: conditionally executed sequence of statements: A sequence_of_statements that is executed only when the filter of an iterator construct is satisfied Sounds better... **************************************************************** From: Tucker Taft Sent: Thursday, April 11, 2019 6:03 PM >I agree that the set-up looks like a definition, but the actual definition >does not read like a definition. >"if the statements are executed" sounds to me like something that's >happening now, as opposed to something definitional. Think of it as a >dictionary entry: > > conditionally executed (for a sequence_of_statements): > If the statements are executed only when the filter of the > iterator construct is satisfied. > >This definition doesn't make any sense. The "if" does not belong here; one >needs some other word or punctuation to connect the description of the term >to the actual definition. But I can't find one that works. "When ... then >..." works, but you say you don't like that. I objected to the "When we say...." I don't object to using "when" in general. But I agree that "when" doesn't really help here. The simple solution to your dictionary entry is simply to omit the "if": conditionally executed (for a sequence_of_statements): The statements are executed only when the filter of the iterator construct is satisfied. I think if you want to mechanically convert the original statement into a dictionary entry, you need to break it as follows: A sequence_of_statements of a loop_statement with an iterator construct is said to be /conditionally executed/ if: the statements are executed only when the filter of the iterator construct is satisfied. >Secondly, I thought that the complaint about the original wording was the >use of "say". Changing "say" to a different form of the same work "said" >doesn't seem responsive to that complaint. The complaint was about "When we say ..." -- who is "we"? ... >So I still prefer the above. We could literally add a qualification to the >first part if it makes you feel better: > > When a sequence_of_statements of a loop_statement with an iterator > construct is /conditionally executed/, the statements are executed > only when the filter of the iterator construct is satisfied. This is fine with me. But I also think the one with the "said to be" is just as good, and is less likely to be confused with a normative statement of semantics. I think you were getting hung up on trying to mechanically create the dictionary entry from the statement. If you treat the "if" as part of the introduction, (as shown above) the dictionary entry seems fine. >An alternative would be use "If" rather than "when": > > If a sequence_of_statements of a loop_statement with an iterator > construct is /conditionally executed/, then the statements are > executed only when the filter of the iterator construct is satisfied. This one is also fine with me. >But of course that doesn't make the definition part read any better. I don't know what you mean by the "definition part" in this context. Again, the right way to structure this if you want to extract the "definition" is as follows: If a sequence_of_statements of a loop_statement with an iterator construct is /conditionally executed/, then: The statements are executed only when the filter of the iterator construct is satisfied. ... >JP suggested: > >"A sequence_of_statements of a loop_statement is said to be >/conditionally executed/ if the statements are executed only >when the filter of the iterator construct is satisfied." > >My problem with this is that "the iterator construct" is not >well defined if the loop_statement doesn't have one (e.g. a >"while" loop or an "infinite" loop). > >Which, as described above, is irrelevant, and easily fixable as well. > >But J-P's version doesn't fix the problem that the definition (rather than >the description of the term) doesn't make sense as a definition (as it is >the same as the original, and doesn't change the part I object to). Again, I think if you group the "if" with the introductory part of the sentence, your hypothetical dictional entry doesn't suffer from the problem you are complaining about. **************************************************************** From: Randy Brukardt Sent: Thursday, April 11, 2019 8:34 PM ... >I objected to the "When we say...." I don't object to using "when" in >general. >But I agree that "when" doesn't really help here. The simple solution to >your dictionary entry is simply to omit the "if": > > conditionally executed (for a sequence_of_statements): > The statements are executed only when the filter of the > iterator construct is satisfied. Sure, but if you need someone to explain how some wording is read, *it's bad wording*! "if" is the start of many rules and definitions, and to say, "well, this time, and this time only, you should just read the "if" as a connector word rather than anything meaningful!", that's not helping the clarity of the Standard. On top of that, a definition isn't "if" anything. It just is. >I think if you want to mechanically convert the original statement into >a dictionary entry, you need to break it as follows: > > A sequence_of_statements of a loop_statement with an iterator > construct is said to be /conditionally executed/ if: > > the statements are executed only when the filter > of the iterator construct is satisfied. Sure, but again: if someone (especially someone experienced) needs to be *told* how to read something, it's not working. We can do better. >... >So I still prefer the above. We could literally add a qualification to >the first part if it makes you feel better: > > When a sequence_of_statements of a loop_statement with an iterator > construct is /conditionally executed/, the statements are executed > only when the filter of the iterator construct is satisfied. > >This is fine with me. But I also think the one with the "said to be" is >just as good, and is less likely to be confused with a normative statement >of semantics. "said to be" is fine by me, but the "if" in the middle has to go. >I think you were getting hung up on trying to mechanically create the >dictionary entry from the statement. If you treat the "if" as part of >the introduction, (as shown above) the dictionary entry seems fine. But why would one do that? In approximately 90% of RM statements, the "if" is the start of the rule. >>An alternative would be use "If" rather than "when": >> >> If a sequence_of_statements of a loop_statement with an iterator >> construct is /conditionally executed/, then the statements are >> executed only when the filter of the iterator construct is satisfied. >> >This one is also fine with me. I have less objection to starting the definition with "then", because that is a well-known connector word that never starts anything. So it's pretty clear it belongs to the term and not to the definition. Perhaps we should combine the two ideas: If a sequence_of_statements of a loop_statement with an iterator construct is said to be /conditionally executed/, then the statements are executed only when the filter of the iterator construct is satisfied. This seems to be clearly a definition, and it's pretty obvious that the meat doesn't start with "then". I'll go with that unless someone objects. **************************************************************** From: Tucker Taft Sent: Friday, April 12, 2019 6:16 PM Works for me. **************************************************************** From: Tucker Taft Sent: Saturday, April 13, 2019 11:10 AM But "for the record," I think you still have an unnecessarily restrictive implicit rule about definitions. "Blah is said to be foo-bar, if blah is always frobisher" seems to be a perfectly good way of defining what we mean by "foo-bar." For example: You are said to be "seriously drunk" if every time you try to stand up you fall over. Anyway, I am fine with your "if ... then ..." formulation if that somehow works better for you. **************************************************************** From: Randy Brukardt Sent: Tuesday, May 7, 2019 5:34 PM > But "for the record," I think you still have an unnecessarily > restrictive implicit rule about definitions. And you have a blind spot about the particular wording. > "Blah is said to be foo-bar, if blah is always frobisher" > seems to be a perfectly good way of defining what we mean by > "foo-bar." Surely. But in that case the "if" belongs reasonably to the definition: foo-bar: if blah is always frobisher This makes sense. > For example: > > You are said to be "seriously drunk" if every time you try to stand > up you fall over. "seriously drunk": if every time you try to stand up you fall over. Again, makes sense read this way. The original wording does not make sense read this way. That was my objection. > Anyway, I am fine with your "if ... then ..." formulation if that > somehow works better for you. OK. But I have to get the last word in. :-) ****************************************************************