I’m taking a break from posting.
Disillusioned am I.
I’m taking a break from posting.
I’m taking a break from posting.
Disillusioned am I.
So what the heck is Norm on about NOW ?
Properties. Specifically computed properties.
Normally you dont want to be shadowing properties and if you do you need to be careful about how you do it so it doesn’t muck up everything. But even when you DO shadow “right” there can still be issues.
And the reason this comes up is because the DECLARED type of an item may be REALLY relevant.
For instance if you have
Class Item property Foo as Integer End Class Class subItem Inherits Item Computed Property Foo as integer Get as Integer break return Item(self).Foo End Get Set(value as integer) break Item(self).Foo = value End Set End Computed Property End Class
This can lead to a messy situation.
If you try something like
Dim c As Item c = New Item c.foo = 129 // sets Foo directly and never hits a breakpoint in the computed c = New Subitem c.foo = 9
You will not get ANY complaints from the compiler
The local we declared, c, can hold a reference to an Item OR any of its subclasses – since any of its subclasses IS also the super type (thats how inheritance works)
But with properties the DECLARED type matters. Although the debugger knows that, at the end c holds a reference to one of the SubTypes, the PROPERTIES that are accessed are those of the SUPER class in this case (actually what would be correct to say is the properties of the declared type)
And so, because despite a computed property being a lot like a pair of methods, its not treated the same. For instance, if the code above is altered to
Class Item Public Sub Foo() as Integer break return privateFoo End Sub Public Sub Foo(assigns v as Integer) Break privateFoo = v End Sub Private property privateFoo as integer End Class Class subItem Inherits Item Public Sub Foo() as Integer break return super.Foo End Sub Public Sub Foo(assigns v as Integer) Break super.Foo = v End Sub End Class
with the same code trying to set and get the value
Dim c As Item c = New Item c.foo = 129 // sets Foo directly and never hits a breakpoint in the computed c = New SubItem c.foo = 9
You’ll see a vast different. This time the RUNTIME type matters and the code in the subclass methods DOES get called.
This is because methods, unlike properties, do use dynamic or virtual dispatch (the names get used interchangeably quite frequently) But properties do NOT. so whatever declared type a local or parameter is matters as to which property you might actually be accessing.
Sometimes this is where you need to cast (which kind of breaks the whole idea of using OO anyways since now you end up with big select case statements to handle many supers & subclasses)
IF subclasses computed properties could be handled using the same dynamic dispatch mechanism that methods use it would make it possible to put properties in the inspector behaviour AND have subclass properties overload the super class ones.
Right now you have to pick between one or the other since computed properties can be in the Inspector Behaviour but arent virtual, or you use method pairs which ARE virtual but cant be exposed in the Inspector Behaviour.
Its crummy to have to make this choice at all.
I’ve had several people tell me they are “stepping away from Xojo” at the moment.
Most are users with many years experience in Xojo.
It’s disappointing that its come to this.
Anyone else had this said to them or doing this ?
In the IDE you can create constants.
And if you create them as string constants you can set them to be “localized” or not.
This gives you the ability to support multiple different languages in a single build as the localized language files will be saved and used by your application.
But what happens to other kinds of constants if you add different instance values to ? What does the IDE do with those ? And how does it use those ?
Create a new desktop project. Add a new number constant, kWindowMin. Then add set a new instance value for MacOS ANY LANGUAGE and make the value 500. Add another instance for Windows ANY LANGUAGE and make the value 700.
Set the Window1 Width to #kWindowMin
And notice what it does on macOS (or Windows) immediately. Then run it on macOS and Windows.
Note that this is NOT a value looked up at runtime. It’s not determined at runtime like a dynamic language constant is. With a dynamic constant you can change the system language, run and if there is a localization for that language it will show that localization. Stop the app, switch languages and run again and the new language should show.
This kind of constant is looked up in a platform specific way at COMPILE / BUILD time.
Its set AT COMPILE TIME and never again.
They can be handy because in some situations you need a larger window or field size because the default localized values for a language are longer (German tends to be this way compared to English)
And since you can use it for all kinds of values including integers yiu could use it for colors and have a different set of colors you use for macOS or Windows quite easily.
And you can use Booleans. So with settings for transparency its fairly easy to set up one value for macOS to be TRUE – since it supports transparency very nicely – and FALSE for Windows. Then you can assign that constant to those Windows & controls TRANSPARENT property and easily switch between macOS having transparency on and Windows having it off.
And how they work …..
In a bug report I made I posted a tiny sample of code
Dim tokens() As String Select Case True Case tokens.ubound < 0 Case tokens(0) = "End" Case "Dim" break End Select
(Not this code has a known bug in it – Case “Dim” is wrong but it illustrated the bug I was reporting) I’ve used this style for very long sections of code esp where I dont want to clutter it up with extraneous “if then” or “elseif”
But it gathered a curious comment that convinced me the writer of that comment isnt certain how SELECT CASE works. The comment was
I see no sense in the line „Select Case True“, since True is always True. So the error message points in the right direction, correcting this line.
While I understand the reasoning it also happens to illustrate the misunderstanding of how select case works.
The statement that follows select case is known as the Test Expression.
Xojo will then evaluate each case expression and find the first one that matches that Test Expression.
In the case of the code above it will find the first one that has a case expression that is true
It behaves as if the code was written as
if true = (tokens.ubound < 0) then elseif true (tokens(0) = "End") then elseif true = ( "Dim" ) then end
This sample replicates the same bug as the original BUT this time the compiler correctly complains about the comparison between TRUE and “DIM” (which is what my bug report was about originally)
Select case can be a very handy way to declutter code and remove a lot of “if then” and “elseif then” from your code.
But only if you know how it works.
Should be a great WWE match up
Really the question was “should I use a class or a module?”
There’s not really global “Oh always use X” answer here.
But usually if you find yourself wiring code that passed data to a method and you have a group of methods that collectively define a “data type” then you probably want a class.
What do I mean by that ?
Suppose you create a structure and put it in a module. And then that module has all kinds of methods that perform some kind of operations on that structure. That really probably _should_ be a class and all the methods in that module methods in the class.
Modules, or namespaces, arent as a mechanism to define a data type. This kind of style is very classical non-OOP design.
There _may_ still be reasons you want to use this style though. Yoi might use it when the data you’re dealing with is used for a declare or other external API and so your choices ARE limited by what declares can accept. There _may_ be other ways to deal with this situation but it wouldn’t be the worst choice to use a namespace in such a case.
Sometimes when you want to subclass a control you want to retain the property name the Xojo control uses, but you want to add some custom functionality by putting a computed property in place in your subclass.
In the long run this makes your subclass a better drop in replacement. You dont end up with the case where the superclass has a property named one thing, like Text, and your subclass has a similar property named something else, like Caption.
For some properties the IDE will prevent you from doing this at all. Basically IF the property you want to do this with is named TEXT you cant create a subclass with a computed property named TEXT because the IDE will stop you – TEXT is a data type and Xojo will stop you from using that name since TEXT is a data type.
Most times you’re stuck.
Notice I say “most times”
There ARE ways to make this work – but it involves working AROUND the IDE outside of the IDE. And it can be “fragile” – if you do anything that would alter the signature in the IDE it will fix it for you then you have to redo things.
When I have wanted to do this I will name my property something memorable – often “Caption” or something mostly suitable but still not the name I really want.
Then I save as text (xml would also work since its mostly plain text). Then I open my project in a text editor like BBEdit & I find the item I named “Caption” and rename it “Text”. Save the edited text and now get the IDE to reload the project.
And there’s my property named “Text” as I expect and I can then also edit and fix any code in the getter & setter and the IDE wont fight me.
I’ve submitted a feature request to make it so that if there is a property on the super class that has the same name as a data type like Text that the IDE permit me to make a computed property on a subclass that shadows that one.
In the mean time this is a workaround.
There are some really handy pragmas that can help you speed up your code a lot if you turn off the things they deal with.
Normally Xojo puts in extra checks to make sure you dont exceed array boundaries and dont overflow the stack on recursive calls. The list is on this page but I’ll repeat a few here
BackgroundTasks Enables or disables auto-yielding to background threads.In addition to the pragma directive, specify True or False. You may place this pragma anywhere within the method to enable or disable background threads as necessary.
BoundsChecking Enables or disables bounds checking.In addition to the pragma directive, specify True or False. You may place this pragma anywhere within the method to enable or disable bounds checking as necessary.
NilObjectChecking Controls whether to automatically check objects for Nil before accessing properties and calling methods. In addition to the pragma directive, specify True or False.
StackOverflowChecking Controls whether to check for stack overflows.In addition to the pragma directive, specify True or False. You may place this pragma anywhere within the method to enable or disable stack overflow checking as necessary.
These 4 can be VERY handy and can improve speed a lot. But, I would suggest ONLY enabling them in release builds AFTER you have debugged everything satisfactorily.
Enabling them in a debug build may mean you get odd crashes of your debug builds because none of these checks will be done. And if you have an issue that causes one of these you may get a hard crash of your app being debugged instead of breaking into the debugger where the issue exist.
And there is one more you might need to carefully determine if you want it enabled or not
BreakOnExceptions Used to override the BreakOnExceptions menu item in the IDE. The possible values are: True, False, and Default. You may place this pragma anywhere within the method to enable or disable breaking on exceptions as necessary.
In conjunction with the others if you turn break on exceptions off as well then you can have a horrible time trying to debug.
Often I will use code like
#if debugBuild = false #pragma BackgroundTasks false #pragma BoundsChecking false #pragma NilObjectChecking false #pragma StackOverflowChecking false #endif
at the beginning of methods so that during debugging runs I still get the exceptions if I do something that would cause a crash in a release build. Eventually I may also add
#pragma BreakOnExceptions false
outside that group because I have debugged that code well enough and tested whatever exception handling in there I’m happy with it and can ignore any exceptions the code might raise.
Careful out there !
Sure I badly paraphrased the line from Wizard of Oz but this isn’t a word junkies blog. Or a Word© junkies blog either 🙂
Stupid tech jokes aside this one is about Ptr and Memoryblock and their interesting relationship.
In Xojo a memory block is just that – a chunk of memory acquired in one of many ways, that usually can be manipulated in lots of ways. They can be really useful for all kinds of tasks like dealing with byte oriented data (files, binary streams) as well as more high level things like manipulating UTF-8 data since at the very lowest level UTF-8 is just special runs of bytes that we interpret as “characters” or “text”.
But then, everything in a program is JUST runs of bytes that are interpreted in special ways depending on what the bytes are, whether they happen to be “data” or “code”.
And this is where things get interesting.
A recent post on the forums did
dim p as ptr = d //d is a delegate like "AddressOf methodName" dim mb as MemoryBlock = p dim id as string = Crypto.SHA256(mb)
So exactly whats going on here and why might this be a problem and why might it cause a crash ?
AddressOf returns, as it states, the in memory address of whatever method you ask for. And this address is a ptr – a specific place in the running instance as loaded at this time which _could_ be different next time you run the application. This tends to be an OS level security measure.
Memory blocks CAN be created from a Ptr. Usually this is so you can use it with a declare that creates and allocates some memory and returns a pointer to that allocated chunk of memory. But, a pointer is a pointer is a pointer. So it really doesn’t matter where that pointer came from. And with this particular pointer
dim mb as MemoryBlock = p
being the address of some method, or executable code, it just happens to be in our program and its memory space. But it is relevant that is its executable code.
And then when this code tries to access that ptr it tries to READ the code, not just the ptr, since the base address of the memory block is just where “the bytes that make up thi memoryblock” are.
Crypto may die for one of two reasons. First – the OS may bock you from reading the executable code this way. Secondly Crypto would need to know how much data to encrypt. And a memoryblock created from a Ptr doesn’t have a known size. So SHA256 may just try and read -1 byes (which is a HUGE unsigned number) and crash because of that.
If you’re going to mess with Ptr’s & memoryblocks make sure you know what toes you’re prepared to lose 🙂
One day on IfNotNil we were discussing byte code and interpreters.
And the conversation came around to old CPU’s like the 6502. One many folks cut their teeth on. My first computer was a TRS-80 CoCo and after than I stepped up to an IBM clone; a TI Professional which lasted me through University and up until I started my first job after school.
As part of the discussion it was hinted that writing a byte code interpreter for any one of several old 8 bit CPU’s might be an interesting diversion. And it might also prove to be useful as a learning exercise for others.
Since the 6502 is an 8 bit only machine it basically is a “byte code” interpreter by its very definition. Each opcode is entirely contained in one byte – instead of like some current machines today that have very wide opcodes.
As such its possible to encode EVERY opcode and an associated handler in a simple table of 255 entries that, when an opcode is encountered, the handler is fetched from a table of handlers and invoked.
Those handlers are all 0 parameter methods that fetches whatever necessary operands it requires, executes the specific instruction, sets registers, and returns.