Enum values as parameter default values in Haxe - enums

Is there a way to use enum default parameters in Haxe? I get this error:
Parameter default value should be constant
enum AnEnum {
A;
B;
C;
}
class Test {
static function main() {
Test.enumNotWorking();
}
static function enumNotWorking(e:AnEnum = AnEnum.A){}
}
Try Haxe link.

Update: this feature has been added in Haxe 4. The code example from the question now compiles as-is with a regular enum.
Previously, this was only possible if you're willing to use enum abstracts (enums at compile time, but a different type at runtime):
#:enum
abstract AnEnum(Int)
{
var A = 1;
var B = 2;
var C = 3;
}
class Test3
{
static function main()
{
nowItWorks();
}
static function nowItWorks(param = AnEnum.A)
{
trace(param);
}
}
There's nothing special about the values I chose, and you could choose another type (string, or a more complex type) if it better suits your use case. You can treat these just like regular enums (for switch statements, etc.) but note that when you trace it at runtime, you'll get "1", not "A".
More information: http://haxe.org/manual/types-abstract-enum.html

Sadly enums can't be used as default values, because in Haxe enums aren't always constant.
This piece of trivia was on the old website but apparently hasn't made it into the new manual yet:
http://old.haxe.org/ref/enums#using-enums-as-default-value-for-parameters
The workaround is to check for a null value at the start of your function:
static function enumNotWorking(?e:AnEnum){
if (e==null) e=AnEnum.A;
}
Alternatively, an Enum Abstract might work for your case.

Related

How do I declare ENUMs in Chapel?

Building out a flexible function, and I want it to look like
if sensor.type == SENSOR_TYPE.DISTANCE {
doSomthingEmotionallyDistant();
} else if sensor.type = SENSOR_TYPE.ANGLE {
gleanAnAngelsAngle();
}
Do enums have to be declared at the Module level? Can you point me to some examples or (better) provide one here?
Do enums have to be declared at the Module level?
Nope. They can be declared in inner scopes as well.
Can you point me to some examples
The syntax is covered in the spec and the quick reference sheet. There really aren't many great examples in the documentation right now, as far as I can tell. This might benefit from an issue or (better) a small contribution to the primers, for example.
or provide [an example] here?
Below is your example, expanded with a working enum. Note, I've changed .type to .t since .type is reserved for the actual type.
enum SENSOR_TYPE {DISTANCE, ANGLE};
record Sensor {
var t: SENSOR_TYPE;
}
var sensor = new Sensor(t=SENSOR_TYPE.DISTANCE);
if sensor.t == SENSOR_TYPE.DISTANCE {
doSomethingEmotionallyDistant();
} else if sensor.t == SENSOR_TYPE.ANGLE {
gleanAnAngelsAngle();
}
// Defined so this example will compile...
proc doSomethingEmotionallyDistant() { writeln('DISTANCE'); };
proc gleanAnAngelsAngle() { writeln('ANGLE'); };
You can also "use" an enum like you can with a module, to expose it's symbols to your namespace:
enum SENSOR_TYPE {DISTANCE, ANGLE};
use SENSOR_TYPE;
record Sensor {
var t: SENSOR_TYPE;
}
var sensor = new Sensor(t=DISTANCE);
if sensor.t == DISTANCE {
doSomethingEmotionallyDistant();
} else if sensor.t == ANGLE {
gleanAnAngelsAngle();
}
// Defined so this will compile...
proc doSomethingEmotionallyDistant() { writeln('DISTANCE'); };
proc gleanAnAngelsAngle() { writeln('ANGLE'); };

Why do Static Methods & Enumerations have unexpected behavior in Xamarin Forms? Objects Passed to Static Methods become null & enums are stored as int

