1

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.

unlockme
  • 3,897
  • 3
  • 28
  • 42
  • 1
    No, the outer brackets are only meant to allow proper indentation. – Willem Van Onsem Jun 07 '18 at 09:24
  • @Willem Van Onsem, how does python allow that. I thought python is space indented. Can I also use it elsewhere in my code. – unlockme Jun 07 '18 at 09:30
  • this is exactly why: because Python is space intended. – Willem Van Onsem Jun 07 '18 at 09:31
  • This has blown my head out. So you are saying the outer brackets are not instantiating a function inside a tuple ? @WillemVanOnsem – unlockme Jun 07 '18 at 09:33
  • no, for a singleton tuple a tailing comma is required, and for 2-tuples or more-tuples, there should be commas, but here there are no commas, but dots, used for attribute access. – Willem Van Onsem Jun 07 '18 at 09:34
  • So this means I could as well write this function as `split_clerk_warehouse = flow.Split().Next(this.shipment_type).Next(this.package_goods)' – unlockme Jun 07 '18 at 09:37
  • Exactly. You can for example edit the file, and test it. – Willem Van Onsem Jun 07 '18 at 09:38
  • Ok thanks, @WillemVanOnsem. may be you could add an answer and I accept it to your credit – unlockme Jun 07 '18 at 09:44
  • btw, there is another possible style for formatting flow code - is to use linebreaks inside method call parenthesis https://github.com/viewflow/cookbook/blob/master/custom_ui/demo/parcel/flows.py#L17 – kmmbvnr Jun 07 '18 at 11:22

1 Answers1

3

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).

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555