Jump to content
John Kouraklis

Difference between Pred and -1

Recommended Posts

Hi,

I am looking at some older code and I see the author uses the following statement:

 

for i:=0 to Pred(WhateverList.count) do

 

instead of the usual one:

 

for i:=0 to WhateverList.count - 1 do

 

Does it make any real difference or it's just a personal preference?

 

Thanks

  • Like 1

Share this post


Link to post

In that code statement it does not matter if Pred() or attached -1 will be used. Both do same but Pred() can do more than give back decremented number.

 

Those types are supported:

Characters, Non-floating number types, Enumeration types and Pointers 

 

Example:

Character := Pred( Char( 'X' ) ); = W

 

/edit

It might be possible that on mass operations a -1 is faster than using Pred().

Not tested by myself but possible.

(not for above example, when used inside loops)

Edited by KodeZwerg

Share this post


Link to post
On 12/3/2018 at 5:03 PM, John Kouraklis said:

for i:=0 to Pred(WhateverList.count) do

I just saw noticed this (or recognized what it is) in sample code, for the first time! Pretty cool, can replace StringList.Count - 1, like High(Array) replaces Length(Array) - 1.

 

@John Kouraklis let's see what else I can figure out a 1.5 years later than you 🙂

  • Haha 1

Share this post


Link to post

Pred and Succ best use is when used with enum.

LBrushKind := Pred(LBrushKind);

replace

LBrushKind := TBrushKind(Ord(LBrushKind)-1);

  • Like 3

Share this post


Link to post
5 hours ago, Mike Torrettinni said:

You don't use Pred(List.Count), you don't think is useful?

No. It's pointless verbiage. Use List.Count - 1

 

  • Like 1

Share this post


Link to post

I would like to have List.High or List.HighIndex or List.LastIndex or whatever.

Why to write every time -1 when you want the last index?

  • Like 2

Share this post


Link to post

I only use Pred rarely with enums. With integers it's worse than N-1.

21 minutes ago, Cristian Peța said:

I would like to have List.High or List.HighIndex or List.LastIndex or whatever.

Why to write every time -1 when you want the last index?

I guess having for-in construction there's not much need in last index

  • Like 2

Share this post


Link to post
11 hours ago, Mike Torrettinni said:

You don't use Pred(List.Count), you don't think is useful?

I notice you didn't answer the question, but no; It makes the code harder to read as you have to think about what Pred does. With "Count-1" there's no doubt.

 

Don't use a feature just because it's new or you've just discovered it.

  • Like 2

Share this post


Link to post
5 hours ago, Cristian Peța said:

I would like to have List.High or List.HighIndex or List.LastIndex or whatever.

Why to write every time -1 when you want the last index?

You can add an extension method if you wish to do that using a class helper.  (Low as well).

Share this post


Link to post
1 hour ago, Anders Melander said:

It makes the code harder to read as you have to think about what Pred does. With "Count-1" there's no doubt.

Well, I have different experience. For a long time i didn't know about High(Array) and dealing with a lot of arrays, i had occasions forgetting -1 in Length(Array) -1, so High(Array) is, for me, excellent replacement.

Edited by Mike Torrettinni
softer tone of words.

Share this post


Link to post

High is fine for an array. Pred is a stupid way to write Count - 1. I mean, you aren't proposing writing Pred(Length(arr)) are you. 

  • Like 1

Share this post


Link to post

I use High with Arrays, Pred I saw in example with List.Count example. I see High used with Arrays very often, but not every body is using it, of course. Years ago I had a custom checker that would check for Length(Array) that is missing -1... lot's of fun, before I started using High 🙂

Share this post


Link to post
15 hours ago, Fr0sT.Brutal said:

I guess having for-in construction there's not much need in last index

I only rarely use for-in, perhaps I should try using it more often. I only use it for enums, I never thought you can use it for TList, even though it makes sense. Good thread @John Kouraklis , good ideas coming out of this! 🙂

  • Like 1
  • Thanks 1

Share this post


Link to post
8 hours ago, Mike Torrettinni said:

I only rarely use for-in, perhaps I should try using it more often. I only use it for enums, I never thought you can use it for TList, even though it makes sense

The coolest thing about for-in is that you can implement it for any custom class or record by implementing an iterator. So, f.ex., you can have `for jsonval in JSONDoc.Values['somearray']`. For-in works for strings as well iterating by chars though I personally haven't used it in such way.

And it's a bit slower so for time-critical routines usual `for` still remains actual (though for very super time-critical things pointer increasing could beat `for` anyway)

  • Like 2

Share this post


Link to post
27 minutes ago, Fr0sT.Brutal said:

(though for very super time-critical things pointer increasing could beat `for` anyway)

It depends. Sometimes indexed access is faster.

Share this post


Link to post

I also use for..in all the time.

 

Don't forget though that in for loops you can not modify the iteration variable. So, if you have a TStringList, this code does not compile:

 

for item in list do
  item:=item + '123';

In such cases, iterating through the items via index is the only option

 

    for num := 0 to list.Count - 1 do
      list[num]:=list[num] + '123';

 

Share this post


Link to post
1 minute ago, John Kouraklis said:

I also use for..in all the time.

 

Don't forget though that in for loops you can not modify the iteration variable. So, if you have a TStringList, this code does not compile:

 


for item in list do
  item:=item + '123';

In such cases, iterating through the items via index is the only option

 


    for num := 0 to list.Count - 1 do
      list[num]:=list[num] + '123';

 

 

You mean this, right? :

 

    for num := 0 to Pred(list.Count) do
      list[num]:=list[num] + '123';

🙂

  • Haha 1

Share this post


Link to post
8 hours ago, Anders Melander said:

It depends

That's why I said "could".  😉

Edited by Fr0sT.Brutal

Share this post


Link to post
9 hours ago, Anders Melander said:

It depends. Sometimes indexed access is faster.

For an array indexed access is usually fastest. 

 

Delphi RTL enumerators are often sub optimal. I mean, heap allocation to iterate a collection ffs. 

Share this post


Link to post

off-by-one errors are the bane of most programmers' existence. I eventually learned to look for "... 0 to ... -1" or "... 1 to ... <x>" where "x" does not contain a '-1'

 

The use of pred() in place of '-1' is inconsistent at best, and rarely used, so it much harder to detect quickly when it's not used appropriately.

 

Wirth threw it into the language as a pedagogical tool. That was nice, but it's impractical.

 

The 'for ... in' approach is far less likely to lead to such errors.

 

The use of 'Low(x) to High(x)' is even less error-prone than '0 to ...-1' IMO.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×