I have been using C#/.NET/Visual Studio since 2000, but I just started working with Xamarin Forms recently. It's a pretty great platform, however I have run across a couple of issues that I cannot figure out. (I'm using Visual Studio 2017 Community). I have been researching this behavior extensively, but have had absolutely no luck in obtaining a resolution. I have created a small application which easily reproduces both of these behaviors and would greatly appreciate any expertise that would help me fix my code so it works as expected. The two issues are these:
1) After creating a custom object using new in Xamarin Forms, the object is not null. However, if that object is passed via the parameter list into a static method, it becomes null inside the method. (Note: In my sample applications I placed the static method inside the Form1 and MainPage classes. I did this only to simplify the samples. The behavior is the same when I put the static method into a separate utility class, either static class or normal class.)
2) Custom enumerations are treated as integers instead of the actual enumerated type. For example, if an instance of an enumerated type is given a value of the first item in the enumeration, its value is 0, an integer. Whereas in a Windows application, the value would be the actual enumeration value (e.g., EnumValue1), and its type would be the enumerated type. This can be a problem if one is trying to do comparisons with strings. For example, aEnum.ToString() == "EnumValue1" will return true in a Windows application, but will return false in Xamarin Forms, because aEnum.ToString() will evaluate to "0". This behavior also breaks the tenet of encapsulation in object-oriented programming, in that you aren't supposed to have to know the underlying implementation of a data type in order to properly use it.
Below is the code that reproduces the issues. There are 2 separate projects, one Windows Forms, the other Xamarin Forms. (The Xamarin Forms project was created with .NET Standard code sharing strategy). Both projects use 2 utility classes Enumerations and CustObj, where the only differences are the namespace definitions (namespace WinFormApp.Utilities and namespace XamarinFormsApp.Utilities, respectively). They both reside in a Utilities folder under their respective projects.
Windows Forms "Form1.cs"
using System.Windows.Forms;
using WinFormApp.Utilities;
namespace WinFormApp
{
partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// ENUMERATION TEST
ACustomEnumeration aCE = ACustomEnumeration.EnumValue1;
string aceStr = aCE.ToString();
// PASSING OBJECT TO STATIC METHOD
CustObj aCustObj = new CustObj();
int ii = aCustObj.i;
string ss = aCustObj.s;
Form1.Foo(aCustObj);
}
public static void Foo(CustObj custObj)
{
}
}
}
Xamarin Forms "MainPage.xaml.cs"
using Xamarin.Forms;
using XamarinFormsApp.Utilities;
namespace XamarinFormsApp
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
// ENUMERATION TEST
ACustomEnumeration aCE = ACustomEnumeration.EnumValue1;
string aceStr = aCE.ToString();
// PASSING OBJECT TO STATIC METHOD
CustObj aCustObj = new CustObj();
int ii = aCustObj.i;
string ss = aCustObj.s;
MainPage.Foo(aCustObj);
}
public static void Foo(CustObj custObj)
{
}
}
}
Utility class "Enumerations.cs"
namespace WinFormApp.Utilities (or XamarinFormsApp.Utilities)
{
public enum ACustomEnumeration
{
EnumValue1,
EnumValue2
}
class Enumerations
{
}
}
Utility class "CustObj.cs"
namespace WinFormApp.Utilities (or XamarinFormsApp.Utilities)
{
public class CustObj
{
public ACustomEnumeration _aCEMember;
public int i;
public string s;
public CustObj()
{
this.i = 99;
this.s = "Hello!";
}
}
}
When stepping through the WinFormApp in Visual Studio, one observes the following variables before the call to static method Foo:
aCE with value of EnumValue1 and Type ACustomEnumeration
aceStr with Value of "EnumValue1" and Type string
aCustObj with Type CustObj and data members:
_aCEMember with Value of EnumValue1 and Type ACustomEnumeration
i with Value of 99 and Type int
s with Value of "Hello!" and Type string
ii with Value of 99
ss with Value of Hello!
After stepping into Foo, the parameter is as expected:
custObj with Type CustObj and data members:
_aCEMember with Value of EnumValue1 and Type ACustomEnumeration
i with Value of 99 and Type int
s with Value of "Hello!" and Type string
All variables evaluate as expected. Enumerations evaluate as the actual enumerated value. The custom object is instantiated and its data members are given their appropriate initial values. When the object is passed into the static method, it is passed correctly as a reference type, and retains all of its data inside the method.
Conversely, when stepping through the XamarinFormsApp in Visual Studio, one observes the following variables before the call to static method Foo:
aCE with Value of 0 and Type int (violates encapsulation)
aceStr with Value of "0" and Type string (this demonstrates the problem with how enumerations are evaluated)
aCustObj with Type CustObj and data members:
_aCEMember with no Value or Type at all
i with no Value or Type at all
s with no Value or Type at all
ii with Value of 99
ss with Value of Hello!
After stepping into Foo, the parameter is NOT as expected:
custObj with Value of null and Type CustObj
The problems with enumerations are fairly obvious. But I am very confused as to what is really going on with the custom object. It makes no sense that when I examine an object after its instantiation, that it doesn't show its data members as being initialized. Although it is strange how variables ii and ss are actually given the correct values.
More importantly, the fact that when I pass the object into the static method, it becomes null, is really mind-boggling.
Does anyone have any ideas as to what is happenning, and how to fix it?

Is it possible to return multiple types through a function?

I wanted to know if its possible to return a function that could either return a boolean or a void ? I know I could use std::optional however that is available only in C++17 and my code base is C++11. I would like something like this
xxx process(int a)
{
if (a==1)
return true;
if (a==2)
return false;
if (a==3)
.... //return nothing
}
For returning two values I use a std::pair (usually typedef'd).
In C++11 and newer, you should use std::tuple for more than two return results.
The abstract example using the tuple
std::tuple<bool, int> process(int a)
{
if (a==1)
return std::make_tuple(true, 0);
if (a==2)
return std::make_tuple(false, 0);
if (a==3)
return std::make_tuple(false, 1);
}
A variant might be a better match:
According to your requirement: a function that could either return a boolean or a void
See at: http://en.cppreference.com/w/cpp/utility/variant
The class template std::variant represents a type-safe union. An
instance of std::variant at any given time either holds a value of one
of its alternative types, or it holds no value (this state is hard to
achieve, see valueless_by_exception).
If you don't want to write an equivalent of std::optional yourself use an enum.
enum class Result
{
False,
True,
Nothing // or whatever name makes sense in your use case
};

ES6 read-only enums that can map value to name

I would like to define an enum-like structure in JS, but have two requirements:
The values be read-only, i.e. no users can assign to them.
The values (0, 1, 2, ...) can be mapped back into the names (as with Java's name method)
The methods I know to create enums like this typically meet one requirement or the other, not both.
I've tried:
const MyEnum = {
a: 0,
b: 1,
c: 2
};
The enum itself is constant, but the values are still mutable and I can't map values back to names efficiently.
When writing an enum in Typescript, it outputs:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["a"] = 0] = "a";
MyEnum[MyEnum["b"] = 1] = "b";
MyEnum[MyEnum["c"] = 2] = "c";
})(MyEnum || (MyEnum = {}));
This can map both ways, but still doesn't have constant values.
The only option I've found that meets both requirements would be using getters on a class:
class MyEnum {
get a() {
return 0;
}
...
}
This method dramatically restricts the legal names and has a lot of overhead, especially in browsers that don't inline getters well (or can't).
#Shmiddty suggested freezing an object:
const MyEnum = Object.freeze({
a: 0,
b: 1,
c: 2
});
This meets the constant requirement well, but doesn't provide a great way to map values back to names.
I could write a helper that builds the reverse mapping like:
function reverseEnum(enum) {
Object.keys(enum).forEach(k => {
enum[enum[k]] = k;
});
}
But any kind of programmatic solution to generate the reverse mapping will run into problems if the original object is frozen or otherwise actually constant.
Is there a clean, concise solution to this in JS?
This does a pretty good job, IMHO.
function Enum(a){
let i = Object
.keys(a)
.reduce((o,k)=>(o[a[k]]=k,o),{});
return Object.freeze(
Object.keys(a).reduce(
(o,k)=>(o[k]=a[k],o), v=>i[v]
)
);
} // y u so terse?
const FOO = Enum({
a: 0,
b: 1,
c: "banana"
});
console.log(FOO.a, FOO.b, FOO.c); // 0 1 banana
console.log(FOO(0), FOO(1), FOO("banana")); // a b c
try {
FOO.a = "nope";
}
catch (e){
console.log(e);
}
I'd use a Map so that your enum values can be any type, rather than having them coerced into strings.
function Enum(obj){
const keysByValue = new Map();
const EnumLookup = value => keysByValue.get(value);
for (const key of Object.keys(obj)){
EnumLookup[key] = obj[key];
keysByValue.set(EnumLookup[key], key);
}
// Return a function with all your enum properties attached.
// Calling the function with the value will return the key.
return Object.freeze(EnumLookup);
}
If your enum is all strings, I'd also probably change one line to:
EnumLookup[key] = Symbol(obj[key]);
to ensure that the enum values are being used properly. Using just a string, you have no guarantee that some code hasn't simply passed a normal string that happens to be the same as one of your enum values. If your values are always strings or symbols, you could also swap out the Map for a simple object.
Just recently implemented an Es6 version that works quite well:
const k_VALUES = {}
export class ErrorCode {
constructor(p_apiCode, p_httpCode){
this.apiCode = p_apiCode;
this.httpCode = p_httpCode;
k_VALUES[p_apiCode] = this;
}
static create(p_apiCode){
if(k_VALUES[p_apiCode]){
return k_VALUES[p_apiCode];
}
return ErrorCode.UNKNOWN;
}
}
ErrorCode.UNKNOWN = new ErrorCode(0, 500);
ErrorCode.NOT_FOUND = new ErrorCode(-1000, 404);
ErrorCode.NOT_FOUND_EMAIL = new ErrorCode(-1001, 404);
ErrorCode.BAD_REQUEST = new ErrorCode(-1010, 404);
I wanted to implement a similar pattern as what we do with Java enums. This enables me to use a constructor to pass values. The constructor then freezes the ErrorCode object - nice and convenient.
Usage: first import your enum class...
import {ErrorCode} from "../common/services/errors/ErrorCode";
Now, after importing the enum class, access it like so:
if( errCode.includes(ErrorCode.BAD_REQUEST.apiCode) ){...}
PS> This is used in conjunction with a Webpack setup using Babel to convert our ES6 classes down for browser compatibility.

