Recent

Author Topic: ways to avoid begin-end’s?  (Read 8133 times)

Khrys

  • Sr. Member
  • ****
  • Posts: 342
Re: ways to avoid begin-end’s?
« Reply #15 on: May 09, 2024, 08:53:09 am »
Just for the record, it is not syntactic abuse to have a statement such as "x := <some integer> and SomeFunction();" SomeFunction could simply be a function that returns the correct mask to use in that situation.  Quite run of the mill stuff.

You're absolutely right. I just made that example in the context of the original poster who wanted to avoid  begin/end  - if avoiding those is the sole intention, then I'd consider it syntax abuse, especially in OP's example that uses  X  as an argument to  DoSomething:

Code: Pascal  [Select][+][-]
  1. if X = 1 then X := 2 and DoSomething(X);

If this is done only for aesthetic reasons, then the programmer expects that X = 2  and that the next statement is  DoSomething(2), but that's not the case. And afterwards  X = 2  isn't even necessarily true unless  DoSomething  returns a no-op  AND  mask. So I think it's fair to call this specific example abuse of syntax.

Weiss

  • Full Member
  • ***
  • Posts: 219
Re: ways to avoid begin-end’s?
« Reply #16 on: May 09, 2024, 10:12:12 am »
Just for the record, it is not syntactic abuse to have a statement such as "x := <some integer> and SomeFunction();" SomeFunction could simply be a function that returns the correct mask to use in that situation.  Quite run of the mill stuff.

You're absolutely right. I just made that example in the context of the original poster who wanted to avoid  begin/end  - if avoiding those is the sole intention, then I'd consider it syntax abuse, especially in OP's example that uses  X  as an argument to  DoSomething:

Code: Pascal  [Select][+][-]
  1. if X = 1 then X := 2 and DoSomething(X);

it wasn't a good example, I completely made it up without thinking. In original code, I wanted to advance the counter along with assigning value to a variable. Which does work, if I create function
Code: Pascal  [Select][+][-]
  1. function increment(i : integer) : integer;
  2. begin
  3. i:=i+1;
  4. end

providing "i" is accessible, then I can omit begin-end, like Thaddy suggested

Code: Pascal  [Select][+][-]
  1. if x=1 then x:=2 and increment(i);

I don't even need brackets, just like that, two separate operations without wrapping in "begin-end". Something I never knew existed. Since I have to create a function, it doesn't save on key strokes and thus it is purely academic knowledge. But it was fun exploring Pascal.

alpine

  • Hero Member
  • *****
  • Posts: 1410
Re: ways to avoid begin-end’s?
« Reply #17 on: May 09, 2024, 10:29:04 am »

it wasn't a good example, I completely made it up without thinking. In original code, I wanted to advance the counter along with assigning value to a variable. Which does work, if I create function
Code: Pascal  [Select][+][-]
  1. function increment(i : integer) : integer;
  2. begin
  3. i:=i+1;
  4. end

providing "i" is accessible, then I can omit begin-end, like Thaddy suggested

Code: Pascal  [Select][+][-]
  1. if x=1 then x:=2 and increment(i);

I don't even need brackets, just like that, two separate operations without wrapping in "begin-end". Something I never knew existed. Since I have to create a function, it doesn't save on key strokes and thus it is purely academic knowledge. But it was fun exploring Pascal.
This is a single assignment with a constant (2) bitwise-anded with the result of increment() and with a side-effect (the increment of i)! But you didn't specify the result for the function, neither that the argument will be passed by reference! No side effect and x will be undefined. If it works it is a pure chance.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: ways to avoid begin-end’s?
« Reply #18 on: May 09, 2024, 10:30:56 am »
it wasn't a good example, I completely made it up without thinking. In original code, I wanted to advance the counter along with assigning value to a variable. Which does work, if I create function
Code: Pascal  [Select][+][-]
  1. function increment(i : integer) : integer;
  2. begin
  3. i:=i+1;
  4. end

Except that the result of that function is undefined. I think that you're assuming that it is all-1s, to the size defined by x which is not known when the function is evaluated.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 5809
Re: ways to avoid begin-end’s?
« Reply #19 on: May 09, 2024, 11:08:33 am »
if someone is really bent on not having to use "begin" "end" then code everything as functions. That allows begin/end free coding such as:
Code: Pascal  [Select][+][-]
  1. f1 and f2 and f3 and f4 and... ... fn;
or essentially the same:
Code: Pascal  [Select][+][-]
  1. if not(f1 and f2 and f3 and f4 and... ... fn) then ReportThereWasAnError();

