* [Caml-list] is there a more concise way to write this? @ 2012-01-20 6:38 Martin DeMello 2012-01-20 6:46 ` Valentin ROBERT ` (3 more replies) 0 siblings, 4 replies; 27+ messages in thread From: Martin DeMello @ 2012-01-20 6:38 UTC (permalink / raw) To: OCaml List let a = match (out, value) with (true, true) -> [o; v] | (false, true) -> [v] | (true, false) -> [o] | (false, false) -> [] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 6:38 [Caml-list] is there a more concise way to write this? Martin DeMello @ 2012-01-20 6:46 ` Valentin ROBERT 2012-01-20 6:58 ` Martin DeMello ` (2 more replies) 2012-01-20 8:52 ` Lin ` (2 subsequent siblings) 3 siblings, 3 replies; 27+ messages in thread From: Valentin ROBERT @ 2012-01-20 6:46 UTC (permalink / raw) To: Martin DeMello; +Cc: OCaml List [-- Attachment #1: Type: text/plain, Size: 733 bytes --] I guess you can write it like: let a = (if out then [o] else []) @ (if value then [v] else []) But it's not particularly more pleasant to the eye. Still it reduces the exponential explosion of the code, at a small additional cost (the @), I believe. On Fri, Jan 20, 2012 at 07:38, Martin DeMello <martindemello@gmail.com>wrote: > let a = match (out, value) with > (true, true) -> [o; v] > | (false, true) -> [v] > | (true, false) -> [o] > | (false, false) -> [] > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa-roc.inria.fr/wws/info/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > > [-- Attachment #2: Type: text/html, Size: 1388 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 6:46 ` Valentin ROBERT @ 2012-01-20 6:58 ` Martin DeMello 2012-01-20 8:37 ` David Allsopp 2012-01-20 8:37 ` Sebastien Ferre 2 siblings, 0 replies; 27+ messages in thread From: Martin DeMello @ 2012-01-20 6:58 UTC (permalink / raw) To: Valentin ROBERT; +Cc: OCaml List thanks, that does reduce the potential explosion, which was my main concern. it even looks pleasant enough if you add a linebreak in the middle. martin On Thu, Jan 19, 2012 at 10:46 PM, Valentin ROBERT <valentin.robert.42@gmail.com> wrote: > I guess you can write it like: > > let a = (if out then [o] else []) @ (if value then [v] else []) > > But it's not particularly more pleasant to the eye. > Still it reduces the exponential explosion of the code, at a small > additional cost (the @), I believe. > > On Fri, Jan 20, 2012 at 07:38, Martin DeMello <martindemello@gmail.com> > wrote: >> >> let a = match (out, value) with >> (true, true) -> [o; v] >> | (false, true) -> [v] >> | (true, false) -> [o] >> | (false, false) -> [] >> >> -- >> Caml-list mailing list. Subscription management and archives: >> https://sympa-roc.inria.fr/wws/info/caml-list >> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >> Bug reports: http://caml.inria.fr/bin/caml-bugs >> > ^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [Caml-list] is there a more concise way to write this? 2012-01-20 6:46 ` Valentin ROBERT 2012-01-20 6:58 ` Martin DeMello @ 2012-01-20 8:37 ` David Allsopp 2012-01-20 13:29 ` Edgar Friendly 2012-01-20 8:37 ` Sebastien Ferre 2 siblings, 1 reply; 27+ messages in thread From: David Allsopp @ 2012-01-20 8:37 UTC (permalink / raw) To: Valentin ROBERT, Martin DeMello; +Cc: OCaml List Valentin ROBERT wrote: > I guess you can write it like: > > let a = (if out then [o] else []) @ (if value then [v] else []) > > But it's not particularly more pleasant to the eye. > Still it reduces the exponential explosion of the code, at a small additional cost (the @), I believe. Actually, it's possible that with more cases it might be faster - it's eliminating the allocation (at some point) of all the tuples needed for the match case, it potentially eliminates a lot of linear comparisons to find the correct match case (I don't think that the compiler would be able to optimise that to a hash-based or index-based lookup) and [@]'s running time is proportional to the length of its first argument only - which here is always a singleton or empty list. The only extra cost is in space - you allocate a cons cell for each item which is included in the list twice (once to put it in the singleton list and once to append the rest of the list to it). If the actual scenario is lots more of these put together, you could profitably define a better special-case operator: let (@@) a b = match a with [] -> b | [a] -> a::b | _ -> assert false (a dirty - though still safe - solution with Obj.magic can reduce the [match] to an [if]...) David ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 8:37 ` David Allsopp @ 2012-01-20 13:29 ` Edgar Friendly 2012-01-20 13:50 ` Fabrice Le Fessant ` (2 more replies) 0 siblings, 3 replies; 27+ messages in thread From: Edgar Friendly @ 2012-01-20 13:29 UTC (permalink / raw) To: caml-list On 01/20/2012 03:37 AM, David Allsopp wrote: > Actually, it's possible that with more cases it might be faster - > it's > eliminating the allocation (at some point) of all the tuples needed for > the match case, Doesn't the ocaml compiler not allocate the unnecessary tuples? https://ocaml.janestreet.com/?q=node/90 > it potentially eliminates a lot of linear comparisons to > find the correct match case (I don't think that the compiler would be > able to optimise that to a hash-based or index-based lookup) Isn't the compiler's compilation strategy for match cases able to build an optimized tree of comparisons in cases like this? I agree there's no easy index or hash strategy for this, but I'd expect it to turn this pattern matching into the equivalent of: if a then if b then [a;b] else [a] else if b then [b] else [] E. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 13:29 ` Edgar Friendly @ 2012-01-20 13:50 ` Fabrice Le Fessant 2012-01-20 13:58 ` oliver 2012-01-20 14:12 ` David Allsopp 2 siblings, 0 replies; 27+ messages in thread From: Fabrice Le Fessant @ 2012-01-20 13:50 UTC (permalink / raw) To: Edgar Friendly; +Cc: caml-list On Fri, Jan 20, 2012 at 2:29 PM, Edgar Friendly <thelema314@gmail.com> wrote: >> it potentially eliminates a lot of linear comparisons to >> find the correct match case (I don't think that the compiler would be >> able to optimise that to a hash-based or index-based lookup) > > > Isn't the compiler's compilation strategy for match cases able to build an > optimized tree of comparisons in cases like this? I agree there's no easy > index or hash strategy for this, but I'd expect it to turn this pattern > matching into the equivalent of: > > if a then if b then [a;b] else [a] > else if b then [b] else [] Indeed, the four line pattern-matching is turned into two consecutive tests. In many cases, the pattern-matching compiler only generates the optimal number of tests, so never be scared of creating big complex patterns... Regards, Fabrice ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 13:29 ` Edgar Friendly 2012-01-20 13:50 ` Fabrice Le Fessant @ 2012-01-20 13:58 ` oliver 2012-01-20 14:05 ` Edgar Friendly 2012-01-20 14:12 ` David Allsopp 2 siblings, 1 reply; 27+ messages in thread From: oliver @ 2012-01-20 13:58 UTC (permalink / raw) To: Edgar Friendly; +Cc: caml-list On Fri, Jan 20, 2012 at 08:29:09AM -0500, Edgar Friendly wrote: [...] > if a then if b then [a;b] else [a] > else if b then [b] else [] [...] For me, the original pattern matching code looks much easier to read. Ciao, Oliver ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 13:58 ` oliver @ 2012-01-20 14:05 ` Edgar Friendly 0 siblings, 0 replies; 27+ messages in thread From: Edgar Friendly @ 2012-01-20 14:05 UTC (permalink / raw) To: oliver, caml-list On 01/20/2012 08:58 AM, oliver wrote: > On Fri, Jan 20, 2012 at 08:29:09AM -0500, Edgar Friendly wrote: > [...] >> if a then if b then [a;b] else [a] >> else if b then [b] else [] > [...] > > For me, the original pattern matching code looks much easier to read. > I agree - this was not meant to be a suggestion on how to make the original code easy to read, but instead to point out that it's as efficient as this ugly "optimized" code. I included it in my benchmark as well for only this reason, to verify that the original code was as efficient as it. E. ^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [Caml-list] is there a more concise way to write this? 2012-01-20 13:29 ` Edgar Friendly 2012-01-20 13:50 ` Fabrice Le Fessant 2012-01-20 13:58 ` oliver @ 2012-01-20 14:12 ` David Allsopp 2012-01-20 14:23 ` Fabrice Le Fessant 2012-01-20 14:23 ` Edgar Friendly 2 siblings, 2 replies; 27+ messages in thread From: David Allsopp @ 2012-01-20 14:12 UTC (permalink / raw) To: Edgar Friendly, caml-list Edgar Friendly wrote: > On 01/20/2012 03:37 AM, David Allsopp wrote: > > Actually, it's possible that with more cases it might be faster - it's > > eliminating the allocation (at some point) of all the tuples needed > > for the match case, > > Doesn't the ocaml compiler not allocate the unnecessary tuples? > https://ocaml.janestreet.com/?q=node/90 > > > it potentially eliminates a lot of linear comparisons to find the > > correct match case (I don't think that the compiler would be able to > > optimise that to a hash-based or index-based lookup) > > Isn't the compiler's compilation strategy for match cases able to build an > optimized tree of comparisons in cases like this? I agree there's no easy > index or hash strategy for this, but I'd expect it to turn this pattern > matching into the equivalent of: > > if a then if b then [a;b] else [a] > else if b then [b] else [] Maybe for this case with two variables, yes - but it can't do that indefinitely: as the number of variables increases, the code size increases exponentially. David ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 14:12 ` David Allsopp @ 2012-01-20 14:23 ` Fabrice Le Fessant 2012-01-20 14:23 ` Edgar Friendly 1 sibling, 0 replies; 27+ messages in thread From: Fabrice Le Fessant @ 2012-01-20 14:23 UTC (permalink / raw) To: David Allsopp; +Cc: Edgar Friendly, caml-list On Fri, Jan 20, 2012 at 3:12 PM, David Allsopp <dra-news@metastack.com> wrote: > Maybe for this case with two variables, yes - but it can't do that indefinitely: as the number of variables increases, the code size increases exponentially. The problem is not the compilation of pattern-matching (number of tests will still be close to optimal), it is just that the number of cases to discriminate increases exponentially with the number of variables. --Fabrice ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 14:12 ` David Allsopp 2012-01-20 14:23 ` Fabrice Le Fessant @ 2012-01-20 14:23 ` Edgar Friendly 1 sibling, 0 replies; 27+ messages in thread From: Edgar Friendly @ 2012-01-20 14:23 UTC (permalink / raw) To: David Allsopp; +Cc: caml-list On 01/20/2012 09:12 AM, David Allsopp wrote: > Maybe for this case with two variables, yes - but it can't do that indefinitely: as the number of variables increases, the code size increases exponentially. true, the right way to generalize this is to use vuillion's `maybe` function that prepends conditionally. My main point is that the original match statement is not bad in efficiency, and does, in fact, run 35% faster for the 2-variable case. E. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 6:46 ` Valentin ROBERT 2012-01-20 6:58 ` Martin DeMello 2012-01-20 8:37 ` David Allsopp @ 2012-01-20 8:37 ` Sebastien Ferre 2012-01-20 9:11 ` Jerome Vouillon 2 siblings, 1 reply; 27+ messages in thread From: Sebastien Ferre @ 2012-01-20 8:37 UTC (permalink / raw) To: caml-list Hi, On 01/20/2012 07:46 AM, Valentin ROBERT wrote: > I guess you can write it like: > > let a = (if out then [o] else []) @ (if value then [v] else []) > > But it's not particularly more pleasant to the eye. > Still it reduces the exponential explosion of the code, at a small > additional cost (the @), I believe. You can make it even more concise by defining a helping function. let b2l b x = if b then [x] else [];; let a = b2l out o @ b2l value v;; This easily generalizes to an arbitrary number of boolean variables. --- Sébastien Ferré ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 8:37 ` Sebastien Ferre @ 2012-01-20 9:11 ` Jerome Vouillon 2012-01-20 9:34 ` Fabrice Le Fessant 0 siblings, 1 reply; 27+ messages in thread From: Jerome Vouillon @ 2012-01-20 9:11 UTC (permalink / raw) To: Sebastien Ferre; +Cc: caml-list On Fri, Jan 20, 2012 at 09:37:17AM +0100, Sebastien Ferre wrote: > You can make it even more concise by defining a helping function. > > let b2l b x = if b then [x] else [];; > > let a = > b2l out o @ > b2l value v;; You can also include the list concatenation in the helper function: let maybe b v c = if b then v :: c else c let g out o value v = maybe out o (maybe value v []) And the parentheses can be avoided by using a right associative application operator: let (@@) f x = f x let a = maybe out o @@ maybe value v @@ [] -- Jerome ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 9:11 ` Jerome Vouillon @ 2012-01-20 9:34 ` Fabrice Le Fessant 2012-01-20 10:27 ` Arnaud Spiwack 0 siblings, 1 reply; 27+ messages in thread From: Fabrice Le Fessant @ 2012-01-20 9:34 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 602 bytes --] On 01/20/2012 10:11 AM, Jerome Vouillon wrote: > And the parentheses can be avoided by using a right associative > application operator: > > let (@@) f x = f x > let a = maybe out o @@ maybe value v @@ [] Since the "%revapply" primitive is available in SVN 3.12 (next 3.12.2 or 3.13), you will be able to use "pipes", without the penalty of expensive partial applications: external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" let a = [] |> maybe value v |> maybe out o I am wondering now if we should also provide the "%apply" primitive too, to be able to choose the order... --Fabrice [-- Attachment #2: fabrice_le_fessant.vcf --] [-- Type: text/x-vcard, Size: 380 bytes --] begin:vcard fn:Fabrice LE FESSANT n:LE FESSANT;Fabrice org:INRIA Saclay -- Ile-de-France;P2P & OCaml adr;quoted-printable:;;Parc Orsay Universit=C3=A9 ;Orsay CEDEX;;91893;France email;internet:fabrice.le_fessant@inria.fr title;quoted-printable:Charg=C3=A9 de Recherche tel;work:+33 1 74 85 42 14 tel;fax:+33 1 74 85 42 49 url:http://fabrice.lefessant.net/ version:2.1 end:vcard ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 9:34 ` Fabrice Le Fessant @ 2012-01-20 10:27 ` Arnaud Spiwack 0 siblings, 0 replies; 27+ messages in thread From: Arnaud Spiwack @ 2012-01-20 10:27 UTC (permalink / raw) To: Fabrice Le Fessant; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 284 bytes --] > I am wondering now if we should also provide the "%apply" primitive too, > to be able to choose the order... > The ability to choose the order seems quite valuable to me. Plus, there is a right-associative apply in the non-rev order in Ocaml's distribution (namely in ocamlbuild). [-- Attachment #2: Type: text/html, Size: 479 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 6:38 [Caml-list] is there a more concise way to write this? Martin DeMello 2012-01-20 6:46 ` Valentin ROBERT @ 2012-01-20 8:52 ` Lin 2012-01-20 9:08 ` Valentin ROBERT 2012-01-20 9:38 ` oliver 2012-01-20 20:40 ` oliver 3 siblings, 1 reply; 27+ messages in thread From: Lin @ 2012-01-20 8:52 UTC (permalink / raw) To: caml-list What about: let a = List.filter (fun x -> x) [out; value] Lin On 01/20/2012 02:38 PM, Martin DeMello wrote: > let a = match (out, value) with > (true, true) -> [o; v] > | (false, true) -> [v] > | (true, false) -> [o] > | (false, false) -> [] > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 8:52 ` Lin @ 2012-01-20 9:08 ` Valentin ROBERT 2012-01-20 9:19 ` Lin 2012-01-20 10:21 ` Martin DeMello 0 siblings, 2 replies; 27+ messages in thread From: Valentin ROBERT @ 2012-01-20 9:08 UTC (permalink / raw) To: Lin; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 874 bytes --] Rather (in this case): let a = List.map fst (List.filter (fun x -> snd x) [(out, o); (value, v)]) That seems reasonable. On Fri, Jan 20, 2012 at 09:52, Lin <mysnowls@163.com> wrote: > What about: > > let a = List.filter (fun x -> x) [out; value] > > Lin > > > > On 01/20/2012 02:38 PM, Martin DeMello wrote: > >> let a = match (out, value) with >> (true, true) -> [o; v] >> | (false, true) -> [v] >> | (true, false) -> [o] >> | (false, false) -> [] >> >> > > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa-roc.inria.fr/**wws/info/caml-list<https://sympa-roc.inria.fr/wws/info/caml-list> > Beginner's list: http://groups.yahoo.com/group/**ocaml_beginners<http://groups.yahoo.com/group/ocaml_beginners> > Bug reports: http://caml.inria.fr/bin/caml-**bugs<http://caml.inria.fr/bin/caml-bugs> > > [-- Attachment #2: Type: text/html, Size: 1595 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 9:08 ` Valentin ROBERT @ 2012-01-20 9:19 ` Lin 2012-01-20 10:21 ` Martin DeMello 1 sibling, 0 replies; 27+ messages in thread From: Lin @ 2012-01-20 9:19 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 1138 bytes --] Oh sorry I assumed `o' is short for `out' and `v' for `value', which seems not the case. By the way, in your solution `fst' and `snd' should be exchanged, i.e. let a = List.map snd (List.filter (fun x -> fst x) [(out, o); (value, v)]) On 01/20/2012 05:08 PM, Valentin ROBERT wrote: > Rather (in this case): > > let a = List.map fst (List.filter (fun x -> snd x) [(out, o); (value, v)]) > > That seems reasonable. > > On Fri, Jan 20, 2012 at 09:52, Lin <mysnowls@163.com > <mailto:mysnowls@163.com>> wrote: > > What about: > > let a = List.filter (fun x -> x) [out; value] > > Lin > > > > On 01/20/2012 02:38 PM, Martin DeMello wrote: > > let a = match (out, value) with > (true, true) -> [o; v] > | (false, true) -> [v] > | (true, false) -> [o] > | (false, false) -> [] > > > > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa-roc.inria.fr/wws/info/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > > [-- Attachment #2: Type: text/html, Size: 3206 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 9:08 ` Valentin ROBERT 2012-01-20 9:19 ` Lin @ 2012-01-20 10:21 ` Martin DeMello 1 sibling, 0 replies; 27+ messages in thread From: Martin DeMello @ 2012-01-20 10:21 UTC (permalink / raw) To: Valentin ROBERT; +Cc: Lin, caml-list I ended up using let (>>?) x y = if x then [y] else [] in let a = (out >>? ...) @ (value >>? ...) which had the advantage that it let me inline the definitions of o and v while keeping things readable. martin On Fri, Jan 20, 2012 at 1:08 AM, Valentin ROBERT <valentin.robert.42@gmail.com> wrote: > Rather (in this case): > > let a = List.map fst (List.filter (fun x -> snd x) [(out, o); (value, v)]) > > That seems reasonable. > > > On Fri, Jan 20, 2012 at 09:52, Lin <mysnowls@163.com> wrote: >> >> What about: >> >> let a = List.filter (fun x -> x) [out; value] >> >> Lin >> >> >> >> On 01/20/2012 02:38 PM, Martin DeMello wrote: >>> >>> let a = match (out, value) with >>> (true, true) -> [o; v] >>> | (false, true) -> [v] >>> | (true, false) -> [o] >>> | (false, false) -> [] >>> >> >> >> >> -- >> Caml-list mailing list. Subscription management and archives: >> https://sympa-roc.inria.fr/wws/info/caml-list >> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >> Bug reports: http://caml.inria.fr/bin/caml-bugs >> > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 6:38 [Caml-list] is there a more concise way to write this? Martin DeMello 2012-01-20 6:46 ` Valentin ROBERT 2012-01-20 8:52 ` Lin @ 2012-01-20 9:38 ` oliver 2012-01-20 13:59 ` Edgar Friendly 2012-01-20 20:40 ` oliver 3 siblings, 1 reply; 27+ messages in thread From: oliver @ 2012-01-20 9:38 UTC (permalink / raw) To: Martin DeMello; +Cc: OCaml List Hello, On Thu, Jan 19, 2012 at 10:38:53PM -0800, Martin DeMello wrote: > let a = match (out, value) with > (true, true) -> [o; v] > | (false, true) -> [v] > | (true, false) -> [o] > | (false, false) -> [] The code looks fine for me. More concise does not always mean better readable or more performant. You apply the same kind of selection for both values. Something that would aequivalent would be of type 'a option. But I doubt that using option type here would make it more concise. Would it make it Better readable? Not necessarily. But at least it would show the operation more clear. But not sure if you want to handle option type in your result. I think a fold could do the selection of the raw values afterwards. If out is derived from o and v is derived from v and both are selected by the same function, you could use that function inside a fold. But would that really be more readable? It might be more generic. But if both selections are not done by the same function application to your result values, this also does not make sense. Do you see what I mean? Ciao, Oliver ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 9:38 ` oliver @ 2012-01-20 13:59 ` Edgar Friendly 2012-01-20 14:42 ` oliver ` (2 more replies) 0 siblings, 3 replies; 27+ messages in thread From: Edgar Friendly @ 2012-01-20 13:59 UTC (permalink / raw) To: caml-list On 01/20/2012 04:38 AM, oliver wrote: > More concise does not always mean better readable or more performant. > You apply the same kind of selection for both values. I can't measure readability, but I did throw together a quick benchmark to test the different methods. Please take no offense at this - I'm sure that the responses were headed much more towards readability than performance, so comparing them on performance is totally unfair, and this in no way judges the people whose names I've used to label the solutions. Maybe not surprisingly, the original match-based code came out fastest, and List.filter the slowest. Here's the result summary: demello (83.95 ns) is probably (alpha=7.88%) same speed as friendly (88.68 ns) which is probably (alpha=23.96%) same speed as vuillion (96.68 ns) which is 34.6% faster than robert (147.94 ns) which is probably (alpha=8.43%) same speed as ferre (154.63 ns) which is 70.7% faster than lin (527.64 ns) which is 17.1% faster than lefessant (636.43 ns) which is 31.1% faster than lin2 (924.24 ns) Source code and full results follow. E. --------------------------------- let o = 1 and v = 2 let demello = function | (true, true) -> [o; v] | (false, true) -> [v] | (true, false) -> [o] | (false, false) -> [] let robert (out, value) = (if out then [o] else []) @ (if value then [v] else []) let b2l b x = if b then [x] else [];; let ferre (out, value) = b2l out o @ b2l value v;; let maybe b v c = if b then v :: c else c let vuillion (out, value) = maybe out o (maybe value v []) let (|>) x f = f x (* no %revapply yet *) let lefessant (out, value) = [] |> maybe value v |> maybe out o let lin (out, value) = List.filter (fun x -> x) [out; value] let lin2 (out, value) = List.map snd (List.filter (fun x -> fst x) [(out, o); (value, v)]) let friendly (out,value) = if out then if value then [o;v] else [o] else if value then [v] else [] let test f n = for i = 1 to n do ignore(f (true, true)); ignore(f (true, false)); ignore(f (false, true)); ignore(f (false, false)); done let () = Bench.bench_n [ "demello", test demello; "robert", test robert; "ferre", test ferre; "vuillion", test vuillion; "lefessant", test lefessant; "lin", test lin; "lin2", test lin2; "friendly", test friendly; ] |> Bench.summarize ~alpha:0.05 ------------------------------ Measuring: System Clock Warming up Estimating clock resolution (1.44 us) Estimating cost of timer call (1.60 us) Benchmarking: demello Ran 32768 iterations in 1.68 ms Collecting 300 samples, 28127 iterations each, estimated time: 431.61 ms N: 300 Inter-quartile width:16.65 ns, Full range: (43.99 ns,525.38 ns) Outliers: 7 (2.3%) High Mild, 19 (6.3%) High Severe, mean: 83.95 ns, 95% CI: (75.16 ns, 88.32 ns) std.dev.: 48.91 ns, 95% CI: (27.18 ns, 61.20 ns) Benchmarking: robert Ran 16384 iterations in 2.96 ms Collecting 300 samples, 7956 iterations each, estimated time: 431.66 ms N: 300 Inter-quartile width:19.52 ns, Full range: (102.86 ns,644.99 ns) Outliers: 6 (2.0%) High Mild, 9 (3.0%) High Severe, mean: 147.94 ns, 95% CI: (141.11 ns, 153.17 ns) std.dev.: 53.76 ns, 95% CI: (22.29 ns, 68.36 ns) Benchmarking: ferre Ran 16384 iterations in 2.71 ms Collecting 300 samples, 8683 iterations each, estimated time: 431.64 ms N: 300 Inter-quartile width:25.01 ns, Full range: (104.02 ns,795.03 ns) Outliers: 6 (2.0%) High Mild, 11 (3.7%) High Severe, mean: 154.63 ns, 95% CI: (149.85 ns, 168.24 ns) std.dev.: 64.76 ns, 95% CI: (46.73 ns, 100.11 ns) Benchmarking: vuillion Ran 32768 iterations in 8.24 ms Collecting 300 samples, 5724 iterations each, estimated time: 431.66 ms N: 300 Inter-quartile width:26.91 ns, Full range: (38.71 ns,1.60 us) Outliers: 14 (4.7%) High Severe, mean: 96.68 ns, 95% CI: (72.67 ns, 115.55 ns) std.dev.: 193.29 ns, 95% CI: (99.28 ns, 244.72 ns) Benchmarking: lefessant Ran 4096 iterations in 2.32 ms Collecting 300 samples, 2543 iterations each, estimated time: 431.72 ms N: 300 Inter-quartile width:147.38 ns, Full range: (346.26 ns,4.15 us) Outliers: 3 (1.0%) High Severe, mean: 636.43 ns, 95% CI: (602.68 ns, 664.49 ns) std.dev.: 277.24 ns, 95% CI: (114.65 ns, 400.85 ns) Benchmarking: lin Ran 4096 iterations in 2.04 ms Collecting 300 samples, 2891 iterations each, estimated time: 431.73 ms N: 300 Inter-quartile width:190.01 ns, Full range: (305.90 ns,1.86 us) Outliers: 2 (0.7%) High Severe, mean: 527.64 ns, 95% CI: (514.62 ns, 556.02 ns) std.dev.: 152.73 ns, 95% CI: (117.57 ns, 225.48 ns) Benchmarking: lin2 Ran 4096 iterations in 2.49 ms Collecting 300 samples, 2371 iterations each, estimated time: 431.71 ms N: 300 Inter-quartile width:252.57 ns, Full range: (505.02 ns,5.90 us) Outliers: 10 (3.3%) High Severe, mean: 924.24 ns, 95% CI: (863.30 ns, 973.78 ns) std.dev.: 469.52 ns, 95% CI: (247.89 ns, 617.19 ns) Benchmarking: friendly Ran 16384 iterations in 1.49 ms Collecting 300 samples, 15769 iterations each, estimated time: 431.63 ms N: 300 Inter-quartile width:15.57 ns, Full range: (49.11 ns,480.53 ns) Outliers: 10 (3.3%) Low Mild, 6 (2.0%) High Severe, mean: 88.68 ns, 95% CI: (86.37 ns, 94.85 ns) std.dev.: 31.12 ns, 95% CI: (13.41 ns, 44.10 ns) ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 13:59 ` Edgar Friendly @ 2012-01-20 14:42 ` oliver 2012-01-20 15:31 ` Fabrice Le Fessant 2012-01-20 21:04 ` oliver 2 siblings, 0 replies; 27+ messages in thread From: oliver @ 2012-01-20 14:42 UTC (permalink / raw) To: Edgar Friendly; +Cc: caml-list On Fri, Jan 20, 2012 at 08:59:31AM -0500, Edgar Friendly wrote: > On 01/20/2012 04:38 AM, oliver wrote: > >More concise does not always mean better readable or more performant. > >You apply the same kind of selection for both values. > > I can't measure readability, but I did throw together a quick > benchmark to test the different methods. Please take no offense at > this - I'm sure that the responses were headed much more towards > readability than performance, Thats not offending, the result is fine for me. :-) I preferred the pattern-match version, because I like things to be displayed in tables. ;-) My version (option type and folding on lists) you did not implemented, but maybe it would have been my work to do that. But I liked the pattern macthing way. That it also is the fastest way, is a fine result. :-) I hope you used more than one call of the function and used average / stddev on your values to get reliable results... I don't know your Bench-module. Where is it from? Ciao, Oliver ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 13:59 ` Edgar Friendly 2012-01-20 14:42 ` oliver @ 2012-01-20 15:31 ` Fabrice Le Fessant 2012-01-20 21:04 ` oliver 2 siblings, 0 replies; 27+ messages in thread From: Fabrice Le Fessant @ 2012-01-20 15:31 UTC (permalink / raw) To: Edgar Friendly; +Cc: caml-list On Fri, Jan 20, 2012 at 2:59 PM, Edgar Friendly <thelema314@gmail.com> wrote: > On 01/20/2012 04:38 AM, oliver wrote: > let (|>) x f = f x (* no %revapply yet *) > let lefessant (out, value) = [] |> maybe value v |> maybe out o I replayed your bench on 3.12.1+dev, where "%revapply" is available, and it is fortunately the same speed as Jerome Vouillon's one. --Fabrice ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 13:59 ` Edgar Friendly 2012-01-20 14:42 ` oliver 2012-01-20 15:31 ` Fabrice Le Fessant @ 2012-01-20 21:04 ` oliver 2012-01-20 21:09 ` oliver 2 siblings, 1 reply; 27+ messages in thread From: oliver @ 2012-01-20 21:04 UTC (permalink / raw) To: Edgar Friendly; +Cc: caml-list My fold approach version: let folded (out, value) o v = let a = if out then Some o else None in let b = if value then Some v else None in List.fold_left ( fun accum elem -> match elem with None -> accum | Some x -> x :: accum ) [] [ b; a ] or when following the way the other functions are notated (o and v not as parameters but in the environment) so that you can paste it into your code: let folded_env (out, value) = let a = if out then Some o else None in let b = if value then Some v else None in List.fold_left ( fun accum elem -> match elem with None -> accum | Some x -> x :: accum ) [] [ b; a ] If let ... = ... in let ... = ... in ... is slower than than let ... = ... and let ... = ... in ... then use the latter one ;-) Ciao, Oliver ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 21:04 ` oliver @ 2012-01-20 21:09 ` oliver 0 siblings, 0 replies; 27+ messages in thread From: oliver @ 2012-01-20 21:09 UTC (permalink / raw) To: Edgar Friendly; +Cc: caml-list On Fri, Jan 20, 2012 at 10:04:30PM +0100, oliver wrote: > > My fold approach version: > > let folded (out, value) o v = > let a = if out then Some o else None in > let b = if value then Some v else None in > List.fold_left ( fun accum elem -> match elem with None -> accum | Some x -> x :: accum ) [] [ b; a ] > > or when following the way the other functions are notated > (o and v not as parameters but in the environment) so that > you can paste it into your code: > > > let folded_env (out, value) = > let a = if out then Some o else None in > let b = if value then Some v else None in > List.fold_left ( fun accum elem -> match elem with None -> accum | Some x -> x :: accum ) [] [ b; a ] > > If > let ... = ... in let ... = ... in ... > is slower than than > let ... = ... and let ... = ... in ... [...] meanI t: If let ... = ... in let ... = ... in ... is slower than than let ... = ... and ... = ... in ... of course. (copy & paste-related typo) Ciao, Oliver ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 6:38 [Caml-list] is there a more concise way to write this? Martin DeMello ` (2 preceding siblings ...) 2012-01-20 9:38 ` oliver @ 2012-01-20 20:40 ` oliver 2012-01-20 21:07 ` Martin DeMello 3 siblings, 1 reply; 27+ messages in thread From: oliver @ 2012-01-20 20:40 UTC (permalink / raw) To: Martin DeMello; +Cc: OCaml List On Thu, Jan 19, 2012 at 10:38:53PM -0800, Martin DeMello wrote: > let a = match (out, value) with > (true, true) -> [o; v] > | (false, true) -> [v] > | (true, false) -> [o] > | (false, false) -> [] [...] Is there a way to get out and value from o and v? Ciao, Oliver ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Caml-list] is there a more concise way to write this? 2012-01-20 20:40 ` oliver @ 2012-01-20 21:07 ` Martin DeMello 0 siblings, 0 replies; 27+ messages in thread From: Martin DeMello @ 2012-01-20 21:07 UTC (permalink / raw) To: oliver; +Cc: OCaml List On Fri, Jan 20, 2012 at 12:40 PM, oliver <oliver@first.in-berlin.de> wrote: > On Thu, Jan 19, 2012 at 10:38:53PM -0800, Martin DeMello wrote: >> let a = match (out, value) with >> (true, true) -> [o; v] >> | (false, true) -> [v] >> | (true, false) -> [o] >> | (false, false) -> [] > [...] > > > Is there a way to get out and value from o and v? No, out and value are just boolean inputs to the function to control how the output is built up out of the individual parts. martin ^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2012-01-20 21:09 UTC | newest] Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-01-20 6:38 [Caml-list] is there a more concise way to write this? Martin DeMello 2012-01-20 6:46 ` Valentin ROBERT 2012-01-20 6:58 ` Martin DeMello 2012-01-20 8:37 ` David Allsopp 2012-01-20 13:29 ` Edgar Friendly 2012-01-20 13:50 ` Fabrice Le Fessant 2012-01-20 13:58 ` oliver 2012-01-20 14:05 ` Edgar Friendly 2012-01-20 14:12 ` David Allsopp 2012-01-20 14:23 ` Fabrice Le Fessant 2012-01-20 14:23 ` Edgar Friendly 2012-01-20 8:37 ` Sebastien Ferre 2012-01-20 9:11 ` Jerome Vouillon 2012-01-20 9:34 ` Fabrice Le Fessant 2012-01-20 10:27 ` Arnaud Spiwack 2012-01-20 8:52 ` Lin 2012-01-20 9:08 ` Valentin ROBERT 2012-01-20 9:19 ` Lin 2012-01-20 10:21 ` Martin DeMello 2012-01-20 9:38 ` oliver 2012-01-20 13:59 ` Edgar Friendly 2012-01-20 14:42 ` oliver 2012-01-20 15:31 ` Fabrice Le Fessant 2012-01-20 21:04 ` oliver 2012-01-20 21:09 ` oliver 2012-01-20 20:40 ` oliver 2012-01-20 21:07 ` Martin DeMello
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox