我已经在Haxe中找到了有关摘要的信息,我正在尝试创建一个示例项目来学习如何使用它们。
到目前为止,我已经阅读了https://haxe.org/manual/types-abstract.html, https://haxe.org/blog/abstracting-primitives/,http://old.haxe.org/manual/abstracts和https://code.haxe.org/category/other/passing-different-types-to-a-function-parameter.html。如果有人有其他材料可以指导我,我将不胜感激。
我基本上是在尝试创建一个函数,该函数将接受类型为String
,Int
,Float
或Bool
的变量,并对其进行跟踪。但是,当我尝试使用haxe -main Main -cpp Export
进行编译时,我有点卡住了:abstracts/Comparison.hx:99: characters 42-43 : Type not found : A
。我正试图找出原因,并加以解决。
我觉得我要附加太多代码,但这是我到目前为止编写的内容:
Main.hx
import abstracts.*;
class Main
{
public static function main()
{
var toPrint:Array<String> = ["String1", "String2", "String3"];
printArray(toPrint);
}
public static function printArray(toPrint:PrintableArray)
{
for (element in toPrint)
{
trace(element);
}
}
}
abstracs / Comparison.hx
package abstracts;
enum Either<A, B>
{
Left(v:A);
Right(v:B);
}
abstract Of2<A, B>(Either<A, B>) from Either<A, B> to Either<A, B>
{
@from inline static function fromA<A, B>(a:A):Of2<A, B>
{
return Left(a);
}
@from inline static function fromB<A, B>(b:B):Of2<A, B>
{
return Right(b);
}
@to inline static function toA():Null<A>
{
return switch (this)
{
case Left(a): a;
default: null;
}
}
@to inline static function toB():Null<B>
{
return switch (this)
{
case Right(b): b;
default: null;
}
}
}
abstract Of3<A, B, C>(Either<Either<A, B>, C>) from Either<Either<A, B>, C> to Either<Either<A, B>, C>
{
@from inline static function fromA<A, B, C>(a:A):Of3<A, B, C>
{
return Left(Left(a));
}
@from inline static function fromB<A, B, C>(b:B):Of3<A, B, C>
{
return Left(Right(b));
}
@from inline static function fromC<A, B, C>(c:C):Of3<A, B, C>
{
return Right(c);
}
@to inline static function toA():Null<A>
{
return switch (this)
{
case Left(Left(a)): a;
default: null;
}
}
@to inline static function toB():Null<B>
{
return switch (this)
{
case Left(Right(b)): b;
default: null;
}
}
@to inline static function toC():Null<C>
{
return switch (this)
{
case Right(c): c;
default: null;
}
}
}
abstract Of4<A, B, C, D>(Either<Either<A, B>, Either<C, D>>) from Either<Either<A, B>, Either<C, D>> to Either<Either<A, B>, Either<C, D>>
{
@from inline static function fromA<A, B, C, D>(a:A):Of4<A, B, C, D>
{
return Left(Left(a));
}
@from inline static function fromB<A, B, C, D>(b:B):Of4<A, B, C, D>
{
return Left(Right(b));
}
@from inline static function fromC<A, B, C, D>(c:C):Of4<A, B, C, D>
{
return Right(Left(c));
}
@from inline static function fromD<A, B, C, D>(d:D):Of4<A, B, C, D>
{
return Right(Right(d));
}
@to inline static function toA():Null<A>
{
return switch (this)
{
case Left(Left(a)): a;
default: null;
}
}
@to inline static function toB():Null<B>
{
return switch (this)
{
case Left(Right(b)): b;
default: null;
}
}
@to inline static function toC():Null<C>
{
return switch (this)
{
case Right(Left(c)): c;
default: null;
}
}
@to inline static function toD():Null<D>
{
return switch (this)
{
case Right(Right(d)): d;
default: null;
}
}
}
摘要/Printable.hx
package abstracts;
abstract Printable(Comparison.Of4<String, Int, Float, Bool>) {}
摘要/PrintableArray.hx
package abstracts;
abstract PrintableArray(Array<Printable.Printable>) {}
非常感谢!
答案 0 :(得分:0)
Type not found : A
错误是由于尝试在静态函数中访问类型为 instance 的类型参数引起的。静态函数只能访问在函数本身上声明的类型参数。 @:to
方法不一定是static
,因此您只需删除关键字即可。
但是还有更多问题:
@from
和@to
而不是@:from
和@:to
,这意味着您的转换方法没有任何作用。@:from
,编译器也不知道如何处理fromA
/ fromB
/ fromC
/ fromD
,因为它们看起来都一样他也一样类型参数是在静态方法上声明的,因此没有具体的String
/ Int
/ etc类型可以作为选择的基础。您可能需要具体的fromString
/ fromInt
/等功能。抽象的隐式强制转换是不可传递的(see example at the bottom here)。这意味着您的Printable
摘要根本不允许任何隐式转换。相反,它可能是一个简单的typedef
:
typedef Printable = Comparison.Of4<String, Int, Bool, Float>;
类似地,您不能在iterator()
method为forwarded的情况下,例如PrintableArray
遍历@:forward(iterator)
。但这可能会导致出现诸如here之类的差异问题。您还缺少隐式转换from Array<Printable>
-简而言之,typedef
会更简单。
即使解决了以上所有问题,您的trace()
也不会具有所需的输出。隐式@:to
强制转换是编译时功能,因此此处不应用强制转换,并且trace()
接受Dynamic
。您最终将得到如下结果:
source/Main.hx:15: Left(Left(String1))
您必须在摘要中添加一个toString()
方法,以避免打印包装器枚举:
function toString():String {
return Std.string(switch this {
case Left(Left(v)): v;
case Left(Right(v)): v;
case Right(Left(v)): v;
case Right(Right(v)): v;
});
}
答案 1 :(得分:0)
我基本上是在尝试使函数接受类型为
String
,Int
,Float
或Bool
的变量。
如果这是问题的核心,则您可能还会查看我的overload库。它是一个宏,允许在Haxe中重载函数。它在编译时根据输入的类型决定要调用的函数。与haxe.ds.Either
(又名Left
/ Right
)相比,它具有一些优势,即它是一种编译时功能,没有运行时开销。还有一些缺点:函数在运行时不容易被调用,或者使用动态输入,必须在编译时知道类型。
答案 2 :(得分:0)
我发现有些东西可以解决一些运行时开销:
WorkItems
似乎工作得很好,但是您必须调用val model = new RandomForestRegressor()
.setFeaturesCol("features")
.setLabelCol("label")
.setImpurity("gini")
.setMaxBins(20)
.setMaxDepth(20)
.setNumTrees(50)
才能获得文字值。它还可以为您提供值类型的索引,并且具有静态扩展名,可读性很强:
Exception in thread "main" java.lang.IllegalArgumentException:
rfr_dc9303ee1fc9 parameter impurity given invalid value gini.
[error] at org.apache.spark.ml.param.Param.validate(params.scala:78)
[error] at org.apache.spark.ml.param.ParamPair.<init>(params.scala:656)
[error] at org.apache.spark.ml.param.Param.$minus$greater(params.scala:87)
[error] at org.apache.spark.ml.param.Params.set(params.scala:737)
[error] at org.apache.spark.ml.param.Params.set$(params.scala:736)
[error] at org.apache.spark.ml.PipelineStage.set(Pipeline.scala:42)
Here's a script,它将制作更大的Multimorph软件包。