Let's imagine you have a list of named things, but you also want to collect them up into a single list. For example: let item1 = "hello" let item2 = "world" let all_items = [ item1; item2 ] let () = printf "item1 = %s\n" item1; printf "all_items = %s\n" (String.concat ", " all_items) This is fine, but there's a danger that a programmer could add item3 but forget to add it to the "all_items" list. (In the real world problem to which this applies, my items are complex and lengthy structures, and the "all-things-list" is well off the bottom of the page when you're viewing the top item). My idea to fix this was to write: let all_items = [ ("hello" as item1); ("world" as item2); ] Actually I was slightly surprised to find this doesn't compile. I guess because "as" can only be used like this in patterns, not expressions. Also the scoping is wrong because the "as item1" if it worked probably wouldn't apply outside the list. I haven't worked out if it's possible to write this in ordinary OCaml, although I suppose ppx could solve it. Any ideas if this is possible? Rich.
[-- Attachment #1: Type: text/plain, Size: 1545 bytes --] If you have an interface file (.mli) for this module, then adding item3 without putting it in all_items or in the .mli will result in an "unused value item3" warning (-w +32). There is no such warning in absence of .mli because, in that case, item3 may a priori be used from the outside. On Fri, Aug 9, 2019 at 4:28 PM Richard W.M. Jones <rich@annexia.org> wrote: > Let's imagine you have a list of named things, but you also want to > collect them up into a single list. For example: > > let item1 = "hello" > let item2 = "world" > let all_items = [ item1; item2 ] > > let () = > printf "item1 = %s\n" item1; > printf "all_items = %s\n" (String.concat ", " all_items) > > This is fine, but there's a danger that a programmer could add item3 > but forget to add it to the "all_items" list. (In the real world > problem to which this applies, my items are complex and lengthy > structures, and the "all-things-list" is well off the bottom of the > page when you're viewing the top item). > > My idea to fix this was to write: > > let all_items = [ > ("hello" as item1); > ("world" as item2); > ] > > Actually I was slightly surprised to find this doesn't compile. I > guess because "as" can only be used like this in patterns, not > expressions. Also the scoping is wrong because the "as item1" if it > worked probably wouldn't apply outside the list. > > I haven't worked out if it's possible to write this in ordinary OCaml, > although I suppose ppx could solve it. Any ideas if this is possible? > > Rich. > [-- Attachment #2: Type: text/html, Size: 2118 bytes --]
On Fri, Aug 09, 2019 at 04:40:48PM +0200, Gabriel Scherer wrote:
> If you have an interface file (.mli) for this module, then adding item3
> without putting it in all_items or in the .mli will result in an "unused
> value item3" warning (-w +32).
> There is no such warning in absence of .mli because, in that case, item3
> may a priori be used from the outside.
I wasn't very clear, but we're using both the individual items and the
list of all items elsewhere in the code. But it raises another point
which is we'd like a list of all items, and maybe to selectively name
some of those items so they can be referenced elsewhere.
Rich.
[-- Attachment #1.1: Type: text/plain, Size: 1700 bytes --] I always found let [item1; item2] as all_items = ["hello"; "world" ] readable but the compiler does does not infer that this match always works and emits: Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (_::_::_::_|_::[]|[]) I've never touched the compiler so I don't have an idea how much effort it would be to make the inference. cheers, Martin On 8/9/19 4:27 PM, Richard W.M. Jones wrote: > Let's imagine you have a list of named things, but you also want to > collect them up into a single list. For example: > > let item1 = "hello" > let item2 = "world" > let all_items = [ item1; item2 ] > > let () = > printf "item1 = %s\n" item1; > printf "all_items = %s\n" (String.concat ", " all_items) > > This is fine, but there's a danger that a programmer could add item3 > but forget to add it to the "all_items" list. (In the real world > problem to which this applies, my items are complex and lengthy > structures, and the "all-things-list" is well off the bottom of the > page when you're viewing the top item). > > My idea to fix this was to write: > > let all_items = [ > ("hello" as item1); > ("world" as item2); > ] > > Actually I was slightly surprised to find this doesn't compile. I > guess because "as" can only be used like this in patterns, not > expressions. Also the scoping is wrong because the "as item1" if it > worked probably wouldn't apply outside the list. > > I haven't worked out if it's possible to write this in ordinary OCaml, > although I suppose ppx could solve it. Any ideas if this is possible? > > Rich. > [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 833 bytes --]
What about good old-fashioned state:
let all_items = ref []
let add_item item = all_items := (item :: !all_items, item)
let item1 = add_item "hello"
let item2 = add_item "world"
let all_items = List.rev !all_items
On 9 Aug 2019, at 15:27, Richard W.M. Jones wrote:
> Let's imagine you have a list of named things, but you also want to
> collect them up into a single list. For example:
>
> let item1 = "hello"
> let item2 = "world"
> let all_items = [ item1; item2 ]
>
> let () =
> printf "item1 = %s\n" item1;
> printf "all_items = %s\n" (String.concat ", " all_items)
>
> This is fine, but there's a danger that a programmer could add item3
> but forget to add it to the "all_items" list. (In the real world
> problem to which this applies, my items are complex and lengthy
> structures, and the "all-things-list" is well off the bottom of the
> page when you're viewing the top item).
>
> My idea to fix this was to write:
>
> let all_items = [
> ("hello" as item1);
> ("world" as item2);
> ]
>
> Actually I was slightly surprised to find this doesn't compile. I
> guess because "as" can only be used like this in patterns, not
> expressions. Also the scoping is wrong because the "as item1" if it
> worked probably wouldn't apply outside the list.
>
> I haven't worked out if it's possible to write this in ordinary OCaml,
> although I suppose ppx could solve it. Any ideas if this is possible?
>
> Rich.
[-- Attachment #1: Type: text/plain, Size: 1772 bytes --] Abusing list notations and GADTs to keep track of length and ensure exhaustive matching: module M = struct type ('a, 'b) t = [] : (_, unit) t | (::) : 'a * ('a, 'b) t -> ('a, unit * 'b) t end;; let rec to_list : type a b. (a, b) M.t -> a list = function | M.[] -> [] | M.(x :: xs) -> x :: to_list xs;; let decompose x = (to_list x, x);; # let all_items, M.[item1; item2] = decompose M.["hello"; "world"];; val all_items : string list = ["hello"; "world"] val item1 : string = "hello" val item2 : string = "world" On Fri, Aug 9, 2019 at 4:27 PM Richard W.M. Jones <rich@annexia.org> wrote: > Let's imagine you have a list of named things, but you also want to > collect them up into a single list. For example: > > let item1 = "hello" > let item2 = "world" > let all_items = [ item1; item2 ] > > let () = > printf "item1 = %s\n" item1; > printf "all_items = %s\n" (String.concat ", " all_items) > > This is fine, but there's a danger that a programmer could add item3 > but forget to add it to the "all_items" list. (In the real world > problem to which this applies, my items are complex and lengthy > structures, and the "all-things-list" is well off the bottom of the > page when you're viewing the top item). > > My idea to fix this was to write: > > let all_items = [ > ("hello" as item1); > ("world" as item2); > ] > > Actually I was slightly surprised to find this doesn't compile. I > guess because "as" can only be used like this in patterns, not > expressions. Also the scoping is wrong because the "as item1" if it > worked probably wouldn't apply outside the list. > > I haven't worked out if it's possible to write this in ordinary OCaml, > although I suppose ppx could solve it. Any ideas if this is possible? > > Rich. > [-- Attachment #2: Type: text/html, Size: 2498 bytes --]
On Fri, Aug 9, 2019, at 16:48, Martin Riener wrote: > let [item1; item2] as all_items = ["hello"; "world" ] Nice! > Warning 8: this pattern-matching is not exhaustive. > Here is an example of a case that is not matched: > (_::_::_::_|_::[]|[]) let [item1; item2] as all_items = ["hello"; "world" ] [@@ocaml.warning "-8"]
Quoting Josh Berdine <josh@berdine.net> (snt: 2019-08-09 16:51 +0200 CEST) (rcv: 2019-08-09 16:53 +0200 CEST): > What about good old-fashioned state: [...] I guess you mean style, not state. And I would agree that inventing just another syntax would not be necessary, > > let all_items = ref [] > let add_item item = all_items := (item :: !all_items, item) This does not xomnpile, but thie here does: let add_item item = all_items := (item :: !all_items); item Ciao, Oliver
[-- Attachment #1: Type: text/plain, Size: 1821 bytes --] Slight fixups: let all_items = ref ([] : string list) let add_item item = (all_items := item :: !all_items ; item) let item1 = add_item "hello" let item2 = add_item "world" let all_items = List.rev !all_items On Fri, Aug 9, 2019 at 7:53 AM Josh Berdine <josh@berdine.net> wrote: > What about good old-fashioned state: > > let all_items = ref [] > let add_item item = all_items := (item :: !all_items, item) > > let item1 = add_item "hello" > let item2 = add_item "world" > > let all_items = List.rev !all_items > > > On 9 Aug 2019, at 15:27, Richard W.M. Jones wrote: > > > Let's imagine you have a list of named things, but you also want to > > collect them up into a single list. For example: > > > > let item1 = "hello" > > let item2 = "world" > > let all_items = [ item1; item2 ] > > > > let () = > > printf "item1 = %s\n" item1; > > printf "all_items = %s\n" (String.concat ", " all_items) > > > > This is fine, but there's a danger that a programmer could add item3 > > but forget to add it to the "all_items" list. (In the real world > > problem to which this applies, my items are complex and lengthy > > structures, and the "all-things-list" is well off the bottom of the > > page when you're viewing the top item). > > > > My idea to fix this was to write: > > > > let all_items = [ > > ("hello" as item1); > > ("world" as item2); > > ] > > > > Actually I was slightly surprised to find this doesn't compile. I > > guess because "as" can only be used like this in patterns, not > > expressions. Also the scoping is wrong because the "as item1" if it > > worked probably wouldn't apply outside the list. > > > > I haven't worked out if it's possible to write this in ordinary OCaml, > > although I suppose ppx could solve it. Any ideas if this is possible? > > > > Rich. > [-- Attachment #2: Type: text/html, Size: 2605 bytes --]