Operator_Lookup

In code I’ve been writing I’ve found a need to be able to “add properties” – but not in a conventional way.

Normally I’d just add a property to some class in my Xojo code and be off & running. But now I’m needing to be able to define “classes” (They’re not really classes) in a way that they can be added EVEN AFTER the application has been compiled.

So this means I need to be able to added to a text file, that gets read, and a new “property” is available on the “class”. Admittedly a very unusual need.

But this IS possible.

There is a little used method that any class can use to make it so the compiler can “lookup” something that is not defined in the conventional ways. That method is _operator_lookup_. By adding this method to a class the compiler will call it to lookup any “name” on a class that it cannot find using its normal mechanisms. Note that this WILL make it so you no longer get compilation errors. So IF you use operator_lookup you need to make sure you have a means to debug any errors (like a break statement or something in you implementation to catch any typo’s)

With those warnings out of the way how can you make use of this ?

In normal code you might never need to.

However, if you suppose you have a class that is dynamically configured and used like the following :

for each configProperty in classInstance.Configuration
    // now use this property in some generic way 
    // maybe like an inspector that can edit anything 
    inspector.EditProperty configProperty
next

Then its possible you can add a configuration property that can be manipulated in a generic way and you DO NOT know all of them ahead of time.

Operator_Lookup lets you deal with this.

And it can be both a GETTER and a SETTER.

You’ll find some sample code in a series of posts I made about this topic

API 2 speed hit

I’ve seen others comment that they’ve run into slow downs with API 2.

I’ve been trying to sqeeze every last ounce from a large app and ran into this one. I’d suspected it might be a hit but measuring it indeed shows there is a hit – not tens of seconds but when you want EVERY last microsecond these few add up.

My test code is the following

Const kNumberOfIterations = 1000000

Dim startTime As Double
Dim endTime As Double

startTime = System.Microseconds

For i As Integer = 0 To kNumberOfIterations
  
  Dim s As String = Trim( "abc" + Str(i) + "def" )
  
Next

endTime = System.Microseconds
System.debuglog " elapsed 1 = " + Str(endTime - startTime, "###########0")

startTime = System.Microseconds

For i As Integer = 0 To kNumberOfIterations
  
  Dim tmp As String = "abc" + Str(i) + "def"
  Dim s As String = tmp.Trim()
  
Next

endTime = System.Microseconds
System.debuglog " elapsed 2 = " + Str(endTime - startTime, "###########0")

Pretty simple operations but when I run this compiled with default optimization (aggressive doesnt work in the app I’m building for reasons I have yet to discern) I get the following results

Feb 11 22:22:52  My Application[46161] <Warning>:  elapsed 1 = 557024
Feb 11 22:22:52  My Application[46161] <Warning>:  elapsed 2 = 573987

A different of roughly 20,000 microseconds (2 msec)

In a small app that I can compile as aggressive this difference shrinks – but as I noted I cant use aggressive with my app yet.

That API forces you to create & use more temporary variables can have an impact. Sticking with the API 1 equivalent _may_ save you time.

More old things relearned recently

I know this was posted about years and years ago. Its probably been a decade or more since this was last written about.

But I ran into it again and had to say to myself “Oh right you cant do this this way because the App method will return nil at this point”

The situation is I wanted to put a custom menu item subclass into the menu bar. This works. You can add the item and change its super and all your constructors etc will get called. But if you need to refer to “the application” then there are times when it will NOT work. Like if the item you added is part of the default menu bar created when the application starts up.

At that point the global App method can and may return NIL because the default menubar is created BEFORE the application singleton is registered in a way the App method can return it.

So IF you need to do something like this and need to refer to “App” then you may need a flag that delays this initialization until some time after the app has started up and you CAN get a valid reference to the singleton.

Heads up !

Convert To or Convert From ?

A while back I started thinking that some of the new style Xojo is using is awkward but it never really struck me why it felt that way.

After working with new releases for a while I know what I find strange.

Sometimes you tell an instance to do something.

var someInteger as Integer
var s as string
s = someInteger.ToString

for instance tells out integer instance someInteger to convert itself to a string. THe style is very much object verb.

Except when its not

var someStringArray() as String
var s as string
s = someStringArray.ToString // NOPE - this does not compile

No in this case we do not tell our “object” , the array, to convert itself to a string like we do many other things. In this case we have to tell the String “type” to make a string From an Array

Var someStringArray() As String
s = String.FromArray(someStringArray)

Yet there are many other places where ToString does exist. Here’s a handful in the Language reference.

Thats not to say the “From type” conversion doesnt make sense. There are lots of places it does. For things that have constructors i makes sense that the “convert from” method might be a constructor, or maybe a shared factory method that returns a new fully created instance. Or maybe its the operator_convert initializer that can return a fully constructed instance. I had a long discussion with Aaron about whether a constructor vs factory vs operator_convert makes more sense and there are some interesting considerations he brought up but I wont go into those details here. Maybe another post another day.

For intrinsic non-reference types like Integer, string, boolean etc where there is no means to use a constructor the choices are really limited. But even in that case we see that things like booleans, integers, colors etc have both a ToString and FromString – something arrays do not have.

That seems particularly inconsistent with all the efforts Xojo is going to to make the language more consistent.

And now I know why I find it jarring that its missing for arrays to be able to tell them to convert To String.

Later !

Lying to the compiler .. and why it doesnt matter

If you’re like some coders you like to have “clean” compiles

No warnings. No errors. Nothing.

So when a new one does popup you can inspect it, fix it, and return to a pristine state. Its one way to make sure new issues dont crop up very earliy in your work cycle.

