Input and output

Table of contents

  1. Command-line
    1. Input
    2. Output
  2. String formatting
    1. First examples
    2. Named arguments
  3. Files
    1. Text files
    2. Binary files
    3. Configuration files

Command-line

Input

For command-line input, a function called input is used. It takes an optional argument: the prompt, that is simply a text printed before one can type input into the input line. And it returns a string, containing the text that was typed. Here is a most basic example:

s = input("Please type something and press return: ")
print("Input was: '", s, "'".)

That input string can be converted into an integer or a floating point number:

s = input("> ")
print([s,int(s),float(s)])

Output

For command-line output, the function print is used. It takes any number of arguments, converts its arguments into strings and joins them together.

> print("a",12,"|",3.4,[1,2])
# Output:
# a12|3.4[1, 2]

That is to say, the equation

print(*a) ≡≡ print(a.join())
≡≡ print(a.map(str).join())

holds. This allows us to express an alternative version of print that takes a separator.

function print(a,sep)
   put(a.join(sep),"\n")
end

print([1,2,3],"|")
# Output:
# 1|2|3

String formatting

First examples

Let us have a look on the following example.

for x in 1..8
   print([x,2^x])
end

We would like it to be printed in tabular format. This is achieved as follows.

for x in 1..8
   print("{} | {:r4}" % [x,2^x])
end

This {} is a placeholder for the value of x, and {:r4} is a placeholder for the value of 2^x. That r4 means "right align by four spaces padding".

# Leading zeros
for x in 1..8
   print("{} | {:r3(0)}" % [x,2^x])
end

# Fill the space with dots
for x in 1..8
   print("{}{:r5(.)}" % [x,2^x])
end

Alternatively:

for x in 1..8
   print("{} | {}" % [x,str(2^x).rjust(3,'0')])
end

Note that print(x,y,z) is the same as print([x,y,z].join()). For oversight, have a look on the following table.

Print sth. to the command-line Convert sth. into a string
basic print(x,y,z) s = [x,y,z].join()
formatted print(template % [x,y,z]) s = template % [x,y,z]

But if an integer n is to be converted into a string, str(n) can be used simply instead of [n].join().

Named arguments

If the template string is very large, it is better to use named arguments.

print("{x} | {y}" % {x=360,y=240})

If an argument shall occur repeatedly, the arguments can be named or indexed.

print("{x} | {y} | {x} | {x}" % {x=360,y=240})
print("{0} | {1} | {0} | {0}" % [360,240])

Formatting is placed after a colon.

print("{x:r4} | {y:r4}" % {x=360,y=240})
print("{0:r4} | {1:r4}" % [360,240])

Formatting integers

To convert an integer into a hexadecimal representation:

hex = |n| "0x{:x}"%[n]

To convert an integer in range 0..255 into a hexadecimal representation:

hex2 = |n| "0x{:r2(0)x}"%[n]

To convert an integer into a binary representation:

bin = |n| "0b{:b}"%[n]

To convert an integer in range 0..255 into a binary representation:

bin8 = |n| "0b{:r8(0)b}"%[n]

Files

Text files

Reading a text file is very convenient:

s = read("file.txt")

The more general file system interface provides more control:

use fs: open

s = open("file.txt").read().decode("utf-8")

Binary files

The following program obtains 10 bytes of random data:

use fs: open

f = open("/dev/urandom")
a = f.read(10).list()

Configuration files

A possible way to express configurations is to simply state them as Moss code. In doing so, the expressions are loaded as a Moss module or by eval. A passive data structure looks as follows:

# patterns.moss
# =============
pattern1 = {
   color = "yellow",
   width = 12.4,
   center = [2,0],
   tail = {
      color = "blue",
      height = 4.2
   }
}

# m.moss
# ======
patterns = load("patterns")
p = patterns.pattern1

Now, patterns is a module object. Using record, it may be considered to be a map:

patterns = record(load("patterns"))
p = patterns["pattern1"]