dim wp as waveformProperties = channelWaveformProperties(i)
findMatchingWaveformPresetIfExists(wp)
But this brings up a pretty basic question… Why can’t I do this in the first place? I would expect that at runtime the inner expression would be evaluated (i.e., dereference the item from the array) first, and then passed to the method. Can the existing compiler really not tell that the array (or indeed, a function call etc) will return the correct type to match the ByRef definition?
Will the fabled new compiler slated for sometime before the end of the world allow for things like this?
If you think about it, the error message makes perfect sense. When you pass something ByRef, you are passing a pointer (address) to the value or object. How can the compiler know the value of an expression and where that value may ultimately be stored in memory at compile time in order to pass its address?
Randy, your comment beautifully illustrated why the compiler should not even have to care - a pointer is a pointer is a pointer. If I tell the compiler that I’ll be passing a pointer to an object to a method, why should it care where I get that pointer at runtime?
It can’t. It also can’t tell where in memory ANYTHING will be at compile time.
@Rick Araujo - waveformProperties is a class that handles managing electrical waveforms for a device we’re developing. It stores things such as frequency, polarity, amplitude, etc. It includes several methods for doing various things. The hardware we are working on supports up to 5 simultaneous waveforms, so I have an array of 5 waveformProperties called channelWaveformProperties. Apparently the compiler won’t let me say: take the ith waveformProperty from the channelWaveformProperties array as your argument. Instead, I have to pull the ith waveformProperty out myself into a locally dim’d variable, then pass that instead.
I hate to bring up other languages etc, but I can’t think of any other language I’ve used that is incapable of evaluating an expression prior to passing the results to a method in this manner. This includes Java, C (++), PHP, Ruby, Objective-C, etc.
Reminds me of when I first started using Xojo (ahem, RealBasic 4) back in the day. Back then, you could not pass an array to a method at all… as in, you could not declare a method that took an array as an argument. The compiler simply would not do it at all.
@Rick Araujo - this is why I have always felt it was odd that an array and a function call use the same syntax - i.e., parentheses. When reading code, it is sometimes hard to tell if it is an array or a method. When showing people Xojo code for the first time, this is one of the oddities that I always have to explain…“yeah, they decided to use parens for arrays instead of the [ and ] brackets like every mainstream language in the world does. Don’t ask why. Xojo just does some weird stuff.”
ByRef says you plan on replacing the pointer itself, not just modifying what it points to. That’s why the location has to be predictable. ByRef says you could have a completely different object when the function returns, not just a modified object. Do you really need to pass the parameter ByRef?
Yep, I know. But it’s due to a language legacy. Maybe, someday, they will decided to do a huge overhaul to the language (as Python did in v3) changing all the oddities to a better language design (in my opinion) making it even incompatible with the old language and breaking old code in a purpose. Maybe they include a project setting like “Compile as Xojo V1 Syntax” for retro compatibility of old projects.
Thanks @Rick Araujo - that does work fine, not sure why I convinced myself to try to pass ByRef instead… had my head in other environments that do things differently lately, I suppose.
Passing by reference and passing by value in Xojo appear to behave a little differently than I’m used to in other languages. To make sure I have things straight, in Xojo:
If it’s an instantiated object or an array of any type, it is ALWAYS passed ByRef, even if you try to define the method you are calling to receive things ByVal.
If it’s an intrinsic type (Integer, Double, String, Structure, Currency (or anything defined as a “Data Type” in the language reference, it is passed ByVal unless you specify ByRef.
Which begs the question: Why in the world does ByVal even exist?
But I also think my original question has been lost: Let’s assume that I had the following method:
Sub doSomething(ByRef i as Integer)
i = Pow(i + 1, 2) //silly example.
End Sub
and then this chunk of code:
[code] dim numbers() as Integer
numbers.append(1)
numbers.append(2)
numbers.append(3)
doSomething(numbers(1))[/code]
The compiler barks at me because it can’t seem to figure out that it just needs to pull an item out of the numbers array and pass it’s address to doSomething. I’m forced to do it manually:
dim numbers() as Integer
numbers.append(1)
numbers.append(2)
numbers.append(3)
dim i as integer = numbers(1)
doSomething(i)
numbers(1) = i
This just strikes me as odd compiler behavior. The compiler should know that numbers() is going to be an array of Integers, and that Integers can be passed byRef, ergo an item in numbers() should be allowed to be passed in this manner.
When you declare a variable of an object type, that variable contains a reference to the object, not the object itself. When you pass that variable to a function (without using ByRef), you are passing the reference (a pointer really) ByVal. That means you cannot change the value of the reference - it will still point to the same object when the function returns, no matter what you do in the function. If you pass it ByRef, though, the function may actually change the object instance that the variable refers to. So it does make sense to think about passing an object ByVal or ByRef. There is still a distinction.
sub foo(ref as Class1)
ref = new Class1 // creates object B
end
dim p as new Class1 // creates object A
foo(p)
// p still refers to object A
sub foo(ByRef ref as Class1)
ref = new Class1 // creates object B
end
dim p as new Class1 // creates object A
foo(p)
// p now refers to object B