Leave Comments, Critiques, and Suggestions Here
How to Migrate from Phobos to Tango
WORK IN PROGRESS
This page will try address the different modules of Phobos, and how one might approach a conversion to Tango. Many of the modules are just renamed, and in those cases just that is mentioned. For more complex usecases, we try to provide examples.
To make the transition easier, you may find Tangobos useful. This is a port of the Phobos source code that runs on top of Tango. With this you can port a little at a time.
Note that Tango fixes some bugs and limitations in Phobos.
object
Object
The toString method in Tango was originally renamed toUtf8 to better reflect what the method actually does. Recently Tango reverted back to toString in order to make it easier for code to be compatible with both Phobos and Tango.
Error
This class has been removed from Tango, as it was a subclass of Exception, and thus could be silently ignored with a
catch (Exception e) { }
which don't make sense when Errors are supposed to be unrecoverable.
std.base64
std.bitarray
The BitArray struct in std.bitarray compares to the one in tango.core.BitArray, which should provide all the functionality present in Phobos.
Use
import tango.core.BitArray;
std.boxer
See tango.core.Variant.
std.compiler
std.conv
A generic to!(Type)(fromVal) template like that in D2's std.conv can be found in tango.util.Convert.
The Format object in tango.text.convert.Format can also do many conversion tasks. It is an instance of a tango.text.convert.Layout.
For more information about Tango's formatting functions, see API docs, the manual or the formatting tutorial.
std.cover
The contents of this module, and the code coverage feature itself, are compiler-specific and are currently not available in an import library. Until a package can be devoted to compiler extensions, the following functions may be declared and used to access code coverage features:
extern (C) void dmd_coverSourcePath( char[] pathname ); extern (C) void dmd_coverDestPath( char[] pathname ); extern (C) void dmd_coverSetMerge( bool flag );
std.ctype
std.date
std.demangle
From Tango 0.99.9 you will find demangling by using
import tango.core.stacktrace.Demangler;
std.file
The functionality in this module is covered mostly by the FileProxy class and it's subclass, File in the tango.io.FileProxy and tango.io.File modules. These classes corresponds to the DirEntry struct in std.file, but provides more functionality. They can be used by importing
import tango.io.File; // or if no reading or writing is required import tango.io.FileProxy;
Most of the operations require the instantiation of either of the classes mentioned above, for instance
auto file = new File("/home/foo/myfile.txt");
The first 3 functions require a File instance, whereas the rest is found in FileProxy, except if otherwise noted.
read
By using the File instance from above, read the file using
auto res = file.read();
write
Writing to the file can be done in a similar fashion:
file.write(mycontent);
append
To append, follow the same pattern.
file.append(mycontent);
rename
If the object has been creating with an existing file or directory, it can be renamed.
scope target = new FilePath("/home/foo/newfilename.txt"); file.rename(target);
remove
Removal of the file follows the same pattern.
file.remove();
getSize
This function is also comparable.
file.getSize();
getTimes
This function is divided into three to give each of it's out parameters:
auto created = file.getCreatedTime(); auto modified = file.getModifiedTime(); auto accessed = file.getAccessedTime();
exists
To check if the path File or FileProxy instance points to, exists as a file or directory, do
if (file.isExisting) { ... }
getAttributes
Don't currently exist in Tango.
isfile, isdir
Since these are mutually exclusive options, FileProxy.isDirectory will return true if it is a directory, false if it is a file.
if (file.isDirectory) { // f is a directory } else { // f is a file }
chdir
This functionality is provided in the tango.io.FileSystem, to use it do
import tango.io.FilePath; import tango.io.FileSystem; scope dir = new FilePath("/home/foo/changetodir"); FileSystem.setDirectory(dir);
mkdir
To create a directory pointed to by a FileProxy instance, do
file.createDirectory();
rmdir
To remove a file or folder pointed to by a FileProxy instance, do
file.remove();
getcwd
This functionality is provided in the tango.io.FileSystem, to use it do
import tango.io.FileSystem; auto dir = FileSystem.getDirectory();
listdir
The basic listdir corresponds to FileProxy.toList, which can be used as follows
auto list = f.toList();
std.format
Tango's tango.text.convert.Layout module is the one most similar to std.format, in that the functionality in Layout is used to provide formatting for various purposes such as formatted printing via Stdout.formatln. This is much the same as how std.format is used to do the formatting for std.stdio.writefln and other functions in Phobos.
Layout is a template that can be instantiated for different character types (char,wchar,or dchar). A default char (UTF8) instance is available in tango.text.convert.Format.
For more information about Tango's formatting functions, see API docs, the manual or the formatting tutorial.
std.gc
Interface to interact with the garbage collector, is found in tango.core.Memory.
std.intrinsic
The symbol names for these functions are hardcoded into DMD, however, Tango provides a wrapper module for std.intrinsic that is the preferred method for accessing these functions. This module is tango.core.Intrinsic and may be imported by doing:
import tango.core.Intrinsic;
Be aware that if any name collisions occur, the Phobos name must be provided to disambiguate (ie. std.intrinsic.*).
std.math
Most of the functions in std.math have their equivalents in tango.math.Core, so for those, do
import tango.math.Core;
Note that all the functions here are pure D implementations, and do not use any standard C routines.
Some of the functions present in std.math are low-level math functions, used mainly in library functions. These are imported from tango.math.IEEE by doing
import tango.math.IEEE;
See below for which functions this concerns.
Some of the functions are currently just wrappers around standard C routines, but will replaced by D routines at a later time. Do not use tango.stdc.math to access those functions.
The error functions erf() and erfc() are found in tango.math.ErrorFunction. The gamma functions tgamma() and lgamma() have been moved to tango.math.GammaFunction, but with names changed to gamma() and logGamma().
rndtol
This function does not have an equivalent in Tango.
rndtoln
This function does not have an equivalent in Tango.
modf
This function is just a wrapper around the standard C routine, use from tango.stdc.math.
fabs
Use abs from tango.math.Core instead.
nearbyint
rint
This function is just a wrapper around the standard C routine, use from tango.stdc.math.
lrint
Use rndlong from tango.math.Core.
round
This function is just a wrapper around the standard C routine, use from tango.stdc.math.
lround
This function is just a wrapper around the standard C routine, use from tango.stdc.math.
trunc
This function is just a wrapper around the standard C routine, use from tango.stdc.math.
remainder
Use the mod operator (%) instead.
remquo
This function is just a wrapper around the standard C routine, use from tango.stdc.math.
isnan, isfinite, isnormal, issubnormal, isinf
These classification functions can all be found in tango.math.IEEE, with name capitalisation changes. Many of these functions also have built-in equivalents in the language.
- isNan(x) is equivalent to x!<>0.
- isFinite(x) is equivalent to abs(x)<real.max.
- isInfinity(x) is equivalent to abs(x)==real.infinity.
signbit, copysign
Found in tango.math.IEEE.
nan
The Phobos version of this function did nothing. In Tango, NaN payloads are created with the NaN functions in tango.math.IEEE.
nextafter
Included in tango.math.IEEE with the name nextAfter(), but consider using nextUp() or nextDown() instead.
fdim, fma
Included in tango.math.IEEE.
fmax, fmin
tango.math.Core has max, min, maxNum and minNum.
feqrel
LOCATION NOT YET DETERMINED. Currently in tango.math.IEEE.
std.md5
std.mmfile
std.openrj
std.outbuffer
std.path
The functionality in std.path can mostly be found in tango.io.FilePath. Where std.path provides stand alone functions, FilePath provides two classes, one mutable and one immutable. These classes takes a path as the constructor argument, and provide queries towards this. Since the object is filled at construction, there might be a slight performance hit if you need to query only once, whereas the information is already there for every subsequent query towards the same path, and performance should be better for those cases.
The separator constants are provided in the tango.io.FileConst and changed to camelCase style naming.
Unless otherwise specified, all imports for the Tango examples are
import tango.io.FilePath; import tango.io.FileConst; // if you need path constants
getExt
char[] mypath = "myfile.ext"; char[] res = getExt(mypath);
translates to
scope mypath = new FilePath("myfile.ext"); auto res = mypath.getExt();
getName
char[] mypath = "/home/foo/bar"; char[] res = getName(mypath);
translates to
scope mypath = new FilePath("/home/foo/bar"); auto res = mypath.getFullPath();
getBaseName
char[] mypath = "/home/foo/bar"; char[] res = getBaseName(mypath);
translates to
scope mypath = new FilePath("/home/foo/bar"); auto res = mypath.getName();
getDirName
char[] mypath = "/home/user"; char[] res = getDirName(mypath);
translates to
scope mypath = new FilePath("/home/user"); auto res = mypath.getPath();
getDrive
char[] mypath = r"C:\foo\bar"; char[] res = getDrive(mypath);
translates to
scope mypath = new FilePath(r"C:\foo\bar"); auto res = mypath.getRoot();
defaultExt
This function don't have an equivalent in Tango.
addExt
char[] mypath = "myfile.foo"; char[] res = addExt(mypath, "ext");
translates to
scope mypath = new FilePath("myfile.foo"); auto res = mypath.asSuffix(mypath.getSuffix() ~ ".ext");
isabs
char[] mypath = "/home/foo"; bool absolute = isabs(mypath);
translates to
scope mypath = new FilePath("/home/foo"); auto absolute = mypath.isAbsolute();
join
char[] res = join("/home/foo", "bar/readme.txt");
translates to
scope myPath = new FilePath("bar/readme.txt"); auto res = myPath.join("/home/foo");
fncharmatch
The equivalent resides in tango.util.PathUtil, with the name charMatch().
fnmatch
The equivalent resides in tango.util.PathUtil, with the name patternMatch().
expandTilde
This currently resides in the tango.posix project, the module posix.utils.Tilde.
length
If you need to check whether the path has a length larger than zero, or not, use
if (mypath.isEmpty) { ... }
std.process
Phobos only presents a wrapper around the common C API for executing external programs, while Tango provides an abstraction that is easy to use and extend in tango.sys.Process and tango.sys.Pipe . It also lets you use stdin, stdout, and stderr within the Tango IO/conduit framework, so you can iterate over output, redirect using pipes, and more.
For just executing a process, do
import tango.sys.Process;
If you also want to manipulate the pipes, use the import
import tangy.sys.Pipe;
A simple example follows
try { import tango.sys.Process; uint i = 0; auto p = new Process("ls -al"); p.execute(); Stdout.formatln("Output from {0}:", p.programName); foreach (line; new LineIterator!(char)(p.stdout)) { Stdout.formatln("line {0}: '{1}'", i++, line); } auto result = p.wait(); Stdout.formatln("Process '{0}' ({1}) exited with reason {2}, status {3}", p.programName, p.pid, cast(int) result.reason, result.status); } catch (ProcessException e) { Stdout.formatln("Process execution failed: {0}", e.toString()); }
The C execvpe function is present as a static function of the Process class.
std.random
The std.random functions have their equivalents in the tango.math.Random module, and to access them, do
import tango.math.Random;
rand_seed
The random number generator in Tango is a class with static methods that seeds itself from the current time through a static constructor. If you want to reseed, do
Random.seed(mynewseed);
rand
To get the next random number from the generator, you can either do
auto randomnumber = Random.get();
or
auto randomnumber = Random.get(limit);
where limit is the maximum number you want returned.
std.regexp
Tango's tango.text.Regex has been imported from Phobos and can be found by doing
import tango.text.Regex;
std.signals
std.socket
std.socketstream
std.stdint
This module is available as a part of the standard C library in Tango, which is located in the package tango.stdc.
std.stdio
The functionality in std.stdio corresponds mostly to that found in tango.io.Stdout, especially can writef be exchanged with Stdout, although note that Tango uses the new format string syntax found in .Net String.format. Thus
import std.stdio; writefln("Lucky number is %s.", 42);
becomes
import tango.io.Stdout; Stdout.format("Lucky number is {}", 42).newline;
For the extended functionality in Tango's formatted output, see API docs, the manual or the formatting tutorial.
std.cstream
std.stream
std.string
toString(int) can be found in tango.text.convert.Integer (Note the recent change: It used to be called toUtf8 in Tango).
toString
int myint = 3; char[] res = toString(myint);
translates to
import tango.text.convert.Integer; int myint = 3; auto res = toString(myint);
format
import std.string; char[] res = std.string.format("Completed %s of %s", i,N);
translates to
import tango.text.convert.Format; char[] res = Format("Completed {} of {}", i,N);
For more information about Tango's formatting functions, see API docs, the manual or the formatting tutorial.
std.system
std.thread
Tango exposes its threading features in tango.core.Thread with a similar interface to the one available in Phobos. Differences which may affect existing code are:
- Thread.wait() is called Thread.join().
- Thread.wait( milliseconds ) is not available.
- stacksize is not available as a a ctor option, though its addition is being considered.
- Thread.run() is not available. Classes deriving from Thread should pass a delegate to super().
- Thread.getState() is not available. Thread.isRunning() is offered in its place.
- Thread.setPriority() is not available. Scheduling features may be added later.
- Thread.isSelf() is not available. Thread.getThis() can easily be used for a similar purpose.
- Thread.pause(), resume(), pauseAll(), and removeAll() are not available as they are dangerous.
The Tango thread module also has many features which Phobos lacks. These are explained in the module documentation, and further in the threading chapter of the manual.
std.traits
Basic type traits functionality in Tango is available in tango.util.meta.Traits, which may be imported as
import tango.util.meta.Traits;
std.typetuple
std.uni
std.uri
std.utf
std.zip
std.zlib
std.c.*
std.outofmemory
This module unnecessarily exposes internal functionality and is not available in Tango. Its nearest equivalent would be tango.core.Exception which may be impoted as
import tango.core.Exception;