;;;; (array-fill [r c] v) and (array-gen [r c] f) — a fixed array as a value. ;;;; ;;;; DISCUSS.org's "need a value-producing array constructor": (array n T) is ;;;; the zeroed array and dotimes is Unit, so neither could be the initialiser ;;;; expression of a declaration. These are expressions, so they compose where ;;;; a bracket literal does — including as a defvar's initialiser, which is the ;;;; line the note was written about. ;;;; ;;;; The dimensions are in brackets and are the same compile-time lengths the ;;;; [n T] type spelling takes: an integer or a constant's name. (defconst rows 3) (defconst cols 4) ;; The line from the note. A typed declaration with a computed initialiser, ;; which is the startup-lifted path a defvar already had. (defvar grid [rows [cols u8]] (array-fill [rows cols] 255)) ;; One index per dimension, i32 each, and the return type is the element type. (defn cell [r i32 c i32] i32 (+ (* r 100) c)) (defn one [i i32] i32 (* i i)) ;; Row-major order is pinned, so a generator that counts observes it: this one ;; is called once per element and answers the call number, so the array it ;; fills is 0 1 2 ... in the order the elements are written. (defvar ticks i32) (defn tick [r i32 c i32] i32 (set ticks (+ ticks 1)) (- ticks 1)) (defn main [] i32 ;; Rank 1. (let [a (array-fill [5] 7)] (print (at a 0)) (print " ") (print (at a 4)) (println "")) ; 7 7 ;; Rank 2, and the element type is the fill value's. (let [b (array-fill [2 3] (f32 1.5))] (print (at b 1 2)) (println "")) ; 1.5 ;; Rank 3. (let [c (array-fill [2 2 2] -1)] (print (at c 0 0 0)) (print " ") (print (at c 1 1 1)) (println "")) ; -1 -1 ;; A dimension may be a constant's name, exactly as in [rows [cols u8]]. (let [d (array-fill [rows cols] 1)] (print (at d 2 3)) (println "")) ; 1 ;; The generator, rank 1: element i is i*i. (let [g (array-gen [5] one)] (print (at g 0)) (print " ") (print (at g 3)) (print " ") (print (at g 4)) (println "")) ; 0 9 16 ;; The generator, rank 2. Element [i][j] is i*100+j, which pins the index ;; arguments: the first is the outer index and the second the inner one, and ;; a form that passed them the other way round would print 1 and 300 here. (let [h (array-gen [rows cols] cell)] (print (at h 0 0)) (print " ") (print (at h 0 1)) (print " ") (print (at h 1 0)) (print " ") (print (at h 2 3)) (println "")) ; 0 1 100 203 ;; Row-major, pinned. [tick] answers the call number, so the element that ;; was written first holds 0 — and with four columns, [1][0] is the fifth. (let [t (array-gen [rows cols] tick)] (print (at t 0 0)) (print " ") (print (at t 0 1)) (print " ") (print (at t 1 0)) (print " ") (print (at t 2 3)) (println "")) ; 0 1 4 11 ;; The defvar from the top: 255 everywhere, read back as an i32 so the ;; printed value is the number and not a byte. (print (i32 (at grid 0 0))) (print " ") (print (i32 (at grid 2 3))) (println "") ; 255 255 ;; An array value copies, which is what makes this a value and not a view: ;; writing through the copy leaves the global alone. (let [copy grid] (set (at copy 0 0) (u8 1)) (print (i32 (at copy 0 0))) (print " ") (print (i32 (at grid 0 0))) (println "")) ; 1 255 ;; A zero dimension is an array with no elements, and the loop that fills it ;; runs no passes. Nothing to read, so the claim is that it compiles and the ;; program carries on. (let [e (array-fill [0] 9)] (println "empty ok")) 0)