Instr <> IndexOf

The bug has been fixed for the next version. It might be a good idea to actually test the bug fix.

1 Like

This speed issue is fixed in the latest beta.

i wish we get a string0 string1 type & class.

FWW I did test this and the speed is now the same (Instr = IndexOf)

1 Like

I never had any trouble remembering that string functions are 1-based and arrays are 0-based. Another instance of Xojo fixing something that wasn’t broken for the sake of some kind of abstract purity, at the expense of users.

3 Likes

I disagree with you on this. The 0-based consistency makes programming much more straightforward.

Here’s another thread where we derailed a little bit and got into a discussion about 1-vs-0:

2 Likes

Yes true, but changing it, for consistency sake, in API2 can break a lot of code, trust me. It’s ok-ish for simple code, but with complex code it is very troublesome to convert to IndexOf.

Yes, but that’s not a good reason. It’s a good reason not to change InStr, but a bad reason to make IndexOf 1-based. IndexOf is a new function. I can’t say it has no legacy attached to it, but there is very little.

I went through all this. Took me about a weekend to convert my project. Yes, InStr to IndexOf is an area that needs special attention. But I found my code simpler to read as a result. It’s a good change despite the growing pains.

3 Likes

I agree. It even made sense to me that way, after being accustomed. Changing them to 0-based is like if I had tried another language; both are pains.

Remembering that InStr is 1-based is the easy part. How it works with similar methods is what makes its response tricky. Tim posted my reasoning, so I’m not going to recap. It’s mentally easier to do Haystack.Left(Haystack.IndexOf(Needle)) than Left(Haystack, InStr(Haystack, Needle) - 1). This is a basic example, but with more complexity, the need to counter offsets is very taxing. Even now, I’m doubting wether or not I got the API1 version of the code correct.

i guess new api2 throw an error for everything like methods in c#.
as example left 100 with a 80 char string fail.
it is not just replace and care about 0 or 1 index.
you have to care about it behave too.

Yeah, that’s true. I wish it didn’t fire an exception, but it makes sense.

Nope. Some methods have default behaviors (docs should reflect it) like, in left() when count > number of chars it assumes number of chars and don’t raise exceptions.

1 Like

That’s terrible. Just give me all the characters you can, don’t throw an exception!!!

1 Like

An argument could be made for either behavior. Your implementation might not behave gracefully if you didn’t get the number of characters you intended. One could argue that if this is important, you could write code to handle that. One could argue that a database error or filesystem error is something that must be handled, whereas an incorrect number of characters returned may not even be an error.

I don’t feel strongly about the issue one way or another. I think I’d prefer it not to throw an exception, but I’m not complaining that it does.

Coming from C#, VB.NET, and JavaScript, I would have found this an incredibly annoying inconsistency, and I think that would be true of most any other language I’m aware of other than maybe VB6 and VBScript, and IIRC those were consistently 1-based by default. I remember reorienting myself to 0-based everything when we made the transition from classic ASP to ASP.NET and the .NET framework generally, and I found it a fairly easy transition because it was consistent.

Yes, one can become inured to a mix of 0 and 1-based framework (and just about anything else!), but it was ultimately just another excuse for language snobs to snub Xojo on the scientific grounds that it’s weird. Maybe cleaning up a few things (and with a lot less breaking changes, than, say, the transition from Python 2 to Python 3) will boost Xojo’s market share a couple of points. Which, sadly, means maybe it will double or triple it, lol.

Agreed.

Amusingly, VB.NET has a namespace full of VB6 compatibility functions that no one has used in at least a decade. Our corporate style guide wanted us to not use those, but to make the same framework calls you would use in any other .NET language. Otherwise C# coders who don’t know VB.NET would find it much harder to understand what our code was doing. So it was, e.g., Convert.ToDateTime() rather than CDate(), etc. And yes, String.IndexOf() rather than Instr().

I will confess though that on the other side of the coin, Microsoft has a damned annoying habit of introducing some functionality that is supposed to be the Second Coming and then four or five years later when it’s well-cemented into your code base, declaring it Old and Lousy and introducing something New and Improved. A good example was .NET Remoting, which gave way to Windows Communication Framework, which gave way to … well, you get the picture. .NET Core itself, and .NET 5+, seemed to be rearranging namespaces just to break things, when it came to their web framework. This is, in fact part of the reason for my interest in Xojo.

So I’m not unsympathetic to the concerns about API 2. Doing something like this every 10 or 20 years is arguably necessary. Doing it every every 3 or 4, not so much. Making up your mind is a feature, too. I regard this API2 less as dithering than clearing out cruft and inconsistency.

Again, throwing an exception is pretty universal these days. Many would argue that sweeping errors under the rug hides bugs, subtle and otherwise.

IDK about Xojo offhand but in .NET you can do Substring(startPos) without the length and it will just give you the rest of the string, if that’s what you actually want. Or you can write a wrapper or extension method that behaves how you want it to. But IMO you should have to deliberately ask for such things.

C# Substring throws range exceptions while Xojo equivalent Middle() assumes default behaviors:

C#

using System;
					
public class Program
{
	public static void Main()
	{
		string s = "123";
		Console.WriteLine("Result [" + s.Substring(4) + "]");
	}
}

Run-time exception (line 8): startIndex cannot be larger than length of string.
Parameter name: startIndex

Stack Trace:

[System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string.
Parameter name: startIndex]
   at System.String.Substring(Int32 startIndex, Int32 length)
   at System.String.Substring(Int32 startIndex)
   at Program.Main() :line 8

XOJO

Var s As String = "123"
System.DebugLog "Result [" + s.Middle(4) + "]"

Result

Anyone want to wager whether the “fix” for this was to essentially do what @anon20074439 suggested in the 3rd post of this thread… except it’s called IndexOf, and uses Instr internally?