Pointers, functions and arrays in D Programming Language - arrays

I'm writing a method to output to several output streams at once, the way I got it set up right now is that I have a LogController, LogFile and LogConsole, the latter two are implementations of the Log interface.
What I'm trying to do right now adding a method to the LogController that attaches any implementation of the Log interface.
How I want to do this is as follows: in the LogController I have an associative array, in which I store pointers to Log objects. When the writeOut method of the LogController is called, I want it to then run over the elements of the array and call their writeOut methods too. The latter I can do, but the previous is proving to be difficult.
Mage/Utility/LogController.d
module Mage.Utility.LogController;
import std.stdio;
interface Log {
public void writeOut(string s);
}
class LogController {
private Log*[string] m_Logs;
public this() {
}
public void attach(string name, ref Log l) {
foreach (string key; m_Logs.keys) {
if (name is key) return;
}
m_Logs[name] = &l;
}
public void writeOut(string s) {
foreach (Log* log; m_Logs) {
log.writeOut(s);
}
}
}
Mage/Utility/LogFile.d
module Mage.Utility.LogFile;
import std.stdio;
import std.datetime;
import Mage.Utility.LogController;
class LogFile : Log {
private File fp;
private string path;
public this(string path) {
this.fp = File(path, "a+");
this.path = path;
}
public void writeOut(string s) {
this.fp.writefln("[%s] %s", this.timestamp(), s);
}
private string timestamp() {
return Clock.currTime().toISOExtString();
}
}
I've already tried multiple things with the attach functions, and none of them. The build fails with the following error:
Mage\Root.d(0,0): Error: function Mage.Utility.LogController.LogController.attach (string name, ref Log l) is not callable using argument types (string, LogFile)
This is the incriminating function:
public void initialise(string logfile = DEFAULT_LOG_FILENAME) {
m_Log = new LogController();
LogFile lf = new LogFile(logfile);
m_Log.attach("Log File", lf);
}
Can anyone tell me where I'm going wrong here? I'm stumped and I haven't been able to find the answer anywhere. I've tried a multitude of different solutions and none of them work.

Classes and interfaces in D are reference types, so Log* is redundant - remove the *. Similarly, there is no need to use ref in ref Log l - that's like taking a pointer by reference in C++.
This is the cause of the error message you posted - variables passed by reference must match in type exactly. Removing the ref should solve the error.

Related

Static extension methods in Kotlin

