Search code examples
djangoparenthesesdjango-viewflow

Use of paratheses symbols in django-viewflow flow


I have been at a loss understanding the use of parentheses in django-viewflow flow code. For example in the code below

start = (
    flow.Start(views.StartView)
    .Permission('shipment.can_start_request')
    .Next(this.split_clerk_warehouse)
)

# clerk
split_clerk_warehouse = (
    flow.Split()
    .Next(this.shipment_type)
    .Next(this.package_goods)
)

from here

It seems as though, a tuple containing functions is assigned to start and to split_clerk_warehouse e.t.c. What does it mean. From my best guess it would seem that the .Next functions accept a tuple as input.

NOTE I do understand the method chaining used here. I am just at a loss to understand the use of braces.

Thanks.


Solution

  • If I understand correctly, you wonder what the use is of the outer brackets.

    Let us first write the (first, but applicable to the second) statement without outer brackets:

    start = flow.Start(views.StartView).Permission('shipment.can_start_request').Next(this.split_clerk_warehouse)
    

    This is exactly equivalent to code in your sample. But you probably agree that this is quite unreadable. It requires a user to scroll over the code, and furthermore it is a long chain of characters, without any structure. A programmer would have a hard time understanding it, especially if - later - we would also use brackets inside the parameters of calls.

    So perhaps it would make sense to write it like:

    start = flow.Start(views.StartView).
                 Permission('shipment.can_start_request').
                 Next(this.split_clerk_warehouse)

    But this will not work: Python is a language that uses spacing as a way to attach semantics on code. As a result it will break: Python will try to parse the separate linkes as separate statements. But then what to do with the tailing dot? As a result the parser would error.

    Now Python has some ways to write statements in a multi-line fashion. For example with backslashes:

    start = flow.Start(views.StartView). \
                 Permission('shipment.can_start_request'). \
                 Next(this.split_clerk_warehouse)

    with the backslash we specify that the next line actually belongs to the current one, and thus it is parsed like we wrote this all on a single line.

    The disadvantage is that we easily can forget a backslash here, and this would again let the parser error. Furthermore this requires linear work: for every line we have to add one element.

    But programming languages actually typically have a feature that programmers constantly use to group (sub)expressions together: brackets. We use it to give precedence (for example 3 * (2 + 5)), but we can use it to simply group one expression over multiple lines as well, like:

    start = (
        flow.Start(views.StartView)
        .Permission('shipment.can_start_request')
        .Next(this.split_clerk_warehouse)
    )

    Everything that is within the brackets belongs to the same expression, so Python will ignore the new lines.

    Note that tuple literals also use brackets. For example:

    ()              # empty tuple
    (1, )           # singleton tuple (one element)
    (1, 'a', 2, 5)  # 4-tuple
    

    But here we need to write a comma at the end for a singleton tuple, or multiple elements separated by comma's , (except for the empty tuple).