HomeForumResearchGuide
Sign in to reply to forum posts.
Printing an integer to the console

Hi,

I'm really new to this, can I check how to print an integer to the console output?

I tried this:

component provides App requires io.Output out {
   int App:main(AppParam params[]) {
      int i = 17
      out.println("my number is $i")
      return 0
      }
   }

But it just prints an odd symbol. How can I print the number properly here?

Thanks

hi, there are two ways to do this.

Either way you need to add requires data.IntUtil iu to your component header line.

One option is then:

out.println("my number is $(iu.makeString(i))")

I also wanted to add a note on associative functions, though. This took me a while to become comfortable with as a concept but it really simplifies code and you might see it in a bunch of code written by other people, especially for the stuff in the data.query package. An associative function call is where you call a function "on" a primitive data type or a Data instance or array instance. You can do this whenever you have a function defined in an interface, the interface is auto-instantiated (like "out" in your example), and the first parameter of that funtion is of the type you want to associate.

For string expansion the compiler takes associative functions one step further and will automatically search for any associable (?) function called makeString() with a single non-optional parameter of the type present in the string expansion.

So then you can just to do this, which you might have seen in other code:

component provides App requires io.Output out, data.IntUtil iu {
   int App:main(AppParam params[]) {
      int i = 17
      out.println("my number is $i")
      return 0
      }
   }

This is because IntUtil has a function defined as:

char[] makeString(int)

So the compiler knows it can use this to translate an int to a char[]. I guess this is also why they changed the function to be called makeString() so the compiler can do the automated lookup on a common name.

If you think about it the makeString() approach gets a form of function overloading dispersed across interfaces. We actually use this style more widely now in a bunch of our project code :-)

I thought I'd expand my answer on the second option a bit more :-)

A really common thing that we use associative functions for in our team is string manipulation. If we want to lowercase a string (which is a char[]) and then trim it, for example, we might do this:

char myString[] = whatever
char newString[] = stringUtil.trim(stringUtil.lowercase(myString))

...or we can do:

char myString[] = whatever
char newString[] = myString.lowercase().trim()

You do have to understand the associative behavior here to read this code, but for me I think the second version is way more readable.

With the makeString() example, to keep us on track for the starter question here, both IntUtil and DecUtil have a makeString() function. That's OK because they're in different interfaces, but they have different parameter lists: the IntUtil version has an int param, and the DecUtil version has a dec param (plus some optional stuff).

So then we can do this:

component provides App requires io.Output out, data.IntUtil iu, data.DecUtil du {
   int App:main(AppParam params[]) {
      int i = 17
      dec d = 12.9
      out.println("my number is $i and another number is $d")
      return 0
      }
   }

Or to write the long form of this in the associative way, the compiler is (I think!!) converting the above to:

component provides App requires io.Output out, data.IntUtil iu, data.DecUtil du {
   int App:main(AppParam params[]) {
      int i = 17
      dec d = 12.9
      out.println("my number is $(i.makeString()) and another number is $(d.makeString())")
      return 0
      }
   }

This is not ambiguous because the compiler knows it's looking for a function with a specific name and a specific first parameter type (int or dec).

Hope that's a bit helpful!

Hi, thank you both for the answers, that's perfect!