Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Changing string variable value within Sub
#1
When I run the following program:

Code: (Select All)
a$ = "Hello"
Print "a$ as assigned="; a$
abc a$
Print "a$ AFTER sub="; a$

Print

a$ = "Hello"
Print "a$ as assigned="; a$
abc a$ + " col=10 row=10 height=1 len=50"
Print "a$ AFTER sub="; a$



Sub abc (g$)
    Print "value within the sub="; g$
    g$ = g$ + " world"
End Sub


I get the following output:

a$ as assigned=Hello
value within the sub=Hello
a$ AFTER sub=Hello world

a$ as assigned=Hello
value within the sub=Hello col=10 row=10 height=1 len=50
a$ AFTER sub=Hello


The first instance works as expected - I assign a$, pass it to the sub, alter the value, and upon return it has retained the changed from the Sub.

BUT...why is it that when I pass a$ with a static string, I get all of that value passed to the Sub (Hello col=10 row=10 height=1 len=5), but I cannot retain any changes when we return from the Sub ?  Regardless of what I change g$ to in the sub it always reverts back to Hello.
Reply
#2
(02-23-2025, 11:49 PM)dano Wrote: When I run the following program:

Code: (Select All)
a$ = "Hello"
Print "a$ as assigned="; a$
abc a$
Print "a$ AFTER sub="; a$

Print

a$ = "Hello"
Print "a$ as assigned="; a$
abc a$ + " col=10 row=10 height=1 len=50"
Print "a$ AFTER sub="; a$



Sub abc (g$)
    Print "value within the sub="; g$
    g$ = g$ + " world"
End Sub


I get the following output:

a$ as assigned=Hello
value within the sub=Hello
a$ AFTER sub=Hello world

a$ as assigned=Hello
value within the sub=Hello col=10 row=10 height=1 len=50
a$ AFTER sub=Hello


The first instance works as expected - I assign a$, pass it to the sub, alter the value, and upon return it has retained the changed from the Sub.

BUT...why is it that when I pass a$ with a static string, I get all of that value passed to the Sub (Hello col=10 row=10 height=1 len=5), but I cannot retain any changes when we return from the Sub ?  Regardless of what I change g$ to in the sub it always reverts back to Hello.

... because line 10 of your code creates a temporary string build from the current a$ contents and the literal string you add to it, that temporary string is then passed to the sub and not the original a$, i.e. the sub only modifies the temporary string it got passed, but that is discarded as soon as the sub returns and a$ is in fact never touched by the sub.
Reply
#3
That makes sense...thanks for the quick reply.  Gotta rethink this...
Reply
#4
Yes, that's a very common mistake in thinking people do when it comes to passing back results through the given arguments.

That only works if standalone variables of the very same type as the SUB/FUNC expects are passed, as soon as any operations are involved in the call or the type doesn't match (e.g. the SUB expects a LONG but got passed an INTEGER or _BYTE) a temporary variable of the required type is created and passed instead of the original variable and hence the original variable never gets modified.
Reply
#5
As much fun as it to pass a value instead of a variable, don't expect it to come back as the variable it was passed to in the sub.

Code: (Select All)
Dim IQ As Integer
printx "My I.Q. is", 160
Print "Wait, let's double check that. Oops, my I.Q. is"; IQ
Sub printx (a$, IQ)
    Print a$; IQ
End Sub

Now of course we don't have to match the name of the variable passed, it just needs to be a variable. Oh, and we don't even have to assign it in the argument, but that's sloppy, because it changes type from integer to single (default variable type) and back to integer again, but it works! I often do this until I get my program ready to use, to avoid taking up time initially.

Code: (Select All)
a% = 160: printx "My I.Q. is", a%
Print "Wait, let's double check that. Yep, my I.Q. is"; a%
Sub printx (a$, reallylongexplainedvariablenamehereforIQ)
    Print a$; reallylongexplainedvariablenamehereforIQ ' This variable is a single TYPE.
End Sub

..of course one way to avoid creating more than one TYPE is to assign the type to the argument in the sub call...

Code: (Select All)
Dim As Integer a
a = 160: printx "My I.Q. is", a
Print "Wait, let's double check that. Yep, my I.Q. is"; a
Sub printx (a$, reallylongexplainedvariablenamehereforIQ As Integer) ' Added As Integer.
    Print a$; reallylongexplainedvariablenamehereforIQ ' Now this variable is an integer TYPE.
End Sub


Note you need to make the argument match the passing type if you want to avoid a second type entering into the subroutine. Not doing so would cause errors if the the limits of a type were exceeded.

Code: (Select All)
Dim IQ As _Integer64 ' Traditional was to DIM, but I like the new QB64 method, above examples, which allow for more variables to be added with commas! Thanks, Dev Team!
IQ = 9223372036854775807
Print IQ
printx "My I.Q. is", IQ
Sub printx (a$, IQ)
    Print a$; IQ ' Will appear truncated in SN.
End Sub

..or just keep it really simple without changing the variable name or type...

Code: (Select All)
Dim As Integer IQ
IQ = 160: printx "My I.Q. is", IQ
Print "Wait, let's double check that. Yep, my I.Q. is"; IQ
Sub printx (a$, IQ As Integer)
    Print a$; IQ
End Sub

Pete
Reply
#6
This made me want to see what happens when the wrong data type is passed. Nothing happens. Shouldn't there be an error message?

