Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Use of Functions
#11
(05-21-2025, 09:12 AM)bplus Wrote: To illustrate further the difference between a Function and an equivalent Sub:
Code: (Select All)
nNames = 5
Dim names$(1 To nNames)
names$(1) = "PhilOfPerth"
names$(2) = "bplus"
names$(3) = "ahenry3068"
names$(4) = "SMcNeill"
names$(5) = "Who am I?"
For i = 1 To nNames

    ' using a function only takes one line to report results
    Print "Function last letter for "; names$(i); " is "; LastLetter$(names$(i))

    ' using a sub like a Function usually requires a call to it then another line to report results
    lastLetter names$(i), ll$
    Print "Sub last letter for "; names$(i); " is "; ll$
    Print
Next

Function LastLetter$ (mystring$)
    LastLetter$ = Mid$(mystring$, Len(mystring$), 1)
End Function

Sub lastLetter (mystring$, myLastLetter$)
    myLastLetter$ = Mid$(mystring$, Len(mystring$), 1)
End Sub

Phil: "With a Sub I can change several variables at the same time."

If you need variables changed then yeah by all means use a Sub.
Functions do a job of processing some information and returning a single result like a formula Area = Pi*R^2
Function AreaCircle(R)
AreaCircle = _Pi * R^2
End Function

The advantage of Functions is they wont change their arguments unless you tell them to.


Note that this is... wrong?  Misleading at the very least.

Functions behave *exactly* as Subs do with regards to passing values and changing their arguments.  I'm not certain what "unless you tell them to" refers to, but if types match and values change inside the function, they'll change outside it too.

x = 1
PRINT foo (x)
PRINT foo (x)
PRINT x

FUNCTION foo (x)
   foo = 2 * x
   X = x + 1
END FUNCTION

^ Prints 2 (x = 1), then 4 (x = 2 after the first call), then 3 (final value of x)
Reply
#12
Most times when I use x in f(x) I don't want to change x, that could mess things up badly!

Here's how variable changing may be misused with a sub
Code: (Select All)
For x = 1 To 10
    f x
    Print x
Next

Sub f (x)
    x = x ^ 2
End Sub

With function it's clear x wont get messed up:
Code: (Select All)
For x = 1 To 10
    Print f(x)
Next

Function f (x)
    f = x ^ 2
End Function
b = b + ...
Reply
#13
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
b = b + ...
Reply
#14
I think the best way a beginner might look at a function is that a function works just like a formula, feed it arguments and it RETURNS a single result and you don't usually want to change the value of the arguments while processing the result.
b = b + ...
Reply
#15
The best way to avoid changing values is just to assign to a temp variable.

FUNCTION foo (tempX)
    X = tempX
    ... do whatever with X
END FUNCTION 

100% safe from changing the value, if you only assign it to a temp variable.
Reply
#16
I am afraid Phil is mistaking variable changing as something a sub or function mainly does.

A sub acting as a function has to change an incoming variable to outgoing one but a function doesn't have to do that at all!
b = b + ...
Reply
#17
Hi
I want to share these informations about SUB and FUNCTION

1. you can declare and use only Function for the type of data that you can declare using a suffix as you can see from these wikipage
Data Types and their suffix.
So you cannot (for now) create a FUNCTION returning a _MEM value or an Array of what_ you_ desired_dimensions or an UDT.

2. SUB and FUNCTION get the parameters for reference and not for value... so if you modify the variable into the procedure (SUB/ FUNCTION)  you get back the variable with the modified value. 
It works for any kind of parameter, so you can return an array and a _MEM and an UDT modified from a FUNCTION (and a SUB).

3. if you don't want to change value of variables passed as parameter you can use 2 ways:
   3.1 you can pass the parameters as value ... each parameter has been typed sorrounded by () Function: the 6th point of descriptions
   or 3.2  you can declare a duplicate of the parameter into the procedure (SUB/FUNCTION) and you assign to these last the parameters passed. So you work with local copies of the parameters into the procedure.
Reply
#18
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
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#19
Hi Phil

Like you, I find I use Subs a lot more than Functions but with my coding I often find I'm dealing with Scientific Notation and a Function here has really sped up things. I'm sure there is likely a better Function routine for handling Scientific Notation but here's an out line of my favorite Function.

Code: (Select All)
Dim Shared Number, x, y


'In the main modula will be a calculation which generates a Scientifically Notated value

Number = 115 / 123456

Print Number

x = 115
y = 123456

Number = SNrid
Print Number

Function SNrid
    ScNote$ = Str$(x / y)
    If InStr(1, ScNote$, "E") Or InStr(1, ScNote$, "D") Then 'This power requires moving the decimal 4 places to the left. E = Single Precision = 7 total digits

        SNA = x / y
        a = SNA * 10000000
        b = a \ 1
        C = a - b
        If C >= .5 Then
            b = b + 1
            SNB = b * .0000001
        End If
        If C < .5 Then
            SNB = b * .0000001
        End If
        SNrid = SNB
        Exit Function
    End If
    SNrid = x / y

End Function
 
And if this looks familiar to either Steve or Mark, or another on this forum, then yes, I likely did find it here and thank you for same.
Reply
#20
Functions can, of course, also be passed to procedures (subs) as arguments. Just as functions can be passed to functions as arguments. This is usually done to save code lines. However, for people unfamiliar with this, it's difficult to understand.

Code: (Select All)

Option _Explicit

Declare Function funcEndpreis(kaufpreis, mehrwertSteuer As Double) As Double
Declare Sub subEndpreis(eingabe As Double)

Dim As Double kaufpreis, mehrwertSteuer

Locate 2, 3
Input "Kaufpreis    : ", kaufpreis
Locate 3, 3
Input "Mehrwertsteuer: ", mehrwertSteuer
Locate 4, 3
Print "----------------------"

Locate 6, 3
Print "Endpreis mit Funktion"
Locate 7, 3
Print Using "Der Endpreis betraegt: ####,#.## Euro"; funcEndpreis(kaufpreis, mehrwertSteuer)

Locate 9, 3
Print "Endpreis mit Prozedur/Sub"
Locate 10, 3
'Function as an argument to a sub
Call subEndpreis(funcEndpreis(kaufpreis, mehrwertSteuer))

End


Sub subEndpreis (eingabe As Double)

  'Da braucht man keine neue Variable!
  Print Using "Der Endpreis betraegt: ####,#.## Euro"; eingabe
End Sub

Function funcEndpreis (kaufpreis, mehrwertSteuer As Double)

  Dim As Double gesamtpreis

  gesamtpreis = kaufpreis + ((kaufpreis * mehrwertSteuer) / 100)
  funcEndpreis = gesamtpreis
End Function

Functions can also produce more than one output, but only return one. (Uploading an image isn't working right now.)

Code: (Select All)

Function funcEndpreis (kaufpreis, mehrwertSteuer As Double)

  Dim As Double gesamtpreis, fool

  fool = kaufpreis * 1.5
  Print fool

  gesamtpreis = kaufpreis + ((kaufpreis * mehrwertSteuer) / 100)
  funcEndpreis = gesamtpreis
End Function

It looks pretty confusing, but it works.
Reply




Users browsing this thread: 2 Guest(s)