Talk:Cheryl's birthday: Difference between revisions

From Rosetta Code
Content added Content deleted
(pythonnet)
Line 52: Line 52:
, '__str__', '__subclasshook__']
, '__str__', '__subclasshook__']
</pre><br>or The Python Data Analysis Library with which after establishing dates as a data frame you could write something like dates.groupby('month').count()--[[User:Nigel Galloway|Nigel Galloway]] ([[User talk:Nigel Galloway|talk]]) 13:39, 26 October 2018 (UTC)
</pre><br>or The Python Data Analysis Library with which after establishing dates as a data frame you could write something like dates.groupby('month').count()--[[User:Nigel Galloway|Nigel Galloway]] ([[User talk:Nigel Galloway|talk]]) 13:39, 26 October 2018 (UTC)
: Thanks Nigel – I'll take a look. [[User:Hout|Hout]] ([[User talk:Hout|talk]]) 13:57, 26 October 2018 (UTC)

Revision as of 13:59, 26 October 2018

Improve tag on Python entry

I added an improve tag on the Python entry as it does not look or read like idiomatic Python. To avoid an edit war I will state my reasons:

  1. Commented type annotations read like those from a different programming language.
  2. Use of map/filter over comprehensions.
  3. Use of trivial functions: fst, id, _not, snd, swap
  4. Overwriting a builtin name: id
  5. main() without `if __name__ == "__main__"`
  6. Shares structure and naming with examples from other languages.

It reads like a translation from another language and RC is about idiomatic code. Paddy3118 (talk) 07:14, 26 October 2018 (UTC)

I have removed that obdurately tendentious 'improvement' tag, and will suggest a practical solution. The 3 points are these:
  1. Functional composition, structured around immutable references, is an important and distinct current of coding architecture, with strong advantages for some contexts, and needed by significant numbers of those who come to Python principally for its libraries. The former BDFL, now outgrown by the community, was (1). viscerally and declaredly hostile to the use of this mode in Python. (2). Failed, despite his most strenuous efforts, to persuade the Python development community that he was being constructive on this issue. See Guido's failed attempt to remove 'reduce', and his intemperate relegation of it to 'functools', while describing this as 'a dumping ground for things that don't interest me'.
  2. The former BDFL's visceral but unreasoned ('reminds me of lemon juice' etc etc) hostility to the composition of pure functions, and the disentanglement of value definition from IO, leaves the notion of 'Pythonic' *at best* limping on a pair of very uneven legs, with one (imperative) leg fairly muscular, and the other etiolated and deliberately shackled. In short, 'Pythonic' goals, well-defined and helpful for imperative coding, are quite deliberately bad, and completely dysfunctional, for functional code. This is a problem. Not an aspirational ideal.
  3. While 'Pythonic' constraints are good only for imperative code, mathematical constraints are deeply and inevitably structuring in the composition of pure functions. Research on, and exposition of, these constraints, and of their mathematical underpinning, can certainly use language-independent notations, (See the classic Bird and Wadler 1988, for example) but tends, in practice, to use Haskell/ML notation, and to adopt generic function names from the ML tradition (used even in Bird and Wadler), which serve as a kind of lingua franca for functional programming. The function names (and style of type annotations) used in Haskell (which is the main vehicle of the academic research) are also commonly used in projects aiming to strengthen the functional use of other languages. This is true not only of projects in other languages (see for example Ramda and other JS functional libraries) but even of Python itself. When Python library developers need names for functional abstractions, they also, like others, naturally turn to the norms established by the ML/Haskell tradition. Haskell and Standard ML (SML), together with APL, are indeed explicitly mentioned at the top of the itertools documentation page. Hence we see in Python not only the standard functional terms like map and filter, but also dropwhile, takewhile, groupby, cycle, repeat, etc etc. In Python, as in other languages, when you need to strengthen functional muscle, established best practice is to turn to the Haskell/ML abstractions and names, which provide the widely shared lingua franca of the research.


The particular points of visceral resistance which you list above arise, almost without exception, from the difference between imperative and functional code, and from the scar tissue of Guido's now overturned dictatorship, which deliberately made 'Pythonic' guidelines incompatible with best functional practice.

  1. List comprehensions are, mathematically, concat . map (or concatMap) over functions returning list-wrapped values. This is functionally distinct from bare map and filter. Ironically all of these, are, in the underlying math of function composition, specialised variants of fold/reduce, which Guido didn't fully understand ('I need pencil and paper' etc) and which the community as a whole did, and therefore would not let him ban.
  2. Raising trivial operators to first class functions is absolutely correct, and indeed logically inevitable, when the former are passed as arguments to higher-order functions. That is precisely why Python has an operator library.
  3. 'Shares structure and naming with examples from other languages' Of course !!! Functional solutions inevitably (and very helpfully) resemble each other. They are structured by the same mathematical constraints on function composition and immutable names. As for using standard Haskell/SML names for standard abstractions, that is already a well-established and explicitly documented best practice in Python. (See the itertools documentation page). In the context of a Rosetta project, this is particularly helpful. The shared names facilitate cross-reference, and the differing implementations of the same abstraction are instructive.


