Page 1 of 1

Access a variable from one function inside another function

Posted: 20 Feb 2018, 13:24
by john_c
Here are 2 functions, the 1st is called inside 2nd. What will be the proper way to invoke "foo" variable inside function2()?

For example, this works, but I understand that this is bad practise:

Code: Select all

function1() {
	foo := "Hello, John!"
}

function2() {
	function1()
	if foo = Hello, John!
		msgBox, Hello Mike!
}

global foo
function2()

Re: Access a variable from one function inside another function

Posted: 20 Feb 2018, 13:52
by boiler
Just return the value of the function.

Code: Select all

function1() {
	return "Hello, John!"
}

function2() {
	foo := function1()
	if foo = Hello, John!
		msgBox, Hello Mike!
}
The main takeaway is that you should get away from thinking that functions share variables and/or variable names. Even if you used a variable inside function1, it could be named foo, but it could be named something else, and it wouldn't matter because it would be unrelated to the other foo other than what you do with it when you get the returned value.

Re: Access a variable from one function inside another function

Posted: 20 Feb 2018, 14:05
by john_c
boiler wrote:...
Thanks again! Your answers are always amazing! :-)

Re: Access a variable from one function inside another function

Posted: 20 Feb 2018, 14:27
by john_c
@boiler

So, as I understand from what you said, this will be impossible?

Code: Select all

function1() {
	person1 := "John"
	person2 := "Jill"
}

function2() {
	msgBox, %person1%
	msgBox, %person2%
}

function2()

Re: Access a variable from one function inside another function

Posted: 20 Feb 2018, 14:46
by nnnik
john_c thats when you return an array.

Code: Select all

function1() {
	person := []
	person.1 := "John"
	person.2 := "Jill"
	return person
}

function2() {
	person := function1()
	msgBox, % person.1
	msgBox, % person.2
}

function2()
Another method would be to use global variables and the global scope:

Code: Select all

function1() {
	global person
	person := []
	person.1 := "John"
	person.2 := "Jill"
}

function2() {
	global person
	msgBox, % person.1
	msgBox, % person.2
}

function1()
function2()
This might seem easier at first however it gets difficult once you have like 30 functions and need to control 300 variables.
You might end up naming 2 variables the same way.

Arguably the best method is to use classes - however that's a little bit advanced so I won't explain it here.

Re: Access a variable from one function inside another function

Posted: 20 Feb 2018, 14:54
by Odlanir
Or even:

Code: Select all

global person1,person2

function1() {
	person1 := "John"
	person2 := "Jill"
}

function2() {
	function1()
	msgBox, %person1%
	msgBox, %person2%
}

function2()

Re: Access a variable from one function inside another function

Posted: 20 Feb 2018, 16:03
by boiler
Another alternative is using ByRef, which allows you to return values directly into the variables in your function call:

Code: Select all

function1(ByRef p1, ByRef p2) {
	p1 := "John"
	p2 := "Jill"
}

function2() {
	function1(person1, person2)
	msgBox, %person1%
	msgBox, %person2%
}

function2()

Re: Access a variable from one function inside another function

Posted: 20 Feb 2018, 17:36
by FanaticGuru
On a tangent note, sometimes you might want to use a gosub which is similar to a function in flow of control in that you jump somewhere and then return but it does not limit anything to a local scope. Everything stays in the global scope which can sometimes be useful.

FG

Re: Access a variable from one function inside another function

Posted: 21 Feb 2018, 08:10
by john_c
Boiler, Nnnik, Odlanir, FanaticGuru - thank you all! Well, it seems there are a lot of thing to learn for!

Re: Access a variable from one function inside another function

Posted: 21 Feb 2018, 11:47
by evilC
What you maybe want is a class.
With a class, you can store variables in the class, and the functions ("methods") of the class can also access these variables.

Code: Select all

#SingleInstance force
#Persistent

mc := new MyClass()
mc.function1()
mc.function2()

class MyClass {
	function1() {
		this.person1 := "John"
		this.person2 := "Jill"
	}

	function2() {
		msgBox, % this.person1
		msgBox, % this.person2
	}
}
However, rather than hard-coding the names, you would normally pass them in in the "constructor":

Code: Select all

mc := new MyClass("John", "Jill")
mc.function2()

class MyClass {
	__New(name1, name2) {
		this.person1 := name1
		this.person2 := name2
	}

	function2() {
		msgBox, % this.person1
		msgBox, % this.person2
	}
}
Classes are really useful if you want to group multiple bits of data together and use them in interesting ways.

Code: Select all

fred := new Person("Fred", 21)
bob := new Person("Bob", 16)

MsgBox % fred.BuildGreeting()
MsgBox % "Bob can order alcohol: " bob.CanOrderAlcohol()

class Person {
	__New(name, age){
		this.name := name
		this.age := age
	}
	
	BuildGreeting(){
		return % "Hi, my name is " this.name ", and I am " this.age " years old"
	}
	
	CanOrderAlcohol(){
		if (this.age >= 18){
			return true
		}
		return false
	}
}

Re: Access a variable from one function inside another function

Posted: 24 May 2022, 11:08
by Krd
boiler wrote:
20 Feb 2018, 16:03
Another alternative is using ByRef, which allows you to return values directly into the variables in your function call:

Code: Select all

function1(ByRef p1, ByRef p2) {
	p1 := "John"
	p2 := "Jill"
}

function2() {
	function1(person1, person2)
	msgBox, %person1%
	msgBox, %person2%
}

function2()
Almost 4 years later and I found how to use Byref for my needs! Fantastic! :bravo: