Path: csiph.com!usenet.pasdenom.info!gegeweb.org!de-l.enfer-du-nord.net!feeder2.enfer-du-nord.net!feeds.phibee-telecom.net!newsfeed.xs4all.nl!newsfeed5.news.xs4all.nl!xs4all!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; 'received:mail-lpp01m010-f46.google.com': 0.09; 'exception': 0.12; 'def': 0.13; '16,': 0.15; 'argument': 0.15; '**kwargs):': 0.16; 'allocates': 0.16; 'arg': 0.16; 'type:': 0.16; '\xa0def': 0.16; '\xa0for': 0.16; 'cc:addr:python-list': 0.16; 'wrote:': 0.18; 'arguments': 0.18; 'exists': 0.18; 'repeated': 0.18; 'sfxlen:2': 0.19; 'cheers,': 0.20; 'cc:no real name:2**0': 0.21; 'header:In-Reply-To:1': 0.22; 'dictionary': 0.23; '\xa0if': 0.23; 'keyword': 0.24; 'static': 0.24; 'modify': 0.25; 'cc:2**0': 0.26; 'code': 0.26; 'all,': 0.27; 'function': 0.27; 'fact': 0.27; 'raise': 0.28; 'second': 0.28; 'message- id:@mail.gmail.com': 0.29; 'true,': 0.29; 'cc:addr:python.org': 0.29; 'pm,': 0.29; 'arguments.': 0.30; 'collections': 0.30; 'none,': 0.30; 'sets.': 0.30; '(as': 0.31; 'pretty': 0.31; 'version': 0.32; 'adds': 0.32; 'go.': 0.32; 'received:209.85.215.46': 0.32; "i've": 0.32; 'does': 0.32; 'too': 0.33; 'fri,': 0.34; 'duplicate': 0.34; 'function.': 0.34; 'data.': 0.36; 'checks': 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; 'should': 0.38; 'data': 0.38; 'describe': 0.39; 'received:209.85.215': 0.39; 'received:209': 0.39; 'being': 0.40; 'views': 0.40; 'unique': 0.61; 'more': 0.61; 'your': 0.61; 'hope': 0.61; '8bit%:4': 0.63; 'our': 0.63; 'here': 0.64; 'evaluate': 0.71; '--->': 0.84; 'descriptive': 0.84; 'remembering': 0.84; 'to:addr:mail.python.org': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; bh=5lYOmqUQJ8JVs33DE8fNhhdwK4RmOReON3un3ym+lrI=; b=0j3jKgrV6c6oEd1ROq16fvsufzlHIdZLI06pd1Tetb4KXBQFb3osHNFaFbV2+0RFIs drmzwyuLa2vwfCFN5SnrsPBMXr6RUuq7A0t6THMF22LZgyJAZ86lv932U/tUqq+hUEmq wqE2D/rwkV92crx9Jtqoq42qQU353bEMR1Y6gCqsXaXS9twlfn9DEIACax4r8HLJOyIz 0YOyStTDTXeVkyg8lx9bwbIOOSkqWZhVg2rD7N8hXNsdaamINMxLAoUVy7XffM77+Koj BU3c+FfVseC6JMFBECjM7xIFX45xtNrS4/FvU64/g0dpglf37zvEcRAfcfj94Yk1oAzG zfgg== MIME-Version: 1.0 In-Reply-To: <4f63e724$0$1386$4fafbaef@reader1.news.tin.it> References: <4f63e724$0$1386$4fafbaef@reader1.news.tin.it> From: Ian Kelly Date: Mon, 19 Mar 2012 17:20:43 -0600 Subject: Re: Currying in Python To: Kiuhnm Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: python-list@python.org 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: 89 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1332199274 news.xs4all.nl 6982 [2001:888:2000:d::a6]:57160 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:21909 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. That's what it exists for. > =A0 =A0""" Generates a 'curried' version of a function. """ > =A0 =A0def geng(curArgs, curKwargs): > =A0 =A0 =A0 =A0def g(*args, **kwargs): > =A0 =A0 =A0 =A0 =A0 =A0nonlocal f, curArgs, curKwargs, minArgs; =A0 =A0# = our STATIC data > > =A0 =A0 =A0 =A0 =A0 =A0if len(args) or len(kwargs): Collections evaluate as true if they are not empty, so this could just be: if args or kwargs: > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0# Allocates data for the next 'g'. We don'= t want to modify our > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0# static data. > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newArgs =3D curArgs[:]; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newKwargs =3D dict.copy(curKwargs); > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0# Adds positional arguments. > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newArgs +=3D args; > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0# Adds/updates keyword arguments. > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if unique: > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0# We don't want repeated keyword a= rguments. > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for k in kwargs.keys(): > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if k in newKwargs: > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0raise(Exception("R= epeated kw arg while unique =3D True")); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =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. Also, you should use a more specific exception type: if unique and not kwargs.keys().isdisjoint(newKwargs): raise ValueError("A repeated keyword argument was suppl= ied") > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0# Checks whether it's time to evaluate f. > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if minArgs >=3D 0 and minArgs <=3D len(new= Args) + len(newKwargs): With minArgs defaulting to None, that would be: if minArgs is not None and minArgs <=3D len(newArgs) + len(newKwargs): > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return f(*newArgs, **newKwargs); = =A0 =A0# f has enough args > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else: > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return geng(newArgs, newKwargs); = =A0 =A0# f needs some more args > =A0 =A0 =A0 =A0 =A0 =A0else: > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return f(*curArgs, **curKwargs); =A0 =A0# = the caller forced the evaluation > =A0 =A0 =A0 =A0return g; > =A0 =A0return geng([], {}); > > def cur(f, minArgs =3D -1): > =A0 =A0return genCur(f, True, minArgs); > > def curr(f, minArgs =3D -1): > =A0 =A0return genCur(f, False, minArgs); The names "cur" and "curr" are terrible. Good 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. Why not more descriptive names like "curry" and "curry_unique"? That's all I've got. All in all, it's pretty decent for a Python newbie. Cheers, Ian