From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=AWL,SPF_NEUTRAL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id 2F16EBC0A for ; Thu, 15 Mar 2007 04:44:31 +0100 (CET) Received: from an-out-0708.google.com (an-out-0708.google.com [209.85.132.248]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id l2F3iUne008213 for ; Thu, 15 Mar 2007 04:44:30 +0100 Received: by an-out-0708.google.com with SMTP id d26so21035and for ; Wed, 14 Mar 2007 20:44:30 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=Lf8+i43SnNTlPyIGzwxNp18bnLrzo7j90eg92f/kxTI4x9Ropi30hBkVoj7N1dSUL9ytt+1kUeHach//shzyU05DNrXyUvnwlMOoZdT7eS5ULbnmWv3eveWBrWAduxWxJhpiD4Ahd4+rkULqnKzpKvfbe8xq4WFNjY4BMPZPS7M= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=WzACIV/XW7jmZJBhGrcUall8l6N5dT5g0d4jcDH9EcOMsFXrU0zE+6vDg5WeOl0QfTRKVesiNgODkSl0K5SvkzslxRqXhmpor1rK3T3WNPyEoSjvUDUX2XtGYV4LSdbz8a1g8BmZUw4mXc6VSPHdTd8C+kV5mgx1c335QtK0cuI= Received: by 10.114.131.2 with SMTP id e2mr55569wad.1173930269468; Wed, 14 Mar 2007 20:44:29 -0700 (PDT) Received: by 10.114.241.6 with HTTP; Wed, 14 Mar 2007 20:44:29 -0700 (PDT) Message-ID: <875c7e070703142044v2bc61765i3ea00d463a8f77ed@mail.gmail.com> Date: Wed, 14 Mar 2007 22:44:29 -0500 From: "Chris King" To: ian Subject: Re: [Caml-list] Style and organization of code Cc: caml-list@inria.fr In-Reply-To: <45F87661.4020504@softhome.net> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <45F87661.4020504@softhome.net> X-j-chkmail-Score: MSGID : 45F8C11E.000 on concorde : j-chkmail score : X : 0/20 1 0.000 -> 1 X-Miltered: at concorde with ID 45F8C11E.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; hash:01 fwiw:01 genlex:01 lexer:01 kwd:01 hashtbl:01 iter:01 hashtbl:01 kwd:01 fist:98 softhome:98 instinct:98 wrote:01 token:01 caml-list:01 On 3/14/07, ian wrote: > Say I have a function called "solveHardProblem". solveHardProblem relies on > several helper functions, which are not going to be useful to any other > functions in the program. So, my first instinct would be to define all the > helpers using let blocks within the definition of solveHardProblem. I usually do exactly that. I think it's fine to have a long let like this, so long as it's made up of small, manageable pieces. The biggest problem is that your arguments are now miles away from the definition of your function, but this can be solved with something like the following: let solve_hard_problem = let solve_simpler_problem x = ... and solve_something_else x = ... in fun x y z -> [code goes here] This is also a good trick for moving a global variable (such as a unique ID counter or a hash table) into the scope of the function that uses it. FWIW I've seen some examples of this style in the standard library. genlex.ml has a 150+ line function of the form: let make_lexer keywords = let kwd_table = Hashtbl.create 17 in List.iter (fun s -> Hashtbl.add kwd_table s (Kwd s)) keywords; let ident_or_keyword id = ... and keyword_or_error c = ... [snip] in fun input -> Stream.from (fun count -> next_token input) Since the "keywords" argument is needed by the helper functions, it appears at the top in the let, but "input" isn't and so it was moved to the bottom in the fun. None of the helper functions are much longer than one screenful so it makes for easy reading.