From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by walapai.inria.fr (8.13.6/8.13.6) with ESMTP id q06AYE4u002308 for ; Fri, 6 Jan 2012 11:34:14 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AlEBAErNBk/RVaC2kGdsb2JhbABDhQ+nMAgiAQEBAQkJDQcUBCGBcgEBAQMBDgQCDx0BJBQBAwELAQUFCw8CJgICIhIBBQEcBjWHWAiZNQqLH4M3hFeJMAIFC4EkiUyBFgSVB41+PYFNgi4 X-IronPort-AV: E=Sophos;i="4.71,467,1320620400"; d="scan'208";a="138111367" Received: from mail-gy0-f182.google.com ([209.85.160.182]) by mail1-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 06 Jan 2012 11:34:11 +0100 Received: by ghrr16 with SMTP id r16so806638ghr.27 for ; Fri, 06 Jan 2012 02:34:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=jH4+yN33VM5NYK+Y/3uuB7pvrnCT33TUtkZXB8dGBbY=; b=aHfjBTD7h8nzKVl2/OHQQkDNid1Lpo66ghq4RocN1pZjpo6u7eqgCPz/DTQ4XJt9Cc r1hvpVRKbqmnI3eRiBA7kD8xbhqqyVIMSvbKoek0r/tTulgZFSusUDJbnXpigRIUEQzM OehovWElm+HtfPbnLzLPsu+ZplwhQ5uTOTsvM= MIME-Version: 1.0 Received: by 10.236.128.207 with SMTP id f55mr6111111yhi.83.1325846048761; Fri, 06 Jan 2012 02:34:08 -0800 (PST) Sender: daniel.c.buenzli@gmail.com Received: by 10.146.95.8 with HTTP; Fri, 6 Jan 2012 02:34:08 -0800 (PST) In-Reply-To: References: <20120105200442.GA17669@annexia.org> <20120105213636.GA30972@annexia.org> Date: Fri, 6 Jan 2012 11:34:08 +0100 X-Google-Sender-Auth: ls_mIOunn1eGo-cmsagRBmV5MKc Message-ID: From: =?UTF-8?Q?Daniel_B=C3=BCnzli?= To: ivan chollet Cc: caml-list Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by walapai.inria.fr id q06AYE4u002308 Subject: Re: [Caml-list] Examples where let rec is undesirable > Sorry Richard I should have elaborated a bit more. > I guess there are a couple of examples in the literature, but one of them > comes to my mind, consider the following code snippet: > > let fd = Unix.open "myfile1" ... in > let fd = Unix.open "myfile2" ... in > ... (some code) > Unix.close fd > > This causes a file descriptor leak that is hard to detect statically in general. If you mean detect statically by a _program_, then this makes absolutely no difference. A static analyzer could alpha rename the term so that each name is unique or work with De Bruijn indexes without changing the complexity of the problem. If you mean detect statically by a _programmer_ then yes, variable shadowing can be a good tool to write obfuscated code. > As a rule of thumb, I think it's better to give different conceptual objects > different variable names, which also improves self-documentation. Agreed. (I'm sure also got caught at least once by something like your first example). > Within nested scopes, all objects declared with a let-binding are usually distinct > conceptually. Not necessarily. I think what Ɓukasz mentions about incrementally transformed values and cognitive burden is very true and in these cases I wouldn't consider name recycling a bad style. One example is working with a purely functional datastructure like Set.t where you need to perform a few applications before getting to the only value you are interested in. The alternative would be to simply not name the intermediate results, it may be possible but sometimes writing the sequence of application explicitly by a serie of lets makes the presentation and the code clearer [1]. Best, Daniel [1] Somewhat related is point-free style programming of which haskellers are very fond of. A little bit of it is nice, but I think it sometimes makes the cognitive burden too high. There's a balance between conciseness and readability. Somehow programmers are obsessed by the former at the detriment of the latter, but a good balance is needed. This example (from this [2] wikipedia page) speaks for itself : mf criteria operator list = filter criteria (map operator list) vs mf = (. map) . (.) . filter I'm sure we all agree the former is easier to grasp. [2] http://en.wikipedia.org/wiki/Point-free_programming