Personally, I very often do the opposite in my code, i.e, even if the statement can be coded without begin/end, I still code it with begin/end because it helps in testing and debugging (particularly in stopping execution), e.g:
Code: Pascal  [Select][+][-]
  1. if <somecondition> then
  2. begin
  3.   <a statement>
  4. end;
  5.  
That allows setting a breakpoint which is triggered only if <a statement> is reached.  if that statement was on the same line as the "if" itself then the value of the condition would not yet be known.

It also allows for easier testing of the execution path where <somecondition> is true.  To test that code simply add a ";" after the then, the code becomes:
Code: Pascal  [Select][+][-]
  1. if <somecondition> then ;
  2. begin
  3.   <a statement>
  4. end;
  5.  
which means <a statement> will be executed which allows the programmer to ensure it works as intented.    Note that the presence of the ";" can be dependent on defining a conditional directive, which is a convenient way of ensuring all code paths are tested (as they should be.)  Long live "begin" "end" (very useful) :)

The use of begin/end and conditional directives allows for code where the testing of every possible execution path is easy to perform.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Weiss

  • Full Member
  • ***
  • Posts: 219
Re: ways to avoid begin-end’s?
« Reply #20 on: May 09, 2024, 11:22:26 am »
actually, any bitwise operation would do the same thing, or xor not, shl etc.  I tried a few. Except "AND" is more readable, it kind of suggests addendum.

>> is cool too.

Code: Pascal  [Select][+][-]
  1. if X=a then X:=1  >>  increment(i);

Gentlemen, I totally understand that this is an unintended use of bitwise operators, that function returns no value and therefore value of X is not affected and solely side effect of function is used. It is a bona fide syntactic abuse, in a context of by-passing begin-end encapsulation.


MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: ways to avoid begin-end’s?
« Reply #21 on: May 09, 2024, 11:35:43 am »
actually, any bitwise operation would do the same thing, or xor not, shl etc.  I tried a few. Except "AND" is more readable, it kind of suggests addendum.

>> is cool too.

Code: Pascal  [Select][+][-]
  1. if X=a then X:=1  >>  increment(i);

Gentlemen, I totally understand that this is an unintended use of bitwise operators, that function returns no value and therefore value of X is not affected and solely side effect of function is used. It is a bona fide syntactic abuse, in a context of by-passing begin-end encapsulation.

The value of x WILL be affected: it will be ANDed (or whatever) with whatever rubbish the increment() function returns since the result is unassigned.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

alpine

  • Hero Member
  • *****
  • Posts: 1410
Re: ways to avoid begin-end’s?
« Reply #22 on: May 09, 2024, 11:37:45 am »
actually, any bitwise operation would do the same thing, or xor not, shl etc.  I tried a few. Except "AND" is more readable, it kind of suggests addendum.

>> is cool too.

Code: Pascal  [Select][+][-]
  1. if X=a then X:=1  >>  increment(i);

Gentlemen, I totally understand that this is an unintended use of bitwise operators, that function returns no value and therefore value of X is not affected and solely side effect of function is used. It is a bona fide syntactic abuse, in a context of by-passing begin-end encapsulation.
This just can't be true!

The neutral operand for AND is all-ones, but for >> (perhaps shr) is a zero. The function has a result, most probably the incidental value of the AX register. It can't be all-ones and all-zeros in the same time.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Weiss

  • Full Member
  • ***
  • Posts: 219
Re: ways to avoid begin-end’s?
« Reply #23 on: May 09, 2024, 11:39:42 am »
If it works it is a pure chance.

You are right. It doesn't. I forgot to check the value of X after bitwising it. Side effect of function works, whatever I make it do, it does. But value of X becomes "0" if I bitwise X with result of function that returns no value. End of story.

Weiss

  • Full Member
  • ***
  • Posts: 219
Re: ways to avoid begin-end’s?
« Reply #24 on: May 09, 2024, 11:44:49 am »
actually, also not true what I jsut said. They all return different value of X, from 658 to exit with code 201.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: ways to avoid begin-end’s?
« Reply #25 on: May 09, 2024, 11:49:34 am »
if someone is really bent on not having to use "begin" "end" then code everything as functions. That allows begin/end free coding such as:
Code: Pascal  [Select][+][-]
  1. f1 and f2 and f3 and f4 and... ... fn;
or essentially the same:
Code: Pascal  [Select][+][-]
  1. if not(f1 and f2 and f3 and f4 and... ... fn) then ReportThereWasAnError();