Often you get a lot of “Unused event parameter” or “Unused method parameter” warnings.

And it can be tedious to go back and insert a pile of #Pragma Unused for each one.

But did you know that you could just write those pragmas right at the outset and tell the compiler that every parameter will be unused ? And that it really wont matter ?

Suppose you write a new method like

Sub foo( bar as integer, baz as color, foobar as string)
End Sub

If you now do a check project you will get warnings that the parameters are unused

So if you dutifully enter

#Pragma unused bar
#Pragma unused baz
#Pragma unused foobar

and redo your check and things are clean again. Now, what if you alter the code to actually use one of those parameters ? Do you need to remove the #pragma ? Doesn’t that #pragma flag the variable as “unused” in a way the compiler will now complain about you saying it was unused but you’ve now gone & used it ?

In fact the answer is no – what that pragma does is mark that variable as USED so the compiler will stop complaining about it being unused. (Cute isnt it ?)

You can leave those pragmas in place and use the variable and NOT mess up anything.

So you might consider writing the pragmas at the time you implement the event or method and never get warnings about unused parameters ever again 🙂

Or just turn those warnings off 🙂

Enjoy !

Lessons I relearned today

  1. find the bug
  2. write a test to show the bug
  3. write the code to fix the bug

I’d made some changes to a client project and while I wasnt specifically fixing a bug I did alter a behaviour that resulted in one.

Turns out I didnt have a test already in place to reveal this change and that cost me a couple hours to track down, write the test, and fix the bug I’d caused.

Having a huge test suite built in (there are nearly 1500 unit tests for this code at present) has helped make sure that changes dont cause bugs.

And the new ones will make sure they dont reappear

Test early. Test often

Stay sane !

Load a file in reverse

From https://forum.xojo.com/t/load-text-file-in-reverse/60911

Simply read the file from beginning to end and instead of always appending lines always INSERT the line just read at the front of the listbox.

t = f.OpenAsTextFile // open selected text file
While Not t.EndOfFile
 x = t.ReadLine
  lstHistory.AddRowAt(0, x)
Wend
t.Close

and the list will appear “reversed” as if you read from the end back to the beginning

Only sort of the right place to put things

SpecialFolder.ApplicationData initially seems a great place to store your applications runtime data. But its only sort of the right place to put things

In reality its the right place for ALL applications to put their data. And becuase many applications can and do put their data there a good habit to get into is to create a DIRECTORY, or folder, specifically for YOUR application to put its things in rather than just toss all of the bits you might want to save in SpecialFolder.ApplicationData (and hope no other app saves over it, erases it, alters it, etc)

There are several ways to accomplish creating a directory for your application and it will depend on what OS your on as to which is “more correct”.

One macOS it might be a good thing to use your applications bundle ID for the name of the directory.
One Windows, while you can use that same string it might be nicer to use the actual name of the application
I’m not 100% sure of what the correct convention is for Linux but you may want to create it as one with the name starting with a period so its hidden by default.

Tim Parnell has a nice module for making some of this really simple to do.

Your users will appreciate it

Compiler issues I’ve reported

Over the past years iv’e reported a few compiler issues

Here’s the current list of open issues I’ve reported

55502 adding a constant to a class cant use an expression while one in code can
56376 compiler misidentifies syntax error on shared factory in super class
56378 factory pattern cant be implemented properly in Xojo esp when items are in a namespace
56765 compiler weird error message seems to be linked to wrong order of evaluation
57500 debugging a while loop in debugger appears to skip entire loop
58900 compiler incorrectly identifies unused local variables
59004 endexception constructor should probably be restricted in some fashion
59061 compiler gives a very ambiguous error message on select case statement
61901 compiler reports completely bogus error
61949 xojo does not warn of conversion on assignment
63438 compiler gets comparison confused with assignment
56264 make it so when a method returns an array you can immediately index into the return result
56272 optional parameters can only be “right most” parameters
60207 command line arguments for debug run cannot use a #constant

And there two I would love to see Xojo fix as its impossible for the usage to be ambiguous

56375 compiler incorrectly identifies “global” as syntax error
In something like an enumeration its impossible for the tokens for Global, Protected, Private and Public to be ambiguous.
An enumeration is written as

Enum myenumeration
   value
   value
End Enum   

And even if the Enum is scoped as private its , at worst, written as.

Private Enum myenumeration
   value
   value
End Enum  

It would be simiar for Public, Private and Global. No one of those value lines can be mistaken for the scope of anything else.

56411 compiler misidentifies “attributes” as syntax error in spots where it cannot be ambiguous

Attributes is handled similarly to the above case for scope. And has the same impossible to be ambiguous situation.

Both of these cases are most definitely fixable but so far Xojo has declined to do so.

Out of my list iof just compiler bugs
– 1 has been fixed
– 2 closed as By Design (noted above)
– 1 closed as Not Reproducible (and I have no idea how to reproduce it either)
– 11 are Reproducible
– 3 feature requests Reviewed

A single set of libraries

This was asked on the Xojo forum

If the applications are developed by the same Xojo version, and all the exe files of several applications are placed in the same folder, is it possible for distribution purposes to have only one Libs folder ? In such case, which would be the name of this unique Lib folder ?

There are some caveats that havent been mentioned

You DO need to recompile everything using the same version of Xojo. That way the Xojo framework, and supporting plugins libraries are all the same version.

The other thing you do need to be careful about is they need to all be the same kind of applications. You cant properly combine the libs for a desktop app and a console app into just one set as the XojoFramework for desktop and Console are not the same.

Nor are the libraries from various plugins used.

So be careful about how you do this.