7. Predefined functions

Every Golo module definition comes with gololang.Predefined as a default import. It provides useful functions.

7.1. Console output

print and println do just what you would expect.

print("Hey")
println()

println("Hey")

7.2. Console input

readln() or readln(strMessage) reads a single line of text from the console. It always returns a string.

readPassword() or readPassword(strPassword) reads a password from the console with echoing disabled. It always returns a string. There are also secureReadPassword() and secureReadPassword(strPassword) variants that return a char[] array.

let name = readln("what's your name? ")
let value = readln()
let pwd = readpwd("type your password:")

7.3. Exceptions

raise can be used to throw a java.lang.RuntimeException. It comes in two forms: one with a message as a string, and one with a message and a cause.

try {
  ...
  raise("Somehow something is wrong")
} catch (e) {
  ...
  raise("Something was wrong, and here is the cause", e)
}

7.4. Preconditions

Preconditions are useful, especially in a dynamically-typed language.

require can check for a boolean expression along with an error message. In case of error, it throws an AssertionError.

function foo = |a| {
  require(a oftype String.class, "a must be a String")
  ...
}

You may also use requireNotNull that… well… checks that its argument is not null:

function foo = |a| {
  requireNotNull(a)
  ...
}

7.5. Arrays (deprecated)

Golo provides functions to deal with Java arrays (Object[]).

  • the Array function takes a variable number of arguments and returns a Java array from them,
  • the aget function takes an array and an index to return the element at that position,
  • the aset function takes an array, an index and a value to set the element at that position,
  • the alength function returns the length of an array,
  • the atoList function calls the java.util.Arrays.asList(values...) method.
let a = Array(1, 2, 3)
require(alength(a) == 3, "a must be of length 3")
require(aget(a, 0) == 1, "the first element shall be 1")
aset(a, 0, 666)
require(aget(a, 0) == 666, "the new first element shall be 666")

Warning

Those functions were introduced for the needs of the early developments of Golo. They will be removed at some point before the release of version 0, so please use the corresponding array object methods instead: get, set, length, …

7.6. Ranges

The range function yields an iterable range over either Integer or Long bounds:

# Prints 1 2 (...) 100
foreach i in range(1, 101) {
  print(i + " ")
}

let r = range(0, 6): incrementBy(2)
println("Start: " + r: from())
println("End: " + r: to())
foreach i in r {
  println(i)
}

println("Increment: " + r: increment())

The lower bound is inclusive, the upper bound is exclusive.

7.7. Closures

Given a closure reference or a method handle, one can convert it to an instance of an interface with a single method declaration, as in:

local function listener = |handler| -> asInterfaceInstance(ActionListener.class, handler)

# (...)
let button = JButton("Click me!")
button: addActionListener(listener(|event| -> println("Clicked!")))

It is possible to test if an object is a closure or not with the isClosure function. This is useful to support values and delayed evaluation, as in:

if isClosure(value) {
  map: put(key, value())
} else {
  map: put(key, value)
}

You can get a reference to a closure using the predefined fun function:

import golotest.Closures

local function local_fun = |x| -> x + 1

function call_local_fun = {
  let f = fun("local_fun", golotest.Closures.module)
  return f(1)
}

Because functions may be overloaded, there is a form that accepts an extra parameter for specifying the number of parameters:

import golotest.Closures

local function local_fun = |x| -> x + 1

function call_local_fun = {
  let f = fun("local_fun", golotest.Closures.module, 1)
  return f(1)
}

7.8. File I/O

Sometimes it is very desirable to read the content of a text file. The fileToText function does just that:

let text = fileToText("/some/file.txt", "UTF-8")

The first parameter is either a java.lang.String, a java.io.File or a java.nio.file.Path. The second parameter represents the encoding charset, either as a java.lang.String or a java.nio.charset.Charset.

We can write some text to a file, too:

textToFile("Hello, world!", "/foo/bar.txt")

The textToFile function overwrites existing files, and creates new ones if needed.

These functions are provided for convenience, so if you need more fine-grained control over reading and writing text then we suggest that you look into the java.nio.file package.

In addition, if you need to verify that a file exists, you can use the fileExists function.

if fileExists("/foo/bar.txt") {
  println("file found!")
}

As in the other File I/O methods, the parameter is either a java.lang.String, a java.io.File or a java.nio.file.Path. The fileExists function will return true if the file exists, false if it doesn’t.

7.9. Array types

Golo does not provide a literal syntax for array types, such as Object[].class in Java.

Instead, we provide 3 helper functions.

  • isArray(object): returns a boolean if object is an array.
  • objectArrayType(): returns Object[].class.
  • arrayTypeOf(type): given type as a java.lang.Class, returns an array of type type[].

7.10. Misc.

mapEntry gives instances of java.util.AbstractMap.SimpleEntry, and is used as follows:

let e = mapEntry("foo", "bar")

# prints "foo => bar"
println(e: getKey() + " => " + e: getValue())