Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printing collections: variable specific

Tags:

scala

I have multidimensional arrays where the dimensions are saved in an ArrayBuffer.

When I print it, obviously, I get e.g. ArrayBuffer(2, 2, 3), but I would like to have 2x2x3. I know that I can do it as follows println(multiarray.dim.mkString("x")).

Is there any "magical" way that I get 2x2x3 by simply issuing println(multiarray.dim)?

EDIT

dim is method of the multidimensional arrays that gives the dimensions...

like image 410
teucer Avatar asked Feb 23 '23 17:02

teucer


2 Answers

If dim returns an ArrayBuffer, then, no, you can't just use println(multiarray.dim). Here are some simple alternatives though:

  1. Define a method to return the dimensions as a String (in your multiarray class):

    def dimStr = dim mkString "x"
    
  2. Define a utility method for printing:

    def printdim(buffer: ArrayBuffer[Int]) = println(buffer mkString "x")
    // or
    def printdim(multiarray: MultiArray) = println(multiarray.dim mkString "x")
    

Generalizing toString:

With a bit more effort, you can define a version of println that will work the way you'd like. The idea is to abstract the String-creation logic. The power of this approach is that, once the basic infrastructure is in place, you're able to control the "stringification" of any type just by bringing an appropriate implicit into scope.

Start by defining a type class:

trait Stringable[T] extends (T => String)

Provide a default implementation of the type class (which just falls back on the ordinary toString method):

class DefaultStringable[T] extends Stringable[T] { 
   def apply(x: T) = x.toString
}
object DefaultStringable {
   implicit def any2stringable[T]: Stringable[T] = new DefaultStringable[T]
}

Implement the type class for your use case:

implicit object DimIsStringable extends Stringable[ArrayBuffer[Int]] {
   def apply(buf: ArrayBuffer[Int]) = buf mkString "x"
}

Define a print method that uses the type class:

def myprintln[T](x: T)(implicit e: Stringable[T]) = e(x)

Fun.

import DefaultStringable._
myprintln(ArrayBuffer(1,2,3)) // prints "ArrayBuffer(1, 2, 3)"

Profit!

import DimIsStringable._
myprintln(ArrayBuffer(1,2,3)) // prints "1x2x3"

If desired, you can make the default type class always available without requiring any import. To do so, you provide the conversion in a companion module to the Stringable trait (as demonstrated below). The disadvantage of doing so is that you'll no longer have a compiler error to alert you if you forget to import an appropriate Stringable.

object Stringable {
   implicit def any2stringable[T]: Stringable[T] = new DefaultStringable[T]
}
like image 194
Aaron Novstrup Avatar answered Mar 03 '23 15:03

Aaron Novstrup


I m' not sure that would qualify as magical, but would that be ok?

class ArrayDim extends ArrayBufer[Int] {
   override def toString = mkString ("x")
}

Edit : Then in the code of your multidimensional array class, replace dim = new ArrayBuffer by dim = new ArrayDim. Depending on how you fill the buffer, you may need minor changes in the code.

like image 35
Didier Dupont Avatar answered Mar 03 '23 16:03

Didier Dupont