That reminds me of some stuff in a book that I'm currently working through. It defined a unification function for Prolog-like programming something like

Code: Pascal  [Select][+][-]
  1. function unify(var p1, p2: pointer): boolean;
  2.  
  3. begin
  4.   if p1 = nil and p2 <> nil then
  5.     p1 := p2;
  6.    if p2 = nil and p1 <> nil then
  7.     p2 := p1;
  8.   result := p1 <> nil and p2 <> nil
  9. end;
  10.  

The original, in a language more C-like than Pascal, did of course have an operator for this with the result propagated via chained assignment. But with the many problems that chained assignment entails, I think I prefer an explicit function particularly if it is simple enough to be inlined.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Weiss

  • Full Member
  • ***
  • Posts: 219
Re: ways to avoid begin-end’s?
« Reply #26 on: May 09, 2024, 12:41:23 pm »
ok, one more thing and we can close this topic. It was a long night shift.

If I bitwise-AND X with function result -1, then value of X is not affected. Providing X is either integer, or real number which has no fractional part.

Code: Pascal  [Select][+][-]
  1. program AlsoProgram;
  2.  
  3. var
  4.  
  5.   i : integer;
  6.   x: real;
  7.  
  8. function increment(var i : integer) : integer;
  9. begin
  10.    i:=i+1;
  11.    increment := -1;
  12. end;
  13.  
  14. begin
  15.    x:=1;
  16.    i:=1;
  17.    if x=1 then x:=5 and increment(i)
  18.    else writeln('we will never get here');
  19.    writeln(' x = ', X, '    i = ', i);
  20.  
  21. readln;
  22.  
  23.  
  24. end.
  25.  

produce result     
Code: Pascal  [Select][+][-]
  1. X:=5,  i:=2

after all, with a lot of ifs and buts, it can be done.

Thaddy

  • Hero Member
  • *****
  • Posts: 18321
  • Here stood a man who saw the Elbe and jumped it.
Re: ways to avoid begin-end’s?
« Reply #27 on: May 09, 2024, 01:02:31 pm »
if someone is really bent on not having to use "begin" "end" then code everything as functions.
That's how much of KOL is designed: function chaining. Actually this is quite a common pattern.
That does not mean it is always a good pattern, btw.
« Last Edit: May 09, 2024, 01:04:05 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: ways to avoid begin-end’s?
« Reply #28 on: May 09, 2024, 02:06:42 pm »
If I bitwise-AND X with function result -1, then value of X is not affected. Providing X is either integer, or real number which has no fractional part.

Not a safe assumption, since the function isn't in control of the types expected by the AND operator so can't predict how the sign (MSB) is extended.

If you write "clever" code like that it will come back to bite you. It will also make you very unpopular with anybody else who subsequently has to review or debug it.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

alpine

  • Hero Member
  • *****
  • Posts: 1410
Re: ways to avoid begin-end’s?
« Reply #29 on: May 09, 2024, 04:33:16 pm »
ok, one more thing and we can close this topic. It was a long night shift.

If I bitwise-AND X with function result -1, then value of X is not affected. Providing X is either integer, or real number which has no fractional part.
Code: Pascal  [Select][+][-]
  1.     if X=a then X:=1  >>  increment(i);
Apparently your programming knowledge starts with C/C++. You so wrongly interpreted the assignment statement with the C assignment operator , which is defined to have a result. The pascal statement does not have a result. Furthermore, even the C/C++ assignment operator have a very low priority, lower than almost every other operator. It will be executed after the shift, and, or whatever is the right-hand operator.

And you should better bet on the 'OR with 0' operator instead of 'AND with -1' just because zero is the only constant compatible with most of the types.

In Pascal there is no 'empty value', neither in C. Not assigning a value to a function result, doesn't mean it will be 'empty value'. BTW FPC always gives a warnings about this.

The only viable way to combine several function invocations without begin/end was given in reply #19 by bx440. But also care must be taken because of the short-circuit evaluation of the logical operators.

If you miss the post-increment operator, you can just define:
Code: Pascal  [Select][+][-]
  1. function PostInc(var I: Integer; AInc: Integer = 1): Integer;
  2. begin
  3.   Result := I;
  4.   I := I + AInc;
  5. end;
then:
Code: Pascal  [Select][+][-]
  1.   A[PostInc(I)] := B[PostInc(J)]; // A[I++] = B[J++]


"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

 

TinyPortal © 2005-2018