Using functions as map keys in Haxe - haxe

I want to use functions as keys in a Map like this:
var timers : Map<Void->Void, snow.api.Timer>;
But Haxe won't compile:
Abstract Map has no #:to function that accepts IMap<Void -> Void, snow.api.Timer>
Is there a way to do this ?

It's easy to write a custom implementation:
import haxe.Constraints;
class FunctionMap<K:Function,V> implements IMap<K,V> {
private var _keys : Array<K>;
private var _values : Array<V>;
public function new () {
_keys = [];
_values = [];
}
public function get(k:K):Null<V> {
var keyIndex = index(k);
if (keyIndex < 0) {
return null;
} else {
return _values[keyIndex];
}
}
public function set(k:K, v:V):Void {
var keyIndex = index(k);
if (keyIndex < 0) {
_keys.push(k);
_values.push(v);
} else {
_values[keyIndex] = v;
}
}
public function exists(k:K):Bool {
return index(k) >= 0;
}
public function remove(k:K):Bool {
var keyIndex = index(k);
if (keyIndex < 0) {
return false;
} else {
_keys.splice(keyIndex, 1);
_values.splice(keyIndex, 1);
return true;
}
}
public function keys():Iterator<K> {
return _keys.iterator();
}
public function iterator():Iterator<V> {
return _values
.iterator();
}
public function toString():String {
var s = new StringBuf();
s.add("{");
for( i in 0..._keys.length ) {
s.add('<function>');
s.add(" => ");
s.add(Std.string(_values[i]));
if( i < _keys.length - 1 )
s.add(", ");
}
s.add("}");
return s.toString();
}
private function index(key:K) : Int {
for (i in 0..._keys.length) {
if (Reflect.compareMethods(key, _keys[i])) {
return i;
}
}
return -1;
}}
http://try.haxe.org/#DdF31

I just tried this in try.haxe.org, and the compiler doesn't seem to like it, so I'm guessing the answer is "no."
You could get around this with some cleverness:
class Test {
static function main() {
var map:Map<VoidVoid,String>;
map = new Map<VoidVoid,String>();
var thing = {func:foo};
map.set(thing,"bar");
trace(map.get({func:foo})); //fails
trace(map.get(thing)); //succeeds;
}
static function foo():Void
{
}
}
typedef VoidVoid = {
var func:Void->Void;
}
But that's not an ideal solution because wrapping it in a typedef like that will make it fail if it's not the exact same instance, even if the value inside is the same.
I also tried making a Map<Dynamic,String> since you can stuff function references in those, but that didn't work either.
At this point I should ask, what problem are you trying to solve this way? Perhaps it could be better solved some other way.

Related

Optional class-code generation in dependence of functions implemented by generics in haxe

Assuming I have the following classes in Haxe:
class Pair<U, V> {
public var first:U = null;
public var second:V = null;
public function new(u:U, v:V) {
this.first = u;
this.second = v;
}
}
class HashablePair<U:{ function hashCode():Int; }, V:{ function hashCode():Int; }> {
public var first:U = null;
public var second:V = null;
public function new(u:U, v:V) {
this.first = u;
this.second = v;
}
public function hashCode():Int { // just a sample way ...
var h1:Int = (first == null) ? 0 : first.hashCode();
var h2:Int = (second == null) ? 0 : second.hashCode();
return 3 * h1 + 5 * h2;
}
}
I wondered if it is possible to write a macro that adds the hashCode function to the pair class, if and only if both generics U and V implement the hashCode-function ... and thus make it possible to combine the two classes into a single one via meta-programming.
You can achieve the desired behavior by simply switching to an abstract:
typedef Hashable = { function hashCode():Int; };
abstract HashablePair<U:Hashable,V:Hashable>(Pair<U,V>)from Pair<U,V> {
public function new(u:U, v:V)
this = new Pair(u, v);
public function hashCode():Int { // just a sample way ...
var h1:Int = (this.first == null) ? 0 : this.first.hashCode();
var h2:Int = (this.second == null) ? 0 : this.second.hashCode();
return 3 * h1 + 5 * h2;
}
}
The from Pair<U,V> makes Pair<U,V> casts to HashablePair<U,V> allowed, as long as the necessary constrains on U and V are respected.
For a complete exemple, check out Try Haxe #d76E1.

