2

Suppose I have a function f that uses two helper functions h and g to get the job done. There are two possible ways of dealing with this situation.

(1) take explicit arguments and returns new objects from each helper function:

def f(x):
    def h(x):
        <do something>
        return y
    def g(y):
        <do something else>
        return z
    return g(h(x))   \\ x remains unchanged

(2) use the scope of f to access and mutate the original argument until it is at the desired state:

def f(x):
    def h():
        <do something>
    def g():
        <do something else>
    h()
    g()
    return x       \\ x is now different

I like situation (1) because it think it is easier to understand what is happening, but I don't really have any concrete reasons for why (1) is better other than it makes more sense to me.

What is the right way to think about this?

  • There is no "right way" to think about this. It really depends on what you're optimizing for. – MetaFight Jul 24 '16 at 22:38
  • Are there certain optimization cases where I might want to go with one or the other? I don't want to take on additional costs by accident. – Logister Jul 24 '16 at 23:15
  • I wasn't specifically talking about performance optimisations, though that might be something you'd chose to optimise for. Other things you might find yourself optimising for are things like readability and maintainability. When optimising there are usually trade-offs. For example, optimising for maintainability may reduce performance (and vice versa). – MetaFight Jul 24 '16 at 23:22
3

Neither. Usually in this situation, you do not want to mutate x, but you do want to take advantage of it already being in scope. This gives you:

def f(x):
    def h():
        <do something using x>
        return y
    def g(y):
        <do something else>
        return z
    return g(h())

These functions are very small typically, and using closed-over variables is to be expected and usually simplifies the interface.

|improve this answer|||||
2

Your option 1 allows x, y, and z to be bound only once, and remain immutable. Many types of languages are moving in this direction, for example, Swift (a strongly typed language) has a let statement that introduces a variable with an immutable binding; Javascript (a dynamically or untyped language depending on how you look at it) has a const declaration for introducing a variable with an immutable binding. Immutable bindings make programs easier to maintain.

Your option 1 allows x, y, and z each to be a different type, which is significant for statically typed languages, and yet also significant for programmers to reason over code in dynamically typed languages. Even in a dynamically typed languages, we often are able to provide type hints or annotations; this is precluded by option 2 unless x y and z happen all to have the same type.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.