On Thursday 17 November 2016 04:52, Rob Gaddi wrote: >> import library >> result = library.make_spam(arg) >> >> >> versus: >> >> import library >> make_spam = library.make_library() >> result = make_spam(arg) >> >> What a drag. >> >> > > And there you have it; an entire extra line at import time.
Multiplied by every function that has a configurable default. Multiplied by every module that imports any of those functions, *whether or not* they change the default. If there are four functions, the user has to do this: import library make_spam = library.make_spam_factory() make_eggs = library.make_eggs_factory() make_cheese = library.make_cheese_factory() make_toast = library.make_toast_factory() before they can even begin to do what they actually want to do, which is make spam, eggs, cheese etc. And yes, there's likely to be four or more of these functions. You can slightly work around this by offering pre-built functions that avoid needing to call the factory, but this is adding more complexity to what really isn't that complicated: a function with a user-configurable default setting. > It's the answer that's explicit. An explicit solution would be to offer no default setting at all and require the user to always provide the setting as an explicit argument to the function. But despite the Zen of Python (which has always been intended as a humorous and intentionally self-contradictory way to think about the design of the language, not as a way to shut down discussion), explicit is not ALWAYS better than implicit. That's why we have default values, and why we don't require imports to be written like this: # explicitly giving the name to bind to is better import math as math It's very unusual to require the caller of a library function to create the function first: factory functions and builders are a powerful technique, but they're more useful for the library, less so for the user of the library. Conceptually, my library offers a simple function. The API of functions is well-known: import library result = library.function(arg) The API for providing user-configurable default values is well-known and easily understood: you set a global variable (or even an environment variable): DEFAULT = foo result = library.function() There's about half a century of programming practice and probably ten billion person-hours of collective experience behind this idea. Whereas fancy tricks involving factory functions, builders and class-based solutions are *much* less well-known or understood. Outside of functional programming circles, the idea of calling a function to return a function is often considered mind-blowing voodoo. > It's versatile (you can create > multiple library instances with different defaults if that sort of thing > is really your jam), Indeed: factory functions are great. But I'm saying that as the writer of the library, not the user of the library. Can you imagine expecting users to do this? from math import trig sin = trig.build('sine') result = sin(0.1) It might only be one extra line of code, but conceptually it is an order of magnitude more complex. The user has to comprehend factory functions and first- class functions as values before they can even begin to understand this. > and it uses no tricky mechanisms that unskilled > programmers won't understand. The internal details of how the implementation works is not important to the user. They only need to understand that the "scheme" parameter takes its value from the first found of: - an explicit argument - a global variable called "WHATEVER" - the library default which is pretty simple to understand and use. -- Steven 299792.458 km/s — not just a good idea, it’s the law! -- https://mail.python.org/mailman/listinfo/python-list