How do you define a static extension method in Kotlin? Is this even possible? I currently have an extension method as shown below.
public fun Uber.doMagic(context: Context) {
// ...
}
The above extension can be invoked on an instance.
uberInstance.doMagic(context) // Instance method
but how do I make it static method like shown below.
Uber.doMagic(context) // Static or class method
To achieve Uber.doMagic(context), you can write an extension to the companion object of Uber (the companion object declaration is required):
class Uber {
companion object {}
}
fun Uber.Companion.doMagic(context: Context) { }
This is what the official documentation says:
Kotlin generates static methods for package-level functions. Kotlin
can also generate static methods for functions defined in named
objects or companion objects if you annotate those functions as
#JvmStatic. For example:
Kotlin static methods
class C {
companion object {
#JvmStatic fun foo() {}
fun bar() {}
}
}
Now, foo() is static in Java, while bar() is not:
C.foo(); // works fine
C.bar(); // error: not a static method
I actually had this exact question 30 minutes ago, so I started digging around and couldn't find any solution or workaround for this, BUT while searching I found this section on the Kotlinglang website that states that:
Note that extensions can be defined with a nullable receiver type. Such extensions can be called on an object variable even if its value is null.
So then I had the craziest idea ever, why not define an extension function with a nullable receiver (without actually using that receiver) and then call it on a null object!
So I tried that, and it worked pretty well, but it looked so ugly. It was like this:
(null as Type?).staticFunction(param1, param2)
So I went around that by creating a val in my extensions file of the receiver type that had a value of null and then use it in my other class.
So, as an example, here is how I implemented a "static" extension function for the Navigation class in Android:
In my NavigationExtensions.kt file:
val SNavigation: Navigation? = null
fun Navigation?.createNavigateOnClickListener(#IdRes resId: Int, args: Bundle? = null, navOptions: NavOptions? = null,
navigationExtras: Navigator.Extras? = null) : (View) -> Unit {
//This is just implementation details, don't worry too much about them, just focus on the Navigation? part in the method declaration
return { view: View -> view.navigate(resId, args, navOptions, navigationExtras) }
}
In the code that uses it:
SNavigation.createNavigateOnClickListener(R.id.action_gameWonFragment_to_gameFragment)
Obviously, this isn't a class name, it is just a variable of the class type that has a null value. This is obviously ugly on the extension maker side (because they have to create the variable) and on the developer side (because they have to use the SType format instead of the actual class name), but it is the closest that can be achieved right now compared to actual static functions. Hopefully, the Kotlin language makers will respond to the issue that was created and add that feature in the language.
Since I keep coming across this when searching, here's a different approach I haven't seen anyone mention that works in a static way and it works with generics!
Extension definitions:
// Extension function
fun <T> KClass<T>.doSomething() = /* do something */
// Extension Property
val <T> KClass<T>.someVal get() = /* something */
Usage:
MyType::class.doSomething()
MyType::class.someVal
As you can see, the trick is attaching the extension function to the KClass of the type instead since that can be referenced statically.
You can create a static method with using Companion object like:
class Foo {
// ...
companion object {
public fun bar() {
// do anything
}
}
}
and then you can call it like:
class Baz {
// ...
private fun callBar() {
Foo.bar()
}
}
Recomend you to look at this link. As you can see there, you just should declare method at the top-level of the package (file):
package strings
public fun joinToString(...): String { ... }
This is equal to
package strings;
public class JoinKt {
public static String joinToString(...) { ... }
}
With constans everything are the same. This declaration
val UNIX_LINE_SEPARATOR = "\n"
is equal to
public static final String UNIX_LINE_SEPARATOR = "\n";
I also required the ability to extend a Java object with a static method and found the best solution for me was to create a Kotlin object that extended the Java class and add my method there.
object Colour: Color(){
fun parseColor(r: Int?, g: Int?, b: Int?) = parseColor(String.format("#%02x%02x%02x", r, g, b))
}
invocation:
val colour = Colour.parseColor(62, 0, 100)
I'm also quite fond of having the possibility to add static extension methods in Kotlin. As a workaround for now I'm adding the exntension method to multiple classes instead of using one static extension method in all of them.
class Util
fun Util.isDeviceOnline(context: Context): Boolean {
val connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connMgr.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}
fun Activity.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
fun OkHttpClient.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
To create an extension method in kotlin you have to create a kotlin file(not a class) then declare your method in the file
Eg:
public fun String.toLowercase(){
// **this** is the string object
}
Import the function in the class or file you are working on and use it.

Class Array in D

Can I create a class array in D? Something like:
interface A {}
class AA: A {}
class AB: A {}
class AC: A {}
ClassList!A list = new ClassList!A {AA, AB, AC};
void testf(ulong testv) {
A a = new list[testv];
}
Yes, that's possible, though not necessarily exactly how you have it there. You can make a list of types with a type tuple:
import std.typetuple;
alias list = TypeTuple!(AA, AB, AC);
But, you can't index it like an array at runtime; trying new list[n] will be a compile time error. Instead, you'll create a helper function that loops over it and returns the instance, like this:
foreach(index, type; list)
if(index == testv) {
a = new type();
break;
}
The way that compiles is foreach(foo; compile_time_list) actually becomes a big unrolled loop. The generated code is as if you wrote:
if(0 == testv) { a = new AA(); goto end; }
if(1 == testv) { a = new AB(); goto end; }
if(2 == testv) { a = new AC(); goto end; }
end:
So that works with runtime values, bridging the gap between the compile time list and the array index you want.
It's worth noting that this isn't necessarily the most efficient, but unless your class list has like a thousand entries, i doubt that would matter. Another option for more speed is to generate a switch statement at compile time from your list, then mix that in. The switch statement will compile to a more efficient lookup table. But odds are the simple loop is fine.
Anyway, putting it together, we get:
import std.stdio;
interface A {}
class AA: A {}
class AB: A {}
class AC: A {}
import std.typetuple;
alias list = TypeTuple!(AA, AB, AC);
void testf(ulong testv) {
A a;
foreach(index, type; list)
if(index == testv) {
a = new type();
break;
}
if(a is null)
writeln("bad type index");
else {
writeln(typeid(cast(Object) a), " was created");
}
}
void main() {
testf(0);
testf(1);
testf(2);
testf(3);
}
Result:
$ ./test50
test50.AA was created
test50.AB was created
test50.AC was created
bad type index
just what we wanted.
BTW, the typeid(cast(Object) a) might look weird, that's fetching the dynamic class of the type. It has to cast to Object first because otherwise, it would print the interface name. Since D interfaces aren't necessarily D classes (they can also be COM objects or C++ classes), the typeid isn't always available. A cast to Object ensures that it is a D class and thus grabs the run time type details.
EDIT: I saw you asked on the newsgroup as well for checking the base class in the loop. Here's how to do that:
You could write your own tuple template for it, or just let the
compile fail on the factory function: the A a = new T(); will
fail if A isn't a base class or interface of T.
Putting the check in the list could look like this:
bool checkClassList(Base, T...)() {
foreach(t; T) {
static if(!is(t : Base))
static assert(0, t.stringof ~ " is not a child of " ~ Base.stringof);
}
return true;
}
template ClassList(Base, T...) if(checkClassList!(Base, T)) {
alias ClassList = T;
}
Usage:
alias list = ClassList!(A, AA, AB, AC); // good
add:
class B {}
alias list = ClassList!(A, AA, AB, AC, B);
and get error:
test50.d(12): Error: static assert "B is not a child of A"
test50.d(19): instantiated from here: checkClassList!(A, AA, AB, AC, B)

Using a weka decision tree classifier without the whole weka library?

I have trained a classifier for my instances, and now want to export it to an Android application, where the Weka library will be unavailable.
It is not suitable to simply add the Weka library in the Android application, because of it's size (6.5 Mb).
Is there any other way to use my classifier to evaluate and label other unlabeled instances? Are there any smaller, independent library specifically design for this?
Of course I could, eventually, write my own library to interpret the output model of Weka, but it would seem logical to me, that such a solution already exists. (although it escapes me, somehow)
There are no independent libraries that would do what you want. You could remove all the parts of Weka you don't need and package that into a library.
In your particular case, the easiest thing to do might be to take the decision tree that Weka learns and put it directly into the code in a series of if...else statements. You could even write a script that takes the (graphical) output of the decision tree and writes that code for you.
After paying more attention the output model of weka, I noticed that by using the option that generates the tree in a Java class form, I can use it separatly from the weka library.
You can remove the generated WekaWrapper and keep only the internal class, which is a basic implementation of the tree:
The class looks something like this:
public class WekaWrapper
extends Classifier {
/**
* Returns only the toString() method.
*
* #return a string describing the classifier
*/
public String globalInfo() {
return toString();
}
/**
* Returns the capabilities of this classifier.
*
* #return the capabilities
*/
public Capabilities getCapabilities() {
weka.core.Capabilities result = new weka.core.Capabilities(this);
result.enable(weka.core.Capabilities.Capability.NOMINAL_ATTRIBUTES);
result.enable(weka.core.Capabilities.Capability.NOMINAL_CLASS);
result.enable(weka.core.Capabilities.Capability.MISSING_CLASS_VALUES);
result.setMinimumNumberInstances(0);
return result;
}
/**
* only checks the data against its capabilities.
*
* #param i the training data
*/
public void buildClassifier(Instances i) throws Exception {
// can classifier handle the data?
getCapabilities().testWithFail(i);
}
/**
* Classifies the given instance.
*
* #param i the instance to classify
* #return the classification result
*/
public double classifyInstance(Instance i) throws Exception {
Object[] s = new Object[i.numAttributes()];
for (int j = 0; j < s.length; j++) {
if (!i.isMissing(j)) {
if (i.attribute(j).isNominal())
s[j] = new String(i.stringValue(j));
else if (i.attribute(j).isNumeric())
s[j] = new Double(i.value(j));
}
}
// set class value to missing
s[i.classIndex()] = null;
return WekaClassifier.classify(s);
}
/**
* Returns the revision string.
*
* #return the revision
*/
public String getRevision() {
return RevisionUtils.extract("1.0");
}
/**
* Returns only the classnames and what classifier it is based on.
*
* #return a short description
*/
public String toString() {
return "Auto-generated classifier wrapper, based on weka.classifiers.trees.Id3 (generated with Weka 3.6.9).\n" + this.getClass().getName() + "/WekaClassifier";
}
/**
* Runs the classfier from commandline.
*
* #param args the commandline arguments
*/
public static void main(String args[]) {
runClassifier(new WekaWrapper(), args);
}
}
class WekaClassifier {
private static void checkMissing(Object[] i, int index) {
if (i[index] == null)
throw new IllegalArgumentException("Null values are not allowed!");
}
public static double classify(Object[] i) {
return node0(i);
}
protected static double node0(Object[] i) {
return 0.0; // unacc
}
}
So, yeah, in fact you can do it really easy. Things to remember:
to classify an instance, call the classify(Object[]) method;
the return value will be a float value;
the return values are explained in comments, right next to the return command;
the parameters have no validation, so be careful in which order you are inputing them (this part was done by the weka dependent part);
the order is the one defined in the arff file.
If you want to run RandomForests, you can use a little script I wrote that turns the output of WEKA's -printTrees option of the RandomForest classifier into Java source code.
http://pielot.org/2015/06/exporting-randomforest-models-to-java-source-code/
The code you need to include into your Android app will consist of three classes only: the class with the generated model + two classes to make the classification work.

how to make getArray method

When I run a specific part of a code I have:
public String getWords (){
randomWord = words[randy.nextInt(words.length)];
return randomWord;
}
private String[] words = {"apple", "beret", "arose", "along", "beamy", "becks", "decks", "barks",
"stark", "start", "stabs", "baggy", "asked", "asset", "asses", "audit",
"bowls", "boxes", "seats", "balls", "boats", "boxer", "brick", "bound",
"brass", "caked", "braid", "caged", "essay", "fault", "dents", "dutch",
"ethos", "dunks", "pains", "faxes", "mummy", "mixer", "mills", "might",
"moral", "teeth", "wings", "works", "walls", "tolls", "crawl", "toxin",
"bangs", "tough"};
Hangman man = new Hangman();
man.mainScreen();
public void mainScreen (){
start();
while (guesses != maxGuesses){
continueGame();
checkBodyParts();
}
gameOver();
}
ERROR:
java.lang.NullPointerException
at Hangman.getWords(Hangman.java:43)
at Hangman.<init>(Hangman.java:28)
at GameApp.main(GameApp.java:9)
I get a runtime error of NullPointerException. I asked around and they said I should make a method to get the array words because I can't get to it at the moment. What should this method have in it?
I believe your problem is here:
private String myGeneratedRandomWord = getWords();
This method is trying to use the array "words" before it is created.
Move this line after the array "words" is created.
This should solve your NullPointerError.

How do I use Control.Invoke if I need to pass in a mixture of reference and value types?

How do I do something like the following?
private delegate void RenameOperation(string name, string uniqueName, int position);
private void AssignColumnNames(string name, string uniqueName, int position)
{
dataGridView1.Columns[position].HeaderCell.Value = name;
dataGridView1.Columns[position].HeaderCell.Tag = uniqueName;
}
void SomeFunction()
{
int colCount = 0;
// ... some other code
if (dataGridView1.InvokeRequired)
{
RenameOperation rename = new RenameOperation(AssignColumnNames);
dataGridView1.Invoke(rename, member.Name, member.UniqueName, colCount);
}
}
Each time I do this I get Object of type 'System.Int32[]' cannot be converted to type 'System.Int32' and I don't know how to solve my problem at all. I could probably code this very differently but I'm interested in why I can't do this.
Managed to solve my own problem here - for anyone who is interested I had passed colCount into invoke between declaring it and calling this invoke, but had written: dataGridView1.Invoke(new ResizeOperation(AddColumn), new[] { colCount }); because I thought the type information there was redundant.

Resources