3

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?

asked Jul 24, 2016 at 19:31
3
  • There is no "right way" to think about this. It really depends on what you're optimizing for. Commented Jul 24, 2016 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. Commented Jul 24, 2016 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). Commented Jul 24, 2016 at 23:22

2 Answers 2

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.

answered Jul 25, 2016 at 2:11
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.

answered Jul 25, 2016 at 1:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.