If you're coming from C++, perhaps you're going to miss cout or some of those fancing ostream stuff in fstream. In Julia, you have print and println, but you have to enclose everything in brackets and the ',' seperation is not really what you're used to when you're coming from C++. I also always enjoyed how easy it is in Java to compose strings. Luckily, it is very easy to incorporate the ostream and String behaviour into Julia, and it also shows some of the nice features of Julia.
cout << "Hello, Julia!\n";
First, we're going to create a
singleton named
cout. There is a special syntax for singletons in Julia (see
here): a type without members.
Next, we'll need a function which handles the operator <<. This works much like in C++, since
operators are functions. The function will just take the other argument, and print it:
# our coutType singleton
type coutType
end
cout = coutType()
# the operator <<
function << (c::coutType, t)
print(t)
return cout
end
Here we have to apply the same mechanism as in C++: The operator << returns the output object so that chained <<'s are possible. Now we can try our code:
julia> cout << "Hello, Julia! It is " <<
time()/3600/24/365 << " years since epoch.\n";
Hello, Julia! It is 42.93542962147783 years since epoch.
If you omit the ; at the end, you still have valid julia code, but in the julia shell you will get an output like
coutType(XXXX) after your output (in loaded files you won't). That's because the julia shell automatically displays the return values of the last statement. ; is the
chained expressions operator , so by inserting a ; at the end you are inserting an empty instruction, which has no return type.
Note that you have to enclose temporary calculations in brackets like for
cout << (1+2) << " is " << 3 << "\n"; .
"composing " + "Strings"
Next we want to have something to use strings as in Java: a = "it's the year " + 2012 + "!". For this, we need to specify a function for +:
# + for strings with variable number of arguments
function +(a::ASCIIString, tArgs...)
for t in tArgs
a = strcat(a,t)
end
return a
end
Here we used Julias nice
vargs ability combined with the
fact that something like "a"+2+"c" is translated in + ("a", 2, "b").
fstream
Of course you can apply the cout idea to other streams, here's for files:
# << operator for files
function << (out::IOStream, t)
write(out, t)
return out
end
# .<< operator for files for writing data stringified (e.g. 2 as "2")
function .<< (out::IOStream, t)
write(out, string(t))
return out
end
And again an example:
myFile=open("year.txt", "w")
year = 2012
myFile << "It is the year " .<< year << ".\n"
close(myFile)
Notice the use of the .<< operator here so 2012 is translated to the string "2012" before being written to the file (otherwise it will write 2012 as binary).
split ostreams
Another idea is to create objects that stream into the console and into a file, which is useful for logging and similar tasks:
type loggerType
file::IOStream
end
logger = loggerType(open("log.txt", "w"))
function << (out::loggerType, t)
out.file .<< t
cout << t
return out
end
year = 2012
logger << "Still the year " << 2012 << "!\n"
close(logger.file)