Combo Box Item comparison and compiler warnings

In VisualStudio (Pro 2008), I have just noticed some inconsistent behaviour and wondered if there was any logical reasoning behind it
In a WinForms project, if I use the line
if(myComboBox.Items[i] == myObject)
I get a compiler warning that I might get 'Possible unintended references' as I am comparing type object to type MyObject. Fair enough.
However, if I instead use an interface to compare against:
if(myComboBox.Items[i] == iMyInterface)
the compile warning goes away.
Can anyone think if there is any logical reason why this should happen, or just an artifact of the compiler not to check interfaces for comparison warnings. Any thoughts?
EDIT In my example, the combobox was bound to a List, but that list was generated using list<IMyInterface>.Cast<MyObject>().ToList<MyObject>()
Its as if the compiler is only taking still assuming I am binding to the List of IMyInterface.
(Object and Interface methods have been changed to protect the innocent)
The compile warning for the first sample is because any custom == operator for your class would be ignored and the references compared (maybe not what you intended, hence the warning).
It's not possible to specify that an operator should be overridden on an interface, so this will always be a reference comparison. The warning is not needed because you should always expect this.
Here's an example of overriding the == operator:
class Program
{
static void Main(string[] args)
{
object t1 = new MyTest() { Key = 1 };
MyTest t2 = new MyTest() { Key = 1 };
Console.WriteLine((MyTest)t1 == t2); // Uses overriden == operator, returns true
Console.WriteLine(t1 == t2); // Reference comparison, returns false
}
}
public class MyTest
{
public int Key { get; set; }
public override bool Equals(object obj)
{
return this.Key == (obj as MyTest).Key;
}
public override int GetHashCode()
{
return this.Key.GetHashCode();
}
public static bool operator ==(MyTest t1, MyTest t2)
{
return t1.Equals(t2);
}
public static bool operator !=(MyTest t1, MyTest t2)
{
return !t1.Equals(t2);
}
}
The MyTest class is considered equal if the Key property is equal. If you were to create an interface, you cannot specify that it should include a custom == operator and therefore the comparison would always be a reference comparison (and therefore false in the case of our sample code).
Lagerdalek,
The warning is generated because you need to cast the item from the Items collection back into the orginal type that was bound to the combo box, before comparing; otherwise you may get unexpected results as the compiler warns.
Here is an example:
myComboBox.DataSource = Collection<Car>;
So if the combo box is bound to a collection of car objects you would cast them back before comparison:
if((car)myComboBox.Items[i] == thisCar)
Then you shouldn't get any warnings.
Another method you could do is:
using(myComboBox.Items[i] as car){
if(myComboBox.Items[i] == thisCar)
}
Let me know. Good Luck! I'm going from memory, I hope I didn't mistype anything. :o)

Resources