Posts: 454
Threads: 45
Joined: Jul 2022
Reputation:
43
(05-21-2025, 12:11 PM)mdijkens Wrote: Example showing difference passing parameter variables by reference or by value:
Code: (Select All)
x = 5: x$ = "ABC"
Print "By Reference:"
Print "Checkfunction returns "; CheckFunction$(x, x$)
Print "After CheckFunction x="; x
Print "After CheckFunction x$="; x$
x = 5: x$ = "ABC"
Print "By Value:"
Print "Checkfunction returns "; CheckFunction$((x), "a" + x$)
Print "After CheckFunction x="; x
Print "After CheckFunction x$="; x$
Function CheckFunction$ (x, x$)
x = x * 3: x$ = x$ + "DEF"
CheckFunction$ = "hello"
End Function
Good example but it can bring some confusion:
I prefer to show variables out and into procedure...
Code: (Select All)
x = 5: x$ = "ABC"
Print "By Reference:"
Print "Checkfunction returns "; CheckFunction$(x, x$)
Print
Print "After CheckFunction x="; x
Print "After CheckFunction x$="; x$
x = 5: x$ = "ABC"
Print "By Value:"
Print "Checkfunction returns "; CheckFunction$((x), "a" + x$)
Print
Print "After CheckFunction x="; x
Print "After CheckFunction x$="; x$
Function CheckFunction$ (x, x$)
Xp = CsrLin: Yp = Pos(0)
Locate Xp + 1, 1
x = x * 3: x$ = x$ + "DEF"
Print "in Function: x = "; x; "X$= "; x$
Locate Xp, Yp
CheckFunction$ = "hello"
End Function
but it brings a hidden issue...
What issue?
the second parameter of the Function is named X$ like the global variable X$ but their are 2 different variables... in the execution the compiler uses a different variable into function to work with a string... so when you modify X$ in Function you modify that is not the global X$ but "a"+X$... so when the value is popped out at the end of the procedure it has not been put into global X$ because it is "a"+X$. If you delete the string "a" added to X$ in the calling of function you'll observe that the global X$ has been changed.
And so?
The correct way to pass string for value is (X$) and not X$...you get global X$ unchanged because you pass more than X$ as parameter, so the changement cannot be put into global X$ after exiting Function.
The confounding issue is to use the same name for parameters of FUNCTION and the global variables. We must use only the same type of variable, not the same name.
Thanks for focusing on this aspect of passing parameter by reference. A composite value passed have no return horse.
here your code modified to show better the issue:
Code: (Select All)
Color 0, 3
x = 5: x$ = "ABC"
Print "By Reference:"
Print "Before CheckFunction x="; x
Print "Before CheckFunction x$="; x$
Print "Checkfunction returns "; CheckFunction$(x, x$)
Print
Print "After CheckFunction x="; x
Print "After CheckFunction x$="; x$
Color 9, 2
x = 5: x$ = "ABC": Y$ = "000"
Print "By Value:"
Print "Before CheckFunction x="; x
Print "Before CheckFunction x$="; x$
Print "Before CheckFunction Y$="; Y$
Print "Checkfunction returns "; CheckFunction$((x), Y$ + x$)
Print
Print "After CheckFunction x="; x
Print "After CheckFunction x$="; x$
Print "After CheckFunction Y$="; Y$
End
Function CheckFunction$ (x, x2$)
Xp = CsrLin: Yp = Pos(0)
Locate Xp + 1, 1
x = x * 3: x2$ = x2$ + "DEF"
Print "in Function: x = "; x; "X2$= "; x2$
Locate Xp, Yp
CheckFunction$ = "hello"
End Function
here screenshot of output
Posts: 583
Threads: 107
Joined: Apr 2022
Reputation:
39
05-22-2025, 02:37 AM
(This post was last modified: 05-22-2025, 02:42 AM by CharlieJV.)
Parameters "by reference" and "by value" have already been mentioned. In case this is useful to the discussion, here are just a couple of silly examples:
By reference:
By value:
Posts: 946
Threads: 51
Joined: May 2022
Reputation:
32
05-22-2025, 03:00 PM
(This post was last modified: 05-22-2025, 03:01 PM by Kernelpanic.)
(05-21-2025, 11:35 AM)bplus Wrote: SMcNeill: "I'm not certain what "unless you tell them to" refers to"
It refers to exactly what you showed in your example:
FUNCTION foo (x)
foo = 2 * x
X = x + 1 ' <<< here Steve told the function to change the variable! not normally done with functions
END FUNCTION This way, nothing happens because the function exits before x = x + 1.
Code: (Select All)
Dim As Integer x
x = 4
Print Using "Ergebnis: ###.###"; foo(x)
Function foo (x)
foo = 2 * x
x = x + 1
End Function
This makes sense.
Code: (Select All)
Dim As Integer x
x = 4
Print Using "Ergebnis: ###.###"; foo(x)
Function foo (x)
x = x + 1
foo = 2 * x
'x = x + 1
End Function
Posts: 91
Threads: 8
Joined: May 2024
Reputation:
9
Code: (Select All) Function CheckFunction$ (x, x$)
x = x * 3: x$ = x$ + "DEF"
End Function
something like this puts off enough people from this basic dialect. they can't understand why qb64pe cannot adjust with something that could be optional to use. such as:
Code: (Select All) Function CheckFunction (x, x$) As String
x = x * 3: x$ = x$ + "DEF"
Result = x$ + Trim$(Str$(x))
End Function
(the code just above should run in freebasic.)
people more used to visual basic than quickbasic dislike the stupid type sigils. on the other hand, the decision was unpopular for those of us older hangers-on. in 2005 to force "return" to work like in c and "all those other" languages. disallow "gosub" to be used ever again.
that's why instead i propose a keyword borrowed from pascal/delphi. which doesn't need type sigil because it would be built in. allow people to choose which style they prefer.
the topic starter is better off continuing to program how he revealed. use subprograms only. but be careful with the arguments that are changed inside a subprogram. document which argument will be changed inside a subprogram.
Posts: 719
Threads: 110
Joined: Apr 2022
Reputation:
28
05-22-2025, 10:22 PM
(This post was last modified: 05-22-2025, 10:25 PM by PhilOfPerth.)
(05-22-2025, 03:30 PM)hsiangch_ong Wrote: Code: (Select All) Function CheckFunction$ (x, x$)
x = x * 3: x$ = x$ + "DEF"
End Function
something like this puts off enough people from this basic dialect. they can't understand why qb64pe cannot adjust with something that could be optional to use. such as:
Code: (Select All) Function CheckFunction (x, x$) As String
x = x * 3: x$ = x$ + "DEF"
Result = x$ + Trim$(Str$(x))
End Function
(the code just above should run in freebasic.)
people more used to visual basic than quickbasic dislike the stupid type sigils. on the other hand, the decision was unpopular for those of us older hangers-on. in 2005 to force "return" to work like in c and "all those other" languages. disallow "gosub" to be used ever again.
that's why instead i propose a keyword borrowed from pascal/delphi. which doesn't need type sigil because it would be built in. allow people to choose which style they prefer.
the topic starter is better off continuing to program how he revealed. use subprograms only. but be careful with the arguments that are changed inside a subprogram. document which argument will be changed inside a subprogram.
Yes, thanks hsiangch_ong.
I'm afraid some of the replies were a bit too much for my little brain to cope with.
I grew up through Locomotive and GW basic, with Subs my main "goto" (pardon the pun), and I find I can do most of the things I need with this,
with the help of the newer graphics, sound and file-handling features etc.
I haven't seen any replies that would persuade me to change at this late stage.
Thanks to those who replied. I appreciate your work and help. You've helped to clear some of the mystery around this topic for me.
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, Western Australia.) 
Please visit my Website at: http://oldendayskids.blogspot.com/
Posts: 4,156
Threads: 190
Joined: Apr 2022
Reputation:
263
Here is my latest Function:
Code: (Select All) _Title "BMI for males" ' b+ 2025-05-22
Print BMI(67, 157) ' matches other sources for me 5/22/2025 24.59 Normal!
Function BMI (HeightInches, Lbs)
BMI = Lbs / (HeightInches ^ 2) * 703
End Function
I use to be well into the obese category, down 90 lbs now!
b = b + ...
Posts: 1,047
Threads: 141
Joined: Apr 2022
Reputation:
23
Wow, I'm surprised how popular this thread is!
The one thing that has confused / surprised me about QB64PE's functions is you can't declare the function's return type with the type name, e.g., the IDE won't accept:
Function MyFunction(Param1 As Integer, Param2 As Integer) As String
instead you have to declare it using the type symbol, e.g.,
Function MyFunction$(Param1 As Integer, Param2 As Integer)
It doesn't bother me enough to care, but it did confuse me at first and it just seems inconsistent with what I'm used to with VB6, VBA, etc. (I don't remember whether the original QuickBasic was like that.)
Posts: 4,156
Threads: 190
Joined: Apr 2022
Reputation:
263
05-23-2025, 10:29 AM
(This post was last modified: 05-23-2025, 10:41 AM by bplus.)
You just made a good point supporting the use of Subs over Functions!
Try and return an array or structure/UDT with a function (in QB64).
OTOH normally you use a sub to draw something but when reviewing my handy Subs and Functions in my toolbox last night (BTW Subs outnumber Functions maybe 5 to 1 !) I found a Function that draws a Sky for background according to a light percentage from 0 to 100. It's a function because it makes a background image that you can reuse in mainloop for drawing same background to clear screen and update animation action. So it returns the handle to that image which needs to be shared with Main program to use in loop.
Here is quick demo test (not using it in a loop over and over again for a background for an animation) just comparing different light settings:
Code: (Select All) _Title "DrawSky&(light) test" 'b+ 2025-05-22
Screen _NewImage(800, 600, 32)
_ScreenMove 250, 60
For i = 0 To 100 Step 12.5
hdl& = DrawSky&(i)
_PutImage , hdl&, 0
_Title "DrawSky&(light) test, light at" + Str$(i) + "%"
_Display
Sleep
Next
Function DrawSky& (light As Long) ' light = 0 to 100 as percent
' needs MidInk~&() Function
Dim As _Unsigned Long saveColor, c
Dim As Long i, rtn, saveDest
Dim r, rn, xx, yy, lite
lite = 2 * light
saveDest = _Dest
saveColor = _DefaultColor(saveDest)
rtn = _NewImage(_Width, _Height, 32)
_Dest rtn&
For i = 0 To _Height - 1
c = midInk(.75 * lite + 10, .75 * lite + 5, 35 + .75 * lite, 25 + lite, lite, 55 + lite, i / (_Height - 1))
Line (0, i)-(_Width, i), c
Next
'stars only in low lite
If lite <= 100 Then
For i = 1 To _Width * _Height / 1500
rn = Rnd: xx = Rnd * _Width: yy = Rnd * _Height
If rn < .01 Then
For r = 0 To 2 Step .5
Circle (xx, yy), r, _RGB32(185, 185, 185)
Next
ElseIf rn < .2 Then
Circle (xx, yy), 1, _RGB32(185, 185, 185)
PSet (xx, yy), _RGB32(185, 185, 185)
Else
PSet (xx, yy), _RGB32(185, 185, 185)
End If
Next
End If
_Dest saveDest
Color saveColor
DrawSky& = rtn
End Function
Function midInk~& (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
midInk~& = _RGB32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##)
End Function
b = b + ...
Posts: 4,156
Threads: 190
Joined: Apr 2022
Reputation:
263
Also reviewing my handy Functions last night I ran into a couple of very useful ones PLUS they reminded me of PhilOfPerth.
So here they are with a demo for @PhilOfPerth
Code: (Select All) Test$ = "PhilOfPerth"
Print "Left of "; Test$; " is "; LeftOf$(Test$, "Of")
Print "Right of "; Test$; " is "; RightOf$(Test$, "Of")
Function LeftOf$ (source$, of$)
If InStr(source$, of$) > 0 Then
LeftOf$ = Mid$(source$, 1, InStr(source$, of$) - 1)
Else
LeftOf$ = source$
End If
End Function
' update these 2 in case of$ is not found! 2021-02-13
Function RightOf$ (source$, of$)
If InStr(source$, of$) > 0 Then
RightOf$ = Mid$(source$, InStr(source$, of$) + Len(of$))
Else
RightOf$ = ""
End If
End Function
b = b + ...
Posts: 4,156
Threads: 190
Joined: Apr 2022
Reputation:
263
05-23-2025, 11:22 AM
(This post was last modified: 05-23-2025, 11:24 AM by bplus.)
Here is 34 very handy Functions in less than 300 LOC
Code: (Select All) ' ======================================================================= IFFs of a Type 2023-11-03
Function IfS$ (Bool&, tru$, fals$) ' IF Boolean Return True$ else False$
If Bool& Then IfS$ = tru$ Else IfS$ = fals$
End Function
Function IfL& (Bool&, tru&, fals&) ' IF Boolean Return True& else False&
If Bool& Then IfL& = tru& Else IfL& = fals&
End Function
Function IfD# (Bool&, tru#, fals#) ' IF Boolean Return True# else False#
If Bool& Then IfD# = tru# Else IfD# = fals#
End Function
Function IfUL~& (Bool&, tru~&, fals~&) ' IF Boolean Return True~& else False~&
If Bool& Then IfUL~& = tru~& Else IfUL~& = fals~&
End Function
' ===================================================================================== Random stuff
Function rndI& (n1 As Long, n2 As Long) 'return an integer between 2 numbers
Dim As Long l, h
If n1 > n2 Then l = n2: h = n1 Else l = n1: h = n2
rndI& = Int(Rnd * (h - l + 1)) + l
End Function
Function rndR (n1, n2) 'return real number (_single, double, _float depending on default / define setup)
rndR = (n2 - n1) * Rnd + n1
End Function
Function rndCWI (center, range) 'center +/-range weights to center
Dim As Long halfRange, c
halfRange = Int(range) + 1 'for INT(Rnd) round range in case not integer
c = Int(center + .5)
rndCWI = c + Int(Rnd * (halfRange)) - Int(Rnd * (halfRange))
End Function
' 2023-01-20 tested
Function rndCW (C As Single, range As Single) 'center +/-range weights to center
rndCW = C + Rnd * range - Rnd * range
End Function
Function rdir% ()
If Rnd < .5 Then rdir% = -1 Else rdir% = 1
End Function
'===================================================================================== Handy numbers
Function dist# (x1%, y1%, x2%, y2%) ' hypot might be better
dist# = ((x1% - x2%) ^ 2 + (y1% - y2%) ^ 2) ^ .5
End Function
Function min (a, b)
min = -a * (a < b) - b * (b <= a)
End Function
Function max (a, b)
max = -a * (a > b) - b * (b >= a)
End Function
Function map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
End Function
'======================================================================================= Color stuff
Function qb~& (n As Long)
Select Case n
Case 0: qb~& = &HFF000000
Case 1: qb~& = &HFF000088
Case 2: qb~& = &HFF008800
Case 3: qb~& = &HFF008888
Case 4: qb~& = &HFF880000
Case 5: qb~& = &HFF880088
Case 6: qb~& = &HFF888800
Case 7: qb~& = &HFFCCCCCC
Case 8: qb~& = &HFF888888
Case 9: qb~& = &HFF0000FF
Case 10: qb~& = &HFF00FF00
Case 11: qb~& = &HFF00FFFF
Case 12: qb~& = &HFFFF0000
Case 13: qb~& = &HFFFF00FF
Case 14: qb~& = &HFFFFFF00
Case 15: qb~& = &HFFFFFFFF
End Select
End Function
Function rclr~& ()
rclr~& = _RGB32(rndI(64, 255), rndI(64, 255), rndI(64, 255), rndI(0, 255))
End Function
Function Plasma~& ()
cN = cN + 1 ''Dim Shared cN, pR, pG, pB
Plasma~& = _RGB32(127 + 127 * Sin(pR * cN), 127 + 127 * Sin(pG * cN), 127 + 127 * Sin(pB * cN))
End Function
Function midInk~& (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
midInk~& = _RGB32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##)
End Function
' ===================================================================================== String Stuff
Function LeftOf$ (source$, of$)
If InStr(source$, of$) > 0 Then
LeftOf$ = Mid$(source$, 1, InStr(source$, of$) - 1)
Else
LeftOf$ = source$
End If
End Function
' update these 2 in case of$ is not found! 2021-02-13
Function RightOf$ (source$, of$)
If InStr(source$, of$) > 0 Then
RightOf$ = Mid$(source$, InStr(source$, of$) + Len(of$))
Else
RightOf$ = ""
End If
End Function
Function strReplace$ (s$, replace$, new$) 'case sensitive 2020-07-28 version
Dim p As Long, sCopy$, LR As Long, lNew As Long
If Len(s$) = 0 Or Len(replace$) = 0 Then
strReplace$ = s$: Exit Function
Else
LR = Len(replace$): lNew = Len(new$)
End If
sCopy$ = s$ ' otherwise s$ would get changed
p = InStr(sCopy$, replace$)
While p
sCopy$ = Mid$(sCopy$, 1, p - 1) + new$ + Mid$(sCopy$, p + LR)
p = InStr(p + lNew, sCopy$, replace$)
Wend
strReplace$ = sCopy$
End Function
Function strEnclose$ (s$, str1or2$)
If Len(str1or2$) = 2 Then
strEnclose$ = Left$(str1or2$, 1) + s$ + Right$(str1or2$, 1)
ElseIf Len(str1or2$) = 1 Then
strEnclose$ = str1or2$ + s$ + str1or2$
Else
Beep
End If
End Function
Function StrCopies$ (NumberOfCopies&, S$) ' modified 2021-02-19 to match STRING$ args and for SUB AStringInsertAtNthPlace
Dim i&, b$
For i& = 1 To NumberOfCopies&
b$ = b$ + S$
Next
StrCopies$ = b$
End Function
'Description: Use Item$() Function to treat strings like arrays without having to use an array structure.
' This function does not throw a fit if you ask for an item number (index) it does not have, it just returns an empty string.
' In QB64, Functions can't return arrays through the function name, but they can return strings that the Item$() function can
' translate like an an array index. nItem numbers are the same as Counting numbers positive integers starting at 1.
' eg Item7$ = Item$(CommaDelimitedString$, 7, ",") 'get 7th Item in string
Function Item$ (s$, nItem As Long, delimiter$)
Dim c As Long, d As Long, lastd As Long
If Len(s$) = 0 Then Item$ = "": Exit Function
lastd = 1: d = InStr(lastd, s$, delimiter$)
While d > 0
c = c + 1
If c = nItem Then
Item$ = Mid$(s$, lastd, d - lastd): Exit Function
Else
lastd = d + 1: d = InStr(lastd, s$, delimiter$)
End If
Wend
c = c + 1
If c <> nItem Then Item$ = "" Else Item$ = Mid$(s$, lastd, Len(s$))
End Function
Function format$ (template As String, Source As String)
Dim d, s, n, i, t$
d = _Dest: s = _Source
n = _NewImage(80, 80, 0)
_Dest n: _Source n
Print Using template; Val(Source)
For i = 1 To 79
t$ = t$ + Chr$(Screen(1, i))
Next
If Left$(t$, 1) = "%" Then t$ = Mid$(t$, 2)
format$ = _Trim$(t$)
_Dest d: _Source s
_FreeImage n
End Function
Function xDP$ (x, DP)
Dim test$, p As Long
test$ = _Trim$(Str$(Int(x * 10 ^ DP) / 10 ^ DP))
p = InStr(test$, ".")
If p = 0 And DP <> 0 Then test$ = test$ + "." + String$(DP, "0")
If p And DP = 0 Then test$ = Left$(test$, Len(test$) - 1)
xDP$ = test$
End Function
Function commaD$ (n#, nDecPlaces%) 'only works right for double# type
Dim place As Long, s$, front$, back$, func$
func$ = _Trim$(Str$(n#))
If Left$(func$, 1) = "-" Then s$ = "-": func$ = Mid$(func$, 2) Else s$ = ""
place = InStr(func$, ".")
If place = 0 Then place = Len(func$) + 1
While place > 4
func$ = Mid$(func$, 1, place - 4) + "," + Mid$(func$, place - 3)
place = InStr(func$, ",")
Wend
'fix to nDecPlaces
place = InStr(func$, ".")
If nDecPlaces% Then
If place Then
front$ = Mid$(func$, 1, place)
back$ = Mid$(func$, place + 1)
If Len(back$) > nDecPlaces% Then func$ = front$ + Left$(back$, nDecPlaces%)
If Len(back$) < nDecPlaces% Then func$ = front$ + Left$(back$ + String$(nDecPlaces%, "0"), nDecPlaces%)
Else
func$ = func$ + "." + String$(nDecPlaces%, "0")
End If
Else
If place Then func$ = Mid$(func$, 1, place - 1)
End If
commaD$ = s$ + func$
End Function
'this might make a nice Money format
Function money$ (n#) 'only works right for double# type
Dim place As Long, s$, front$, back$, b$
b$ = _Trim$(Str$(n#))
If Left$(b$, 1) = "-" Then s$ = "-": b$ = Mid$(b$, 2) Else s$ = ""
place = InStr(b$, ".")
If place = 0 Then place = Len(b$) + 1
While place > 4
b$ = Mid$(b$, 1, place - 4) + "," + Mid$(b$, place - 3)
place = InStr(b$, ",")
Wend
'fix this for 2 places after decimal
place = InStr(b$, ".")
If place Then
front$ = Mid$(b$, 1, place)
back$ = Mid$(b$, place + 1)
If Len(back$) > 2 Then b$ = front$ + Left$(back$, 2)
If Len(back$) < 2 Then b$ = front$ + Left$(back$ + "00", 2)
Else
b$ = b$ + ".00"
End If
money$ = "$" + s$ + b$
End Function
Function DateTimeStamp$
DateTimeStamp$ = Mid$(Date$, 7) + "-" + Mid$(Date$, 1, 2) + "-" + Mid$(Date$, 4, 2) + "_" + Mid$(Time$, 1, 2)
End Function
Function xStr$ (x, strng$) ' make x copies of string
Dim i As Long, b$
For i = 1 To x
b$ = b$ + strng$
Next
xStr$ = b$
End Function
Function timeStr2Secs! (timeStr$)
Dim hh As Long, mm As Long, s!
hh = Val(Mid$(timeStr$, 1, 2))
mm = Val(Mid$(timeStr$, 4, 2))
s! = Val(Mid$(timeStr$, 7, 5))
timeStr2Secs! = hh * 60 * 60 + mm * 60 + s!
End Function
Function secs2TimeStr$ (secs!)
Dim hh As Long, mm As Long, s!, h$, m$, s$
hh = secs! \ 3600
mm = (secs! - hh * 3600) \ 60
s! = (secs! - hh * 3600 - mm * 60)
s! = Int(s! * 100) / 100
h$ = Right$("00" + LTrim$(Str$(hh)), 2)
m$ = Right$("00" + LTrim$(Str$(mm)), 2)
s$ = Right$("00000" + LTrim$(Str$(s!)), 5)
secs2TimeStr$ = h$ + ":" + m$ + ":" + s$
End Function
'load a file into a string from GUI Tools 1 TxtBoxes 2019-09-30
Function fileStr$ (txtFile$)
Dim b$
If _FileExists(txtFile$) Then
Open txtFile$ For Binary As #1
b$ = Space$(LOF(1))
Get #1, , b$
Close #1
fileStr$ = b$
End If
End Function
Function Join$ (arr() As String, delimiter$)
Dim i As Long, b$
For i = LBound(arr) To UBound(arr)
If i = LBound(arr) Then b$ = arr(LBound(arr)) Else b$ = b$ + delimiter$ + arr(i)
Next
Join$ = b$
End Function
b = b + ...
|