Re: [Haskell-cafe] MultiCase alternative

Richard A. O'Keefe wrote:
Let Pi be the pattern (i,_) | (_,i) In SML, fun f P1 ... Pn (0,0) = true | f _ ... _ _ = false
fun g () = f (1,1) (2,2) ... (n,n) (1,1)
(So far it has taken 3 minutes on a fast machine to not finish compiling these 3 lines of code... I fear the worst.)
From personal experience, OR patterns are quite handy when handing an AST where many of the alternatives are to be handled the same. That said, supporting OR patterns in MetaOCaml was responsible for some of
I can't speak for SML, but I was curious to try your example in OCaml, which also supports OR patterns. Here is how it looks in OCaml: let f = function ((1,_)|(_,1)), ((2,_)|(_,2)), ((3,_)|(_,3)), ((4,_)|(_,4)), ((5,_)|(_,5)), ((6,_)|(_,6)), ((7,_)|(_,7)), ((8,_)|(_,8)), (0,0) -> true | _ -> false ;; let g () = f ((1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(1,1)) ;; let _ = g ();; It compiled instantly. I was curious what it is compiled to. Enclosed in the result, in an intermediate language called Lambda (before optimizations). It seems the size of the code is linear in n. Not too bad. BTW, match/1207 is the identifier called match with the timestamp 1207. The timestamps tell distinct identifiers with the same given name apart. Also, 1a means true and 0a means false (and also unit and the empty list). the most complex code there. ocamlc -c -dlambda p.ml (setglobal P! (let (f/1199 = (function param/1206 (let (match/1207 =a (field 0 param/1206)) (catch (catch (if (!= (field 0 match/1207) 1) (if (!= (field 1 match/1207) 1) (exit 1) (exit 2)) (exit 2)) with (2) (let (match/1227 =a (field 1 param/1206)) (catch (if (!= (field 0 match/1227) 2) (if (!= (field 1 match/1227) 2) (exit 1) (exit 4)) (exit 4)) with (4) (let (match/1245 =a (field 2 param/1206)) (catch (if (!= (field 0 match/1245) 3) (if (!= (field 1 match/1245) 3) (exit 1) (exit 6)) (exit 6)) with (6) (let (match/1261 =a (field 3 param/1206)) (catch (if (!= (field 0 match/1261) 4) (if (!= (field 1 match/1261) 4) (exit 1) (exit 8)) (exit 8)) with (8) (let (match/1275 =a (field 4 param/1206)) (catch (if (!= (field 0 match/1275) 5) (if (!= (field 1 match/1275) 5) (exit 1) (exit 10)) (exit 10)) with (10) (let (match/1287 =a (field 5 param/1206)) (catch (if (!= (field 0 match/1287) 6) (if (!= (field 1 match/1287) 6) (exit 1) (exit 12)) (exit 12)) with (12) (let (match/1297 =a (field 6 param/1206)) (catch (if (!= (field 0 match/1297) 7) (if (!= (field 1 match/1297) 7) (exit 1) (exit 14)) (exit 14)) with (14) (let (match/1305 =a (field 7 param/1206)) (catch (if (!= (field 0 match/1305) 8) (if (!= (field 1 match/1305) 8) (exit 1) (exit 16)) (exit 16)) with (16) (let (match/1311 =a (field 8 param/1206)) (if (!= (field 0 match/1311) 0) (exit 1) (if (!= (field 1 match/1311) 0) (exit 1) 1a)))))))))))))))))) with (1) 0a))) g/1201 = (function param/1205 (apply f/1199 [0: [0: 1 1] [0: 2 2] [0: 3 3] [0: 4 4] [0: 5 5] [0: 6 6] [0: 7 7] [0: 8 8] [0: 1 1]]))) (seq (apply g/1201 0a) (makeblock 0 f/1199 g/1201))))

On 19/06/2017, at 9:28 PM, Oleg
wrote: Richard A. O'Keefe wrote:
Let Pi be the pattern (i,_) | (_,i) In SML, fun f P1 ... Pn (0,0) = true | f _ ... _ _ = false
fun g () = f (1,1) (2,2) ... (n,n) (1,1)
(So far it has taken 3 minutes on a fast machine to not finish compiling these 3 lines of code... I fear the worst.)
I can't speak for SML, but I was curious to try your example in OCaml, which also supports OR patterns.
My test case went up to ((20,_)|(_,20)). Your example goes up only to ((8,_)|(0,8)). Your version worked fast in F#. I'm currently trying a full scale example. F# ground away for a couple of minutes and then ran out of memory. ocamlc compiled it too fast to measure accurately.
participants (2)
-
Oleg
-
Richard A. O'Keefe