I am trying to print a 2D char array in SML which is in the form of:
val arr = Array2.fromList [[#"a", #"b", #"c"], [#"d", #"e", #"f"], [#"g", #"h", #"i"]];
Note that the last element in each row is not an #"\n"
element.
The result must be in the following form, where every row is represented in a new line:
abc
def
ghi
Is there any way to do this in SML?
You can iterate and print a full row at a time by using Array2.row
, Array2.nRows
and CharVector.tabulate
:
Array2.row : 'a array * int -> 'a Vector.vector
Array2.nRows : 'a array -> int
CharVector.tabulate : int * (int -> char) -> string
You could define a function app_row
that takes an Array2.array
and calls a function f
on each row, extracted as a vector. And a function vec_to_str
that takes that vector vec
and converts it to a string; then print it.
fun app_row f arr =
let fun loop i = if i = Array2.nRows arr then ()
else (f (Array2.row (arr, i)); loop (i+1))
in loop 0 end
fun vec_to_str vec =
CharVector.tabulate (Vector.length vec, fn i => Vector.sub (vec, i))
fun showMatrix arr =
app_row (fn row => print (vec_to_str row ^ "\n")) arr
Trying this for size:
- showMatrix arr;
abc
def
ghi
> val it = () : unit
This solution should be less I/O intensive than e.g. using Array2.appi
and print each letter one at a time. It's also slightly more complicated because it involves converting a "char Vector.vector" into a "CharVector.vector" (aka a string). (The difference between the two is subtle.)
Still, an alternative solution akin to the solution of P. Antoniadis, but where you don't need to specify the dimensions (since they can be extracted using e.g. Array2.nCols
and Array2.nRows
):
fun showMatrix arr =
Array2.appi Array2.RowMajor (fn (_, col, c) =>
print (str c ^ (if col + 1 = Array2.nCols arr then "\n" else "" )))
{base=arr,row=0,col=0,nrows=NONE,ncols=NONE}