Ok thats gonna be a long answer....
Not, if (as suggested) the expressions are pre-evaluated (once, just once) into local vars. You even quoted that part of my answer, and then (apparently) are ignoring it?
I didn't ignore anything. The fact is, you use _unnecessary_ local variables _and_ even with local variables, the programmer has to carefully read the entire if/else chain to ensure that A is always compared to B (and not other variables). As previously stated, in addition to that, using local variables leaves open the possibility of an incorrect comparison, e.g, A compared against Z, which is simply not possible when using the EVALUATE statement.
Ok, point for evaluate. It ensures you have all conditions in each line, as it expects a total count.
So:
- in "if" you can drop a column
- in "evaluate" you can swap two columns
(swapping in if is possible, but does not do damage, as the order of pre-evaluated arguments in chained "and" does not affect the result)
=> more on this 2 paragraphs below....
Yes, it needs extra lines for the assignment to the local vars.
And, as I just pointed above, having those additional local variables is _not_ without consequences.
The consequences you pointed out, are due to the "if" does not enforce the count of expressions.
The variables make no diff. In fact a/some compiler may internally create them for an "evaluate"
On the other hand, it makes it (by far) less likely, that in subsequent names 2 columns are switched by accident. (Especially if there are more "also" involved.
Less likely, yes but, not impossible in the sequence of if/else since they are repeated. Using the EVALUATE it simply isn't possible because their position occurs only _once_, since they aren't repeated they cannot be misplaced anywhere else.
Your answer does not seem to match my statement.
Just because "evaluate enforces the number of "also" does not mean, they can not be mis-placed.
If I want to write:
evaluate cnt also max also min also avg
when 1 also 2 also 3 also 4
It can by accident happen that I write
when 1 also 3 also 2 also 4
Since when I write the 3 there is no named reference what it is... It could be "min" or "max"... Easy to spot, if the evaluate is just 1 or 2 lines above. But when I have only a handful of "when" then changes of error are very low for "evaluate" as well as for "if".
It matters with growing amount of combinations. But then you easily get 10 or 20 "when", and each has some code attached to it. So the "evaluate" may well be off screen.
If the evaluate is off screen, then it needs to be something like (and cnt,max,min are pre-evaluated:
when cnt=1 also min=2 also max=3 also avg4
(the "evaluate" could still enforce that the 4 expressions, containing the 4 values, are all present)
---
And yes.
also splits the expression, having the first half of it in the "case" line, and then a number of possible 2nd parts for each block.
But it is easier to stick that together, since it is only one expression that is ripped... that needs to be kept in mind.
"evaluate" can split any amount of expressions. That is not a good idea to me.
Maybe I wanted the 3rd "also" to be true, all others false. But by accident, I did put true into the 4th (keeping the total column count correct). There will be no warning, no error, no easy way to spot (it is just a long line of "also true also false also ....", with no indication which "also ..." is for which expression.)
But with the evaluate, it is trivial to simply count the possibilities and see that the expected pattern is present, that is, (true, true), (true, false), (false, true) and (false, false). That pattern is obscured in a chain of if/else because of the repeated presence of if/else/then (and hopefully, it's formatted reasonably well which is far from a given.)
My quote was still on "when 1 also 2" could accidentally be "when 2 also 2". That is all columns, and all rows are present. But they have incorrect values.
Your answer seem to be about, all possibilities are covered. That is if 2 boolean are evaluate, there should be 4 "when". But the same there should be "4 if". No difference there.
The possibility of missing a column in one of the conditions was covered above (pro and con on both sides).
For this point therefore the comparison is only about missing an entire "when" or missing an entire "if". Both can be counted the same way.
Also counting that way is only for boolean or enum. "Evaluate" can also match integers. Then you do not know how many "when" there must be.
Yet if I use local vars (i.e. give each expression a name), then this error can not happen, as I immediately on each line can see, which names should be true and which should be false. (yes slightly more typing, but so much more readable)
Using local variables will make the expression more readable, I'll give you that but, you're conveniently ignoring the fact that they may be switched in one of the many if/else statements.
Afaik covered above.
* IF: an entire "also" may be missing, as no enforcement for the count of sub expressions
* Eval: I may write "when 2 also 1" where I meant to write "..1 .. 2"
I guess switched refers to the 2nd?
Well, I can switch "if (min=1) and (max=2)" to "if (min = 2) and (max=1)" => but that is no immediate problem.
Switching it to "if (min=2) and (mag=1)" is far far less likely using "if with locals" than using "evaluate". It is more likely to go wrong with eval., because in eval when I type "1" I have no close-by visual reference what it is compared too. (Yes if the "evaluate line is right above, but that is for the first "when" only.)
You're also ignoring the fact that now the programmer has to visually determine if any of those locals are modified in any of the if statements, something which is unnecessary when using EVALUATE (since, it normally wouldn't use locals.)
Only one "if" should be entered (so it did ask about, how evaluate handles this)....
If only one "if" is entered, then modifications to the vars do not matter. The other "else if" will never be tested, due to the "else"
In case evaluate allows to enter more than one "when" statement....
Well Pascal has a write protected variable
for AB in TBoolArray.Create(a=b) do begin
// other vars as for in
// the if/else if/else if blocks
end;
Ok. Not serious. If evaluate can enter more than one "when", then point to you.
See the example code in this reply https://forum.lazarus.freepascal.org/index.php/topic,47498.msg340388.html#msg340388
Each "and" ("also") clearly indicates which expression is wanted as true and which is wanted as false. What in this line is less readable than in a "when" line?
First, you only showed _one_ line, of course it's readable, it's only one line. Second, it is almost as rare as Christ's second coming to see if/else chains formatted the way you formatted it (nice formatting, I do appreciate that.) In contrast, an EVALUATE statement is almost always seen properly formatted (WHEN and ALSO clauses vertically aligned.) Of course, there are occasional exceptions as you noted further down your post.
If I use "if else if else if" in an "evaluate" manner, of course I have to format it the same way. And that is a feature that is available...
You havent seen this with "if", well that is not a request for a new feature, but for educating people.
Or shall I read this statement as "the (supposed) readability of evaluate, is actually not coming from the evaluate statement, but from the code formating people have adapted"?
If there are multiply "else if" lines, they will be equally readable as multiple "when" lines.
The main diff here are
1) word substitution: "when" > "else if" / "also" > "and" / That should not affect readability, as in anycase if such a feature where to be added, keywords might be different too.
2) instead of "1 also 2 also 3 also 4" you get "(cnt = 1) and (min = 2) and (max = 3) and (avg = 4)". So you do not constantly need to scroll to the "evaluate" line. IMHO better.
btw, there is an editor macro for aligning things (on wiki pascal script macros). Not powerful enough for this, but a start.
Having names for elements (and close to the elements) is so important, that I have frequently seen code where those names (when the language did not need them) were added in comments. Yet here we have a feature that again intentionally omits them
It is also important _not_ having to name them, that's why the language allows expressions most everywhere, so the programmer doesn't have to declare a variable for every expression to be used in a statement. In this particular case, those additional variables are a clear indication of a deficiency in the language. If the expression is complicated/long then, for clarity, it is justified but, for a simple expression such as A > B, it is _not_ justified.
Ok, I wasn't clear enough. Having names for expression, to which you later refer again.
And yes, I am aware of "with .. do", and I made my comment about it in a previous post. (And on top, there were discussions on the forum about "with ... as X do ")
I am aware that for you, the look up, due to the position in the "grid/table" is sufficient. And I stated that for small samples that is fine. But eventually it scrolls of the screen.
And even on screen, at a certain distance it becomes harder to lookup.
Not to mention the fun...
evalute enum also enum2 also enum3
followed by 20 or more lines "when"
=> and all the lines are formatted for enum identifiers up to 15 chars, when a new enum value is added that is longer.... yeah.
"for in" for ranges, actually is sugar. And drops the information that it is a range/ordinal type.
If a construct prevents a potential error then it isn't sugar, it is practical and valuable because it prevents a possible error.
what error does it prevent?
That I write "high() to low()" ? Well yes that it does...
But probably there are real error that can be prevented, even though I am not aware....
Almost any change can prevent "some" error. But that does not mean that all such changes are worth even thinking about them.
And also that would mean "syntax sugar" does not exist?
Like "evaluate" can prevent errors, but also introduces new ones (see near top of this reply). So on balance.....
As I said, reading the (lets say) 10th "when" line (with each "when" line before, being followed by a block of code, so maybe 40 to 50 lines down from the "evaluate"), the "also true also false also false also true ...." is really not helping. (if you do not have an photographic memory, to remember the "evaluate" line.
It helps plenty but, it cannot be argued that a 50 line EVALUATE statement requires paying a little more attention than a 12 line EVALUATE. That is true of any statement but, there is a whole lot less clutter getting in the way with an EVALUATE statement than what is found in the equivalent chain of if/else. It seems you conveniently ignored that.
How is the clutter different (except for assigning local vars on top), if they otherwise are mainly word substitutions (from a readability point)
Note: the checking that all "Also" must be presence, and none can be omited is not relevant when talking about clutter (in terms of readability).
Other than replacing Also with And, each expression is to be prefixed with "localvar =" (or other operator). But when it grows to such length, this is actually helpful.
Well yes its a fine line between sugar and other..... And one that is to an extend biased by subjective opinion.
It's subjective until you create the graph for the two constructs, which clearly shows that the EVALUATE graph is much simpler than that of the if/else chain AND, as previously stated, the EVALUATE makes it evident that the values being tested _cannot_ change in the construct something which the if/else chain cannot guarantee nor makes it visible since it is saddled with having to use local variables.
answered above
From what I read on it sofar, the only part that is NOT sugar about it, is that it needs each expression only once, and thereby avoids re-evaluation.
Yes and, that very small detail makes a BIG difference.
Agreed, but already exists in todays Pascal / FPC. So no new statement needed.
As for the need of of "const local var" (one time only assignment...) that depends on the question if only one "when" can be entered, or if several can....
However:
- without giving a name (as reference) to the result of each expression, this is actually introducing problems (its ok for small samples, but not for bigger cases)
What problems does it introduce ?... name them or show an example AND it must be a problem that is _not_ present when using if/else.
That on bigger "when" lists, arguments to "when/also" can be mixed up in order. See above
- The same effect can be done with local vars.
I never said the logical construct cannot be expressed in Pascal. What I do say is, the resulting construct is noticeably inferior in readability and maintainability than the equivalent EVALUATE statement.
It seems we have a very different view of readability.
I could see some readability improvements for some code with a different evaluate
evalute foo(x) as cnt also b as b also c=d as CeqD
So that the when statements will then refer to each value by name....
https://github.com/Apress/beg-cobol-for-programmers/blob/master/978-1-4302-6253-4_Coughlan_Ch05/Listing5-9.cbl
I appreciate your looking it up. I won't say anything about it being "short" or otherwise but, it is a lot clearer than the equivalent in Pascal.
That's not bad at all. The same construct using if/else chains would probably result in your being blind thus requiring a white cane and a seeing dog. Your optometrist would be _very_ unhappy.
Comes down to the missing names. See just above this quote.
Local vars, is what currently exists in pascal, if you make this "evaluate ... as ..." then its ok...
Of course then you could instead introduce an extended "with do" (this is no real code, the alias names are crap, but it illustrates what I have in mind)
with foo(x) as cnt , b as b , c=d as CeqD do // aliases would have to be read only, so they cannot be changed
if (cnt = 1) and (b = 1) and (CeqD = true) then
....
else if (cnt = 2) and (b = 1) and (CeqD = true) then
....
else if (cnt = 1) and (b = 2) and (CeqD = true) then
....
else if (cnt = 1) and (b = 1) and (CeqD = false) then
....
given proper matrix formatting, it works the same
- readable (really just diff keywords, same sentence structure, same formatting, same grid.....)
- the alias names are present in the modified evaluate too
- rows can be counted tooo
- only evaluated once
- alias can not be assigned new values
Not sure if I want to promote "with" but diff story
Reading it, on each line I go: "21 throu 99" of what?
Of Qty of course. Expression in first column applies to the item in the first column.
I am aware. But I find it more readable if the entire comparison is in one place.
The statement takes the expression "Qty = 21 throu 99", tears it appart, puts half of it in one line, and the other half somewhere else....
Maybe it's your browser that's doing that. When I look at it, everything is perfectly aligned. Like this (added asterisks to make the logical groups even more visible)
No, aliment was perfect.
I am just used to (from my childhood on) to read from left to right, then a bit down back to start of line, and from left to right..... (same as my epson p60 matrix printer)
Reading, a bit to the right, far up a bit back left, then a bit to the right, far down, a further bit to the right .....
Just not readability.....
Anyway one or two points to you....
I do stay with my statement that it needs "as" => "evaluate foo(x) as fx also ..."
Based on that (if you disagree with the above line, the below is void for you too):
I also keep to "if else if" can be exactly as readable (given the exact same formatting, it is mainly word substitution).
But it introduces "local vars" which may not be desirable.
Then that leaves a choice between "extended WITH" or "evaluate". The former can be used for other stuff too, therefore more flexible.