Is it possible to have different signature? - haxe

I have the following code :
class Test {
static function main() {
trace("Haxe is great!");
var api:Api = new Api();
api.doAdd(1,1);
}
}
class Api {
public function new(){}
public function doAdd( x : Int, y : Int ) {
trace( x + y );
}
public function doAdd( x : Int, y : Int , z : Int) {
trace( x + y + z);
}
}
Here is a link to a try Haxe code
If I try to compile this code, I get an error : ```Duplicate class field declaration : doAdd````
My question is, is there anyway to have two methods with differents signatures in haxe ?

On the Java and C# targets, the following works:
#:overload
public function doAdd(x:Int, y:Int) {
trace(x + y);
}
#:overload
public function doAdd(x:Int, y:Int, z:Int) {
trace(x + y + z);
}
On other targets, the syntax for #:overload is a bit different and only works for externs as far as I understand it. There's an example in this thread.

Related

Flutter compute function not called if parameter is not a primitive?

I tried to send a Map to a compute, but computer is never called. The strange point is if I replace Map with int, it works:
void A()
{
var map=Map();
map["p1"]=90;
D("before compute");
var r1 = await compute(p1, 10);
D("after compute(p1) : $r1");
var r2 = await compute(p2, map);
// code never reaches here!
D("after compute(p2) : $r2");
}
static int p2(Map p)
{
return p["p1"]*10;
}
static int p1(int z)
{
return z*10;
}
output is :
after compute(p1) : 100
Flutter compute methods use Isolates and its only transfer (null, num, bool, double, String) types.
https://api.flutter.dev/flutter/dart-isolate/SendPort/send.html
Just define exact type of Map that "p2" receives as parameter:
static int p2(Map<String,int> p)
{
return p["p1"]*10;
}
Try passing a const parameter:
var r2 = await compute(p2, {"p1":90});

Why does this simple annotation example is not rejected in Static Code Analysis?

I'm using SAL to make sure that all code paths that create an object X should call X::work() before destroying it.
#include <sal.h>
class X {
bool worked = false;
public:
_Post_satisfies_(!worked)
X() : worked(false) {}
_Post_satisfies_(worked)
void work() {
worked = true;
}
_Pre_satisfies_(worked)
~X() {
}
};
int main() {
X x;
X y; // Does not call work() but still passes the test anyway
x.work();
}
When I remove x.work(), then there goes an error as intended:
warning C28020: The expression 'this->worked' is not true at this call.
But soon as I add work() for one object x, the other one y also seems to pass the test. Is there some problem in my annotation?

How to multiply strings in Haxe

I'm trying to multiply some string a by some integer b such that a * b = a + a + a... (b times). I've tried doing it the same way I would in python:
class Test {
static function main() {
var a = "Text";
var b = 4;
trace(a * b); //Assumed Output: TextTextTextText
}
}
But this raises:
Build failure Test.hx:6: characters 14-15 : String should be Int
There doesn't seem to be any information in the Haxe Programming Cookbook or the API Documentation about multiplying strings, so I'm wondering if I've mistyped something or if I should use:
class Test {
static function main() {
var a = "Text";
var b = 4;
var c = "";
for (i in 0...b) {
c = c + a;
}
trace(c); // Outputs "TextTextTextText"
}
}
Not very short, but array comprehension might help in some situations :
class Test {
static function main() {
var a = "Text";
var b = 4;
trace( [for (i in 0...b) a].join("") );
//Output: TextTextTextText
}
}
See on try.haxe.org.
The numeric multiplication operator * requires numeric types, like integer. You have a string. If you want to multiply a string, you have to do it manually by appending a target string within the loop.
The + operator is not the numeric plus in your example, but a way to combine strings.
You can achieve what you want by operator overloading:
abstract MyAbstract(String) {
public inline function new(s:String) {
this = s;
}
#:op(A * B)
public function repeat(rhs:Int):MyAbstract {
var s:StringBuf = new StringBuf();
for (i in 0...rhs)
s.add(this);
return new MyAbstract(s.toString());
}
}
class Main {
static public function main() {
var a = new MyAbstract("foo");
trace(a * 3); // foofoofoo
}
}
To build on tokiop's answer, you could also define a times function, and then use it as a static extension.
using Test.Extensions;
class Test {
static function main() {
trace ("Text".times(4));
}
}
class Extensions {
public static function times (str:String, n:Int) {
return [for (i in 0...n) str].join("");
}
}
try.haxe.org demo here
To build on bsinky answer, you can also define a times function as static extension, but avoid the array:
using Test.Extensions;
class Test {
static function main() {
trace ("Text".times(4));
}
}
class Extensions {
public static function times (str:String, n:Int) {
var v = new StringBuf();
for (i in 0...n) v.add(str);
return v.toString();
}
}
Demo: https://try.haxe.org/#e5937
StringBuf may be optimized for different targets. For example, on JavaScript target it is compiled as if you were just using strings https://api.haxe.org/StringBuf.html
The fastest method (at least on the JavaScript target from https://try.haxe.org/#195A8) seems to be using StringTools._pad.
public static inline function stringProduct ( s : String, n : Int ) {
if ( n < 0 ) {
throw ( 1 );
}
return StringTools.lpad ( "", s, s.length * n );
}
StringTools.lpad and StringTools.rpad can't seem to decide which is more efficient. It looks like rpad might be better for larger strings and lpad might be better for smaller strings, but they switch around a bit with each rerun. haxe.format.JsonPrinter uses lpad for concatenation, but I'm not sure which to recommend.

accessing an element in a range in D

I am writing my first D program, and trying to understand how to implement an associative array. The issue that keeps coming up is that if i create an array like:
import std.stdio;
import std.string;
import std.array;
void main(string[] args) {
int[string] arr = ["first" : 1, "second" : 2];
}
everything compiles fine. but if i try and move arr outside of main--into a struct, i get an error saying: Error: non-constant expression.
this throws the error:
import std.stdio;
import std.string;
import std.array;
struct foo {
int[string] arr = ["first" : 1, "second" : 2];
}
void main(string[] args)
{ /* do stuff with foo */ }
I'm sure this is a super simple fix, but this is my first attempt at D.
This limitation comes from the fact that symbols in D modules are not ordered but exist "in parallel". Which is generally a good thing because:
compiler can possibly do semantic analysis in parallel
you don't need explicit forward declarations (like in C) to use symbol declared later in the module
With that in mind, consider this code (global scope):
int x;
int foo() { return ++x; }
int y1 = foo();
int y2 = foo();
If using run-time code was allowed for initializers, values of y1 and y2 would depend on order of evaluation which is not defined in general - all globals are "equal".
But for local function variables there is no such problem - they are placed on stack and thus order of evaluation is perfectly defined (it is in lexical order):
void foo()
{
int x;
int foo() { return ++x; }
int y1 = foo(); // will always be 1
int y2 = foo(); // will always be 2
}
Because of that compiler restricts you to only compile-time constants when using initializer syntax for globals or struct fields. Constructors (including module constructors) are still OK though:
int[int] x;
static this()
{
x = [ 1 : 1, 2 : 2 ];
}
AA literal may look like a proper constant but it actually needs to allocate memory from run-time heap. D is smart enough to accept some of such entities (even some classes) and put them in fixed binary memory section but AA may be extended so proper dynamic heap is necessary.
Also please note that struct in D can't have default constructor:
struct foo
{
int[string] arr;
// this won't work:
this() { this.arr = ["first" : 1, "second" : 2]; }
}
// need class instead
class boo
{
int[string] arr;
// fine:
this() { this.arr = ["first" : 1, "second" : 2]; }
}
Something like this will work.
struct Foo{
int[string] arr;
}
void main(){
Foo foo = Foo(["first" : 1, "second" : 2]);
}

haxe "should be int" error

Haxe seems to assume that certain things must be Int. In the following function,
class Main {
static function main() {
function mult_s<T,A>(s:T,x:A):A { return cast s*x; }
var bb = mult_s(1.1,2.2);
}
}
I got (with Haxe 3.01):
Main.hx:xx: characters 48-49 : mult_s.T should be Int
Main.hx:xx: characters 50-51 : mult_s.A should be Int
Can anyone please explain why T and A should be Int instead of Float?
A more puzzling example is this:
class Main {
public static function min<T:(Int,Float)>(t:T, t2:T):T { return t < t2 ? t : t2; }
static function main() {
var a = min(1.1,2.2); //compile error
var b = min(1,2); //ok
}
}
I can't see why t<t2 implies that either t or t2 is Int. But Haxe seems prefer Int: min is fine if called with Int's but fails if called with Float's. Is this reasonable?
Thanks,
min<T:(Int,Float)> means T should be both Int and Float. See the constraints section of Haxe Manual.
Given Int can be converted to Float implicitly, you can safely remove the constraint of Int. i.e. the following will works:
http://try.haxe.org/#420bC
class Test {
public static function min<T:Float>(t:T, t2:T):T { return t < t2 ? t : t2; }
static function main() {
var a = min(1.1,2.2); //ok
$type(a); //Float
trace(a); //1.1
var b = min(1,2); //ok
$type(b); //Int
trace(b); //1
}
}

Resources