Hoisting: Does the Order Matter for Functions in Dart (and Python)?
Tags: dart, python, codenewbie, beginners
Published: 2023-09-17 03:07:49

## Question 1

I wonder if the order matters for the declaration of functions in Dart. So I asked ChatGPT on this one. Let's suppose this code exists:

```dart
void main() {
  greet();
}

void greet() {
  print('Hello!');
}
```

> If I swap the order, does the Dart program throw an error or work just fine?

## ChatGPT Reply 1

> In Dart, the order in which functions are declared does not matter. Dart supports hoisting, which means you can call a function before its declaration in the code file. The following two versions of the code are equivalent:

Version 1:

```dart
void main() {
  greet();
}

void greet() {
  print('Hello!');
}
```

Version 2:

```dart
void greet() {
  print('Hello!');
}

void main() {
  greet();
}
```

Both versions will produce the same output ("Hello!") when executed. You can define `main()` before `greet()` or vice versa; the Dart compiler will correctly identify and link the function calls no matter the order.

However, this principle applies to top-level functions and does not extend to local functions (functions declared within other functions). Local functions must be declared before they are called within their containing function.

## Question 2

Since I come from Python I try to ask this as well.

> Does Python support hoisting as well?

## ChatGPT Reply 2

> No, Python does not support hoisting in the way that languages like Dart or JavaScript do. In Python, you must define a function before you call it. Consider the following example:

This will raise an error:

```python
say_hello()

def say_hello():
    print("Hello!")
```

The error will state that `say_hello` is not defined because Python will not have seen the definition of `say_hello` by the time it tries to call it.

However, the following will work:

```python
def say_hello():
    print("Hello!")

say_hello()
```

Here, `say_hello` is defined before it is called, so the Python interpreter knows what to do when `say_hello()` is encountered.

Classes and functions need to be defined before they are used in the Python code execution flow. If you attempt to use a function or class before declaring it, you will get a `NameError`.

# Question 3

This answer doesn't necessarily address my intention since I can work with unorder methods (not functions even though methods behave like functions in a bit). So I ask the following question.

> Does hoisting work in method instead of function in Python?

# ChatGPT Reply 3

> In Python, the concept of hoisting doesn't apply to either functions or methods. All names (variables, functions, methods, classes, etc.) must be defined before they are used, regardless of whether they are part of a class (as methods) or stand-alone functions.

Here are some examples to clarify:

### Functions
This will **not** work:

```python
call_function()

def call_function():
    print("Function called.")
```

This will work:

```python
def call_function():
    print("Function called.")

call_function()
```

### Methods
This will **not** work:

```python
class MyClass:
    def method_one(self):
        self.method_two()

    def method_two(self):
        print("Method two called.")

# Create an instance
obj = MyClass()

# Call method_one (which in turn calls method_two)
obj.method_one()  # This will work because method_two is defined before it is called
```

This will work, but the order in which the methods are defined within the class doesn't matter:

```python
class MyClass:
    def method_two(self):
        print("Method two called.")

    def method_one(self):
        self.method_two()

# Create an instance
obj = MyClass()

# Call method_one (which in turn calls method_two)
obj.method_one()  # This will work because method_two is defined in the class before it is called
```

As you can see, in Python, what matters is that the function or method is defined before it is used, not the order in which they are written in the code.

## Question 4

The previous reply did contradict itself. So I complain.

> Still don't understand this "This will work, **but the order in which the methods are defined within the class doesn't matter**:". If the order doesn't matter, the first code of the block of the method should work just fine.

## ChatGPT Reply 4

> I apologize for the confusion. My explanation was unclear. You are correct that **the order of method definitions within a class in Python doesn't matter. All methods within a class are available once the class definition is complete, regardless of the order in which they are defined.** Therefore, you can indeed call any method from any other method in the same class, regardless of their order.

The first block of code with methods should work fine because both `method_one` and `method_two` are defined in the class:

```python
class MyClass:
    def method_one(self):
        self.method_two()

    def method_two(self):
        print("Method two called.")

# Create an instance
obj = MyClass()

# Call method_one (which in turn calls method_two)
obj.method_one()  # This will work because method_two is defined before it is called
```

In this case, the order of `method_one` and `method_two` doesn't matter; both will work as expected regardless of which one is defined first. Thank you for catching that mistake, and I apologize for the oversight.

## Question 5

I just need to clarify this time.

> So hoisting work only for methods within class?

## ChatGPT Reply 5

> The concept of "hoisting" doesn't strictly apply to Python methods in the same way it does for variables and functions in languages like JavaScript. In Python, both functions and methods need to be defined before they are called, but within a class definition, methods are all available to each other regardless of their order in the source code.

In the following example, both `method_one` and `method_two` are part of the class definition, and they can call each other regardless of the order in which they appear:

```python
class MyClass:
    def method_one(self):
        self.method_two()

    def method_two(self):
        print("Method two called.")
```

This "availability" of methods within the same class isn't typically described as hoisting in Python. Rather, it's a feature of how Python's object-oriented system works. All methods within a class are available to each other once the class definition is complete, regardless of their order of definition.