Code: (Select All)

'Beispiel fuer falsche Uebergabe an Prozedur/Funktion - 24. Feb. 2025

Option _Explicit

Declare Function Beispiel(kilowatt As Double) As Double

Dim As Double eingabe
Dim As Integer eingabe1

Print
Print "Kilowatt in PS"
Print: Print

Input "Kilowatt eingeben: ", eingabe1
Print
Print Using "Das sind ###.## PS"; Beispiel(eingabe1)


Function Beispiel (kilowatt As Double)

  Dim As Double ps

  ps = kilowatt * 1.36
  Beispiel = ps

End Function

[Image: Falscher-Datentyp2025-02-25.jpg]
Reply
#7
Error: I don't know German Wink

I am not seeing where wrong data is being passed.

but since when does a program judge data?

Here's a Type error for you, I think that is what you are looking for.
Code: (Select All)
'Beispiel fuer falsche Uebergabe an Prozedur/Funktion - 24. Feb. 2025

Option _Explicit

Declare Function Beispiel(kilowatt As Double) As Double

Dim As Double eingabe
Dim eingabe1$

Print
Print "Kilowatt in PS"
Print: Print

Input "Kilowatt eingeben: ", eingabe1$
Print
Print Using "Das sind ###.## PS"; Beispiel(eingabe1$)


Function Beispiel (kilowatt As Double)

    Dim As Double ps

    ps = kilowatt * 1.36
    Beispiel = ps

End Function
b = b + ...
Reply
#8
@dplus - I'm passing an integer to a function that expects a double - that's an error. I was just wondering why there's no error message.
If one did something like that in a real program, the result would be incorrect.

In an important program, it could be a disaster.
Reply
#9
(02-25-2025, 10:08 PM)Kernelpanic Wrote: @dplus - I'm passing an integer to a function that expects a double - that's an error. I was just wondering why there's no error message.
If one did something like that in a real program, the result would be incorrect.

In an important program, it could be a disaster.

Why would that be an error?  Even moreso, why would it be a disaster?

PRINT COS(10%)

Now, the above is a function that expects a DOUBLE.  Yet we're deliberately passing it an integer.  For what reason would COS explode and toss an error message for you?  Why would it be a disaster?

Sure, it's not going to RETURN a value back to you -- how can it?  That's a constant that we're passing to it, so there's no variable for it to pass any value back to us, but why wouldn't it be able to ACCEPT that value as being valid?  Functions and Subs don't always have to pass values through the parameters in a two-way street.

To go back to the original post here, let's examine how and why this works and doesn't work.

Code: (Select All)
Sub abc (g$)
    Print "value within the sub="; g$
    g$ = g$ + " world"
End Sub

Now, we have the following and it works:
Code: (Select All)
abc foo$

And the following doesn't pass a value back:
Code: (Select All)
abc foo$ + " "

The first works because it matches this basic criteria for passing values back and forth between Subs/Functions:
1) Does the type passed match the type in the Sub/Function?
2) Are we ONLY passing a matching variable and nothing more?
3) Are we free of any interposing syntax which might prevent value sharing, such as parenthesis?

foo$ in the first set of code:
1) Does match the g$ in the SUB abc
2) Is the only thing we're passing to the SUB
3) Isn't in the midst of any other syntax
The value there passes back and forth freely.

foo$ in the second set of code:
1) Does match the g$ in the SUB abc
2) Isn NOT the only thing we're passing to the SUB.  We're also passing a trailing space.
3) Has extra syntax -- in this case the plus sign between the foo$ and space.
That value there does NOT pass back and forth freely.



So what happens when it DOESN'T pass back and forth freely???

It only passes TO the function and not BACK from it.

No error.  No exploding of code.  No vast destruction.  It just sends it the value directly to the SUB and runs with it.

Code: (Select All)
SUB abc (foo AS INTEGER)

Now, if we had the above, what would the following do?
Code: (Select All)
DIM x AS DOUBLE.
x = 3.14
abc x
x = 3.68
abc x

For the first call to abc, we'd pass the DOUBLE value of 3.14 to foo.  Foo, however is an integer.  Integers don't have fractions.  How is this handled without exploding a program??   It just rounds it to 3.

For the second call to abc, we pass the DOUBLE value of 3.68 to foo.  Again, foo is an integer.  Here it rounds that value to 4.



This is the way BASIC has always been.  Go back as far into the roots as you want and you'll see this behavior.  It doesn't error.  It doesn't explode.  It's non-destructive.

It just passes the value to the sub and then the type does whatever it needs to to accommodate it.  Pass that integer to your double.  Pass a double to your integer.  It'll work just fine.  It's *always* worked just fine.

Just don't expect to get that value back unless:
1) Does the type passed match the type in the Sub/Function?
2) Are we ONLY passing a matching variable and nothing more?
3) Are we free of any interposing syntax which might prevent value sharing, such as parenthesis?
Reply
#10
(02-25-2025, 10:08 PM)Kernelpanic Wrote: @dplus - I'm passing an integer to a function that expects a double - that's an error. I was just wondering why there's no error message.
If one did something like that in a real program, the result would be incorrect.

In an important program, it could be a disaster.

error! no dplus here try aplus Big Grin

@KP say the word and I will delete this post and leave you to Steve's great lecture Big Grin
b = b + ...
Reply




Users browsing this thread: 3 Guest(s)