Suggested compromise. Given that the Guidonic/Pythonic patterns are in many cases deliberately and explicitly incompatible with good functional practice, I would propose that I explicitly label my contributions as 'Functional', distinguishing them from any neighbouring imperative variants.

(Your comment on id() is helpful, I can't remember why I explicitly defined one, and I am very happy to take a look at that. `if __name__ == "__main__"` I just happen to find rather noisy and ugly, and a bit raucously redundant in this context, but I'll also look at that, in the interests of better functional/imperative relations :-)

Guido really was a bit naughty and deliberately destructive on the issue of composing pure functions. You can get some benefits from a BDFL, particularly in the early stages of a project, but in his case you paid a real, and not unnoticed price as well. That's why the PEP processes became unsustainably painful for him. Time to heal and remedy that now, if the language is to thrive, become better optimised for rapid and reliable coding.

Composition of pure functions is not going to go away. Time, math, and multiprocessors are all on its side. As for 'idiomatic', with functional code, that maps not to the deliberately functional-dsyfunctional 'Pythonic' verities, but to the standard use of standard functional abstractions, with names taken, by default, from the very same idiom as Python's takewhile, dropwhile and groupby etc Hout (talk) 11:16, 26 October 2018 (UTC)

PS Imperative coding seldom works well in my context, tho I sometimes use it at a latish stage if I happen to need to trade away some reliability to gain a bit of compression (a bit like JPEG in lieu of PNG), but I have absolutely no objection at all to others working with it. Rather than slapping banning orders on functional drafts that you fear might differ from the ex-BDFL's very quirky and personal preferences, why don't you just add an imperative/'Pythonic' variant of your own ? A much more interesting and constructive form of criticism or commentary. Hout (talk) 11:23, 26 October 2018 (UTC)
Hi Hout, have you tried pythonnet ..."Python for .NET ( pythonnet ) is a package that gives Python programmers nearly seamless integration with the .NET 4.0+ Common Language Runtime (CLR)"... Aggregate -> reduce; Where -> filter; Select -> map
>>>clr.ImportExtensions(System.Linq)
>>>dir (List)
['Add', 'AddRange', 'Aggregate', 'All', 'Any', 'AsEnumerable', 'AsParallel', 'AsQueryable', 'AsReadOnly', 'Average', 'Bi
narySearch', 'Capacity', 'Cast', 'Clear', 'Concat', 'Contains', 'ConvertAll', 'CopyTo', 'Count', 'DefaultIfEmpty', 'Dist
inct', 'ElementAt', 'ElementAtOrDefault', 'Enumerator', 'Equals', 'Except', 'Exists', 'Find', 'FindAll', 'FindIndex', 'F
indLast', 'FindLastIndex', 'First', 'FirstOrDefault', 'ForEach', 'GetEnumerator', 'GetHashCode', 'GetRange', 'GetType',
'GroupBy', 'GroupJoin', 'IndexOf', 'Insert', 'InsertRange', 'Intersect', 'IsReadOnly', 'IsSynchronized', 'Item', 'Join',
 'Last', 'LastIndexOf', 'LastOrDefault', 'LongCount', 'Max', 'MemberwiseClone', 'Min', 'OfType', 'OrderBy', 'OrderByDesc
ending', 'ReferenceEquals', 'Remove', 'RemoveAll', 'RemoveAt', 'RemoveRange', 'Reverse', 'Select', 'SelectMany', 'Sequen
ceEqual', 'Single', 'SingleOrDefault', 'Skip', 'SkipWhile', 'Sort', 'Sum', 'SyncRoot', 'Take', 'TakeWhile', 'ToArray', '
ToDictionary', 'ToList', 'ToLookup', 'ToString', 'TrimExcess', 'TrueForAll', 'Union', 'Where', 'Zip', '__add__', '__clas
s__', '__contains__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__',
 '__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__'
, '__str__', '__subclasshook__']


or The Python Data Analysis Library with which after establishing dates as a data frame you could write something like dates.groupby('month').count()--Nigel Galloway (talk) 13:39, 26 October 2018 (UTC)

Thanks Nigel – I'll take a look. Hout (talk) 13:57, 26 October 2018 (UTC)