Multi-valued mappings in Solidity

I need to be able to have several possible values under the same key in a mapping. Today, Solidity's mappings are mono-valued: writing a value overwrite the previous one (which is still in the blockchain, but not retrievable by a contract). I wrote this code to have multi-valued mappings:
contract MVM {
struct Bucket {
bool exists;
uint num; // Never decreases: we can only add records, not remove them.
mapping(uint => Record) records;
}
struct Record {
bool exists;
string info;
}
// Do not make it public: the compiler crashes when generating
// accessors https://github.com/ethereum/solidity/issues/633
mapping(string => Bucket) data;
function set(string key, string value) {
if (data[key].exists) {
data[key].records[data[key].num] = Record(true, value);
}
else {
data[key].exists = true;
data[key].records[0] = Record(true, value);
}
data[key].num++;
}
function num_of(string key) returns (uint) {
return data[key].num; // Guaranteed to be initialized as zero?
}
function get(string key, uint index) returns (string) {
if (!data[key].exists || !data[key].records[index].exists) {
throw;
}
return data[key].records[index].info;
}
}
An example of its use from the geth console:
> mvs.set.sendTransaction("foo", "bar", {from:eth.accounts[0], gas: 1000000})
"0x79c52c437a94f3301775acec5639404eff563fce1a99ad097f5db28f109d7ab5"
> mvm.set.sendTransaction("foo", "thing", {from:eth.accounts[0], gas: 1000000})
"0xb26b8d34691b0da5cb48af68933e81b514199f4ed8bd2b557767c8b55da85f50"
> mvm.get.call("foo")
"bar"
> mvm.get.call("foo", 1)
"thing"
> mvm.num_of.call("foo")
2
Is there a flaw in my approach? Or a better solution?
contract MVM {
struct Record {
bool exists;
string info;
}
mapping(string => Record[]) data;
// If you want to iterate the whole thing, you can use this:
string[] keysNames;
function set(string key, string value) {
// Remove this if, if you don't need iteration
if (data[key].length == 0) {
keysNames.push(key);
}
data[key].push(Record(true, value));
}
function num_of(string key) constant returns (uint) {
return data[key].length;
}
function get(string key, uint index) constant returns (string) {
if (data[key][index].exists == false) {
throw;
}
return data[key][index].info;
}
function exampleIterate() constant returns (string last) {
uint keysLen = keysNames.length;
for(uint i = 0; i < keysLen; i++) {
uint recordsLen = data[keysNames[i]].length;
for(uint j = 0; j < recordsLen; j++) {
last = data[keysNames[i]][j].info;
}
}
}
}

Console project fails with console.writeline but not console.readline

I have a small sample program which breaks when it reaches line 50 with "Error CS1513: } expected". It's typical, except that I counted the number of curly brackets over and over and found no error. I was told on another forum that the problem is probably my placement of the using keyword and class declarations, but I couldn't find anything wrong.
I would like to know if I'm making a mistake. This is the entire program; written with SharpDevelop if it makes any difference.
using System;
namespace Problem
{
public class ClassA
{
public static void Main(string[] args)
{
ClassB MyObject = new ClassB();
MyObject.MethodA();
}
}
public class ClassB
{
public String str_a = "";
public String str_b = "";
public String str_c = "";
public bool bool_a = false;
public int[] int_a = new int[6];
public void MethodA()
{
while (str_a == "" || str_a == null)
{
String str_a2 = Console.ReadLine();
if (str_a2 == "" || str_a2 == null)
{
}
else
{
str_a = str_a2;
}
}
while (str_c == "")
{
String str_c2 = Console.ReadLine();
if (str_c2 == "" || str_c2 == null)
{
}
else
{
str_c = str_c2;
}
}
while (bool_a == false)
{
Console.WriteLine(""); //Fails to compile, asks for ending brackets here
for (int i = 0; i < 6; i += 1)
{
int_a[i] = 0;
}
bool_a = true;
}
}
}
}
I'm pretty sure you could be a victim of UNICODE quotes.
ʺ ̋“”″"
Try just removing the double-quote characters and typing them in your code editor.
Doh! Classic error! I had a declaration in a while loop:
while {
public int[] int_b = new int[6];
}
Sorry about that, SO. I was having one of those days...

Blackberry - How if addElement() doesn't work?

I am a newbie of Blackberry developing application. I try to store all xml parsing data to an object, and set them to a vector.
public class XmlParser extends MainScreen {
Database d;
private HttpConnection hcon = null;
private Vector binN;
public Vector getBinN() {
return binN;
}
public void setBinN(Vector bin) {
this.binN = bin;
}
LabelField from;
LabelField ttl;
LabelField desc;
LabelField date;
public XmlParser() {
LabelField title = new LabelField("Headline News" ,LabelField.HCENTER|LabelField.USE_ALL_WIDTH);
setTitle(title);
try {
URI myURI = URI.create("file:///SDCard/Database/WebFeed.db");
d = DatabaseFactory.open(myURI);
Statement st = d.createStatement("SELECT feed_url, feed_name FROM WebFeed");
st.prepare();
Cursor c = st.getCursor();
while (c.next()) {
Row r = c.getRow();
hcon = (HttpConnection)Connector.open(r.getString(0));
hcon.setRequestMethod(HttpConnection.GET);
hcon.setRequestProperty("User-Agent", "Profile/MIDP-1.0 Configuration/CLDC-1.0");
hcon.setRequestProperty("Content-Length", "0");
hcon.setRequestProperty("Connection", "close");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
builder.isValidating();
Document document = builder.parse(hcon.openInputStream());
Element rootElement = document.getDocumentElement();
rootElement.normalize();
NodeList list = document.getElementsByTagName("item");
int i=0;
while (i<10){
Node item = list.item(i);
if(item.getNodeType() != Node.TEXT_NODE) {
NodeList itemChilds = item.getChildNodes();
int j=0;
while (j<10){
Node detailNode = itemChilds.item(j);
if(detailNode.getNodeType() != Node.TEXT_NODE) {
if(detailNode.getNodeName().equalsIgnoreCase("title")) {
ttl = new LabelField(getNodeValue(detailNode)) {
public void paint(Graphics g) {
g.setColor(Color.BLUE);
super.paint(g);
}
};
from = new LabelField(r.getString(1), LabelField.FIELD_RIGHT|LabelField.USE_ALL_WIDTH);
ttl.setFont(Font.getDefault().derive(Font.BOLD));
from.setFont(Font.getDefault().derive(Font.BOLD));
add (from);
add (ttl);
} else if(detailNode.getNodeName().equalsIgnoreCase("description")) {
desc = new LabelField(getNodeValue(detailNode), 0, 70, USE_ALL_WIDTH);
add(desc);
} else if(detailNode.getNodeName().equalsIgnoreCase("dc:date")) {
date = new LabelField(getNodeValue(detailNode), 11, 5, USE_ALL_WIDTH) {
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
super.paint(g);
}
};
add(date);
add(new SeparatorField());
} else if(detailNode.getNodeName().equalsIgnoreCase("pubDate")) {
date = new LabelField(getNodeValue(detailNode), 0, 22, USE_ALL_WIDTH) {
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
super.paint(g);
}
};
add(date);
add(new SeparatorField());
} else {
System.out.println("not the node");
}
} else {
System.out.println("not text node");
}
j++;
}
}
i++;
BinNews bin = new BinNews();
bin.setProv(from.getText());
bin.setTitle(ttl.getText());
bin.setDesc(desc.getText());
bin.setDate(date.getText());
binN.addElement(bin);
}
setBinN(binN);
}
//setBinN(binN);
st.close();
d.close();
} catch (Exception e) {
add (new LabelField(e.toString(),LabelField.HCENTER|LabelField.USE_ALL_WIDTH));
System.out.println(e.toString());
}
}
public String getNodeValue(Node node) {
NodeList nodeList = node.getChildNodes();
Node childNode = nodeList.item(0);
return childNode.getNodeValue();
}
}
I try to store all data from an object called BinNews, to a vector called binN. But when I do debugging, I found that BinN has null value, because "binN.addElement(bin)" doesn't work.
Please advise.
First, you don't actually call setBinN until after the while(i < 10) loop completes. So when you say binN.addElement(bin) then binN will be null.
However your setBinN(binN) call doesn't make sense because you're passing in binN and then setting it to itself which isn't going to do anything.
What you can do is have binN = new Vector(); at the top of the constructor and then it won't be null later on. I don't think the setBinN call will be necessary later on if you're adding the BinNews objects straight to binN.

getting list of broken constraints for final best solution in drools-planner

I'm using drools-planner-5.4.0.CR1 and I wanna get list of broken constraints for final best solution
and also looked of examples of 5.4.0.CR1
I've implemented like in example but it returns empty list, in other words getScoreDetailList().size() is equal to 0, but solution.getScore() is equal to -54.
is there any suggestions?
public class SomeClass {
...
private volatile Solver solver;
private ScoreDirector scoreDirector;
...
public void someMethod() {
SolverFactory solverFactory = new XmlSolverFactory(SOLVER_CONFIG);
solver = solverFactory.buildSolver();
scoreDirector = solver.getScoreDirectorFactory().buildScoreDirector();
...
this.scoreDirector.setWorkingSolution(solution);
this.solver.setPlanningProblem(this.scoreDirector.getWorkingSolution());
this.solver.solve();
SomeSolution solution = (SomeSolution) solver.getBestSolution();
this.scoreDirector.setWorkingSolution(solution);
System.out.println( "Score: " + solution.getScore());
System.out.println( "getScoreDetailList size:" + getScoreDetailList().size());
}
public List<ScoreDetail> getScoreDetailList() {
if (!(scoreDirector instanceof DroolsScoreDirector)) {
return null;
}
Map<String, ScoreDetail> scoreDetailMap = new HashMap<String, ScoreDetail>();
WorkingMemory workingMemory = ((DroolsScoreDirector) scoreDirector).getWorkingMemory();
if (workingMemory == null) {
return Collections.emptyList();
}
Iterator<ConstraintOccurrence> it = (Iterator<ConstraintOccurrence>) workingMemory.iterateObjects(
new ClassObjectFilter(ConstraintOccurrence.class));
while (it.hasNext()) {
ConstraintOccurrence constraintOccurrence = it.next();
ScoreDetail scoreDetail = scoreDetailMap.get(constraintOccurrence.getRuleId());
if (scoreDetail == null) {
scoreDetail = new ScoreDetail(constraintOccurrence.getRuleId(), constraintOccurrence.getConstraintType());
scoreDetailMap.put(constraintOccurrence.getRuleId(), scoreDetail);
}
scoreDetail.addConstraintOccurrence(constraintOccurrence);
}
List<ScoreDetail> scoreDetailList = new ArrayList<ScoreDetail>(scoreDetailMap.values());
Collections.sort(scoreDetailList);
return scoreDetailList;
}
}
After
this.scoreDirector.setWorkingSolution(solution);
you forgot to call
this.scoreDirector.calculateScore();
I 'll docs about using Solver.getScoreDirectorFactory() in 5.4.0.Final.

Resources