Path: csiph.com!usenet.pasdenom.info!gegeweb.org!de-l.enfer-du-nord.net!feeder2.enfer-du-nord.net!tudelft.nl!txtfeed1.tudelft.nl!multikabel.net!newsfeed20.multikabel.net!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'args': 0.05; 'subject:Python': 0.05; '"""': 0.07; 'behave': 0.07; 'decent': 0.07; 'type,': 0.07; 'python': 0.08; '"r"': 0.09; '-1.': 0.09; 'be:': 0.09; 'caller': 0.09; 'empty,': 0.09; 'false,': 0.09; 'positional': 0.09; 'exception': 0.12; 'def': 0.13; '16,': 0.15; 'argument': 0.15; '**kwargs):': 0.16; 'allocates': 0.16; 'arg': 0.16; 'defaulting': 0.16; 'naming': 0.16; 'semicolon': 0.16; 'type:': 0.16; '\xc2\xa0if': 0.16; 'cc:addr:python-list': 0.16; 'wrote:': 0.18; 'arguments': 0.18; 'exists': 0.18; 'repeated': 0.18; 'cheers,': 0.20; 'cc:no real name:2**0': 0.21; 'header:In- Reply-To:1': 0.22; 'dictionary': 0.23; 'pep': 0.23; 'received:209.85.213.46': 0.23; 'received:mail- yw0-f46.google.com': 0.23; 'keyword': 0.24; 'static': 0.24; 'modify': 0.25; 'code': 0.26; 'all,': 0.27; 'url:mailman': 0.27; 'function': 0.27; 'fact': 0.27; 'second': 0.28; 'message- id:@mail.gmail.com': 0.29; 'true,': 0.29; 'cc:addr:python.org': 0.29; 'seem': 0.29; 'pm,': 0.29; 'arguments.': 0.30; 'collections': 0.30; 'kelly': 0.30; 'none,': 0.30; 'sets.': 0.30; 'skip:\xc2 20': 0.30; '(as': 0.31; 'pretty': 0.31; 'url:listinfo': 0.32; 'version': 0.32; 'adds': 0.32; 'go.': 0.32; "i've": 0.32; 'rest': 0.32; 'does': 0.32; 'too': 0.33; 'fri,': 0.34; 'duplicate': 0.34; 'function.': 0.34; 'none': 0.35; 'url:python': 0.35; 'data.': 0.36; 'cc:2**1': 0.36; 'checks': 0.37; 'variables': 0.37; 'but': 0.37; 'received:google.com': 0.37; 'skip:" 10': 0.37; 'received:209.85': 0.38; 'enough': 0.38; 'allows': 0.38; 'could': 0.38; 'some': 0.38; 'think': 0.38; 'should': 0.38; 'data': 0.38; 'describe': 0.39; 'url:org': 0.39; 'received:209': 0.39; 'being': 0.40; 'views': 0.40; 'unique': 0.61; 'more': 0.61; 'your': 0.61; 'hope': 0.61; 'march': 0.61; 'our': 0.63; 'here': 0.64; 'below,': 0.64; 'evaluate': 0.71; '--->': 0.84; 'descriptive': 0.84; 'remembering': 0.84 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=fbnc2R+5wb5o6AnXc3VAexkOSwltAGbZicfn50jaoq8=; b=SuPqAlHWpqNvFo2gamP2n/V1ajC2exu1nmuDQclnSa3+Dop2/hr/lCWZADD5OuAb9m XFgO3JME9x71uWK7favcW+6hveLb9Jd5rOEopInBErKQ1ev+ih+1XOiRZMApELOHCRte U3tvJ2544dmZjSf+bADJqtF8zmDADJDAb8MT6Vg60F5gs5JfWBcIfh+6V7EEbqcN3kwR Yab/3dawMcrgVblNMfPpdCV7F9eAjMVcXMI4Y/4x1Q7RXUdH5mbbWseZwKmjO4xLuqwo OcJar6IabtadQ9Ios54yG/02mqu67GPYSfYDnzvY1ZYHjXNm8WI2ZkJhCHmsPKhnWdM8 0I/A== MIME-Version: 1.0 In-Reply-To: References: <4f63e724$0$1386$4fafbaef@reader1.news.tin.it> Date: Tue, 20 Mar 2012 07:11:59 +0000 Subject: Re: Currying in Python From: Arnaud Delobelle To: Ian Kelly Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Cc: python-list@python.org, Kiuhnm X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 115 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1332227523 news.xs4all.nl 6984 [2001:888:2000:d::a6]:35923 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:21919 On 19 March 2012 23:20, Ian Kelly wrote: > I hope you don't mind if I critique your code a bit! > > On Fri, Mar 16, 2012 at 7:21 PM, Kiuhnm > wrote: >> Here we go. >> >> ---> >> def genCur(f, unique =3D True, minArgs =3D -1): > > It is customary in Python for unsupplied arguments with no default to > use the value None, not -1. =C2=A0That's what it exists for. > >> =C2=A0 =C2=A0""" Generates a 'curried' version of a function. """ >> =C2=A0 =C2=A0def geng(curArgs, curKwargs): >> =C2=A0 =C2=A0 =C2=A0 =C2=A0def g(*args, **kwargs): >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nonlocal f, curArgs, curKwargs,= minArgs; =C2=A0 =C2=A0# our STATIC data I don't know if all the rest of the code is below, but this line above would only be necessary if you want to rebind f, curArgs, minArgs. You don't seem to do it, so I think this line is unnecessary. Also, your naming of variables disagrees with PEP 8 :) >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if len(args) or len(kwargs): > > Collections evaluate as true if they are not empty, so this could just be= : > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if args or kwargs: > >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Allocates data = for the next 'g'. We don't want to modify our >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# static data. >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0newArgs =3D curAr= gs[:]; Semicolon to end a statement? >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0newKwargs =3D dic= t.copy(curKwargs); >> >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Adds positional= arguments. >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0newArgs +=3D args= ; >> >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Adds/updates ke= yword arguments. >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if unique: >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# W= e don't want repeated keyword arguments. >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for= k in kwargs.keys(): >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0if k in newKwargs: >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0raise(Exception("Repeated kw arg while unique = =3D True")); >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0newKwargs.update(= kwargs); > > Since you're writing this for Python 3 (as evidenced by the use of the > nonlocal keyword), you could take advantage here of the fact that > Python 3 dictionary views behave like sets. =C2=A0Also, you should use a > more specific exception type: > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if unique and not = kwargs.keys().isdisjoint(newKwargs): > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rais= e ValueError("A repeated keyword argument was supplied") > >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Checks whether = it's time to evaluate f. >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if minArgs >=3D 0= and minArgs <=3D len(newArgs) + len(newKwargs): > > With minArgs defaulting to None, that would be: > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if minArgs is not = None and minArgs <=3D len(newArgs) + > len(newKwargs): > >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret= urn f(*newArgs, **newKwargs); =C2=A0 =C2=A0# f has enough args >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else: >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret= urn geng(newArgs, newKwargs); =C2=A0 =C2=A0# f needs some more args >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else: >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return f(*curArgs= , **curKwargs); =C2=A0 =C2=A0# the caller forced the evaluation >> =C2=A0 =C2=A0 =C2=A0 =C2=A0return g; >> =C2=A0 =C2=A0return geng([], {}); >> >> def cur(f, minArgs =3D -1): >> =C2=A0 =C2=A0return genCur(f, True, minArgs); >> >> def curr(f, minArgs =3D -1): >> =C2=A0 =C2=A0return genCur(f, False, minArgs); > > The names "cur" and "curr" are terrible. =C2=A0Good names should describe > what the function does without being too onerous to type, and the > addition of the duplicate "r" is not an obvious mnemonic for > remembering that the first one prohibits duplicate keyword arguments > and the second one allows them. =C2=A0Why not more descriptive names like > "curry" and "curry_unique"? > > That's all I've got. =C2=A0All in all, it's pretty decent for a Python ne= wbie. > > Cheers, > Ian > -- > http://mail.python.org/mailman/listinfo/python-list