F# Equivalent of Enum.TryParse - enums

In C#, the following code is valid:
MyEnum myEnum = MyEnum.DEFAULT;
if (Enum.TryParse<MyEnum>(string, out myEnum))
{
Console.WriteLine("Success!");
}
So I thought I would use this in F#. Here is my attempt:
let mutable myEnum = MyEnum.DEFAULT
if Enum.TryParse<MyEnum>(string, &myEnum) then
printfn "Success!"
But it complains
a generic construct requires that the type 'MyEnum' have a default constructor
What in the world does that mean?

This is a rather unhelpful (if technically correct) message that the compiler gives you if you try to parse a discriminated union value using Enum.TryParse.
More precisely, if you look at that function, you'll see that it's parameterized with a type that's constrained to be a value type with a default constructor. DU's meet neither of this criteria - this is what the compiler complains about.
When defining an enum in F#, unlike C#, you need to explicitly give each label a value:
type MyEnum =
| Default = 0
| Custom = 1
| Fancy = 2
Skipping the values would make the compiler interpret the type as a discriminated union, which is a very different beast.

Related

strongly typed enum - `class` keyword optional?

In 'modern' C++ that suppports strongly typed enums: is the class keyword optional?
I saw code that defines enums like:
enum SomeEnum: unsigned int {
VAL1 = 0,
VAL2 = 1,
// ...
};
Is this a different thing, a sloppyness of the compiler (VS 2015 (MSVC 19)) or is the class keyword implicit if the enum is strongly typed?
The code in the question declares a normal unscoped enumeration, whose underlying type is however fixed. So it is different from enum class because it still does not introduce a scope for its enumerators.
Since c++11 even normal enums (which still exist) can accept an underlying type specification. See here.
enum-key attr(optional) identifier(optional) enum-base(optional)(C++11) { enumerator-list(optional) }
Emphasis mine
So it is a normal enum not a enum class but with a enum-base specification.
What you call "strongly typed enum" is really named scoped enumerations, and for those the class or struct keyword is mandatory.
Using the "inheritance" syntax is not part of scoped enumerations, they can be used for normal unscoped enumerations as well.

Intellisense with Union Types

I find that intellisense is missing when assigning to a var with a type that is a union type. This makes sense - the compiler doesn't know which of the unioned types you are assigning (although at some point it could deduce when it has enough information but it does not do this either...).
Fine - so I can be explicit and cast the assignment to the type I intend, and the intellisense returns. But this leads to a second problem - for some reason it seems that TypeScript will allow the cast of an empty object literal to any interface, but as soon as a single property is added, the object literal must satisfy the entire interface.
If have two direct questions about this behavior, and they are in the comments in the following code example. I realize I could declare the test vars of more specific types - that is not the point of this topic. Thanks for your help.
interface ITestOne {
a: string;
b?: string;
}
interface ITestTwo {
c: string;
}
type EitherType = ITestOne | ITestTwo;
var test1: EitherType = {}; // ERROR, no intellisense to help fill out the required properties in the object literal
var test2: EitherType = {} as ITestOne; // ALLOWED - Why is this allowed?
var test3: EitherType = { b: 'blah' } as ITestOne; // ERROR: property a is missing. Why ISN'T this allowed if the line above is allowed?
UPDATE 2017-0131
Reply From a bug report I opened on the typescript project on this topic:
What type assertion does, it tells the compiler to "shut up" and trust you. The operator behaves both as an upcast and as a downcast operator. The only check is that the one of the types is assignable to the other.
In the example above, for test: {a: string, b?:string} is assignable to {} (which requires no arguments); for test2 {a: string, b?:string} is assignable to {b:string}, since the type of the only required argument in the target b matches. for test3 neither {a: string, b?:string} is assignable to {b:string, x:string} since it is missing x nor {b:string, x:string} to {a: string, b?:string} since it is missing a.
So, when casting, the source or the target are only verified not to be two completely unrelated types (i.e. number and string), but otherwise the assignment is allowed. My test3 case produced the described result in TypeScript 1.7, but it is now allowed in TypeScript 2.1.
My question about how to get meaningful intellisense in this scenario still stands. However, I suspect the answer is that it is simply not supported without the use of a type guard block.

Method references to raw types harmful?

The code below contains a reference to Enum::name (notice no type parameter).
public static <T extends Enum<T>> ColumnType<T, String> enumColumn(Class<T> klazz) {
return simpleColumn((row, label) -> valueOf(klazz, row.getString(label)), Enum::name);
}
public static <T, R> ColumnType<T, R> simpleColumn(BiFunction<JsonObject, String, T> readFromJson,
Function<T, R> writeToDb) {
// ...
}
Javac reports a warning during compilation:
[WARNING] found raw type: java.lang.Enum missing type arguments for
generic class java.lang.Enum
Changing the expression to Enum<T>::name causes the warning to go away.
However Idea flags the Enum<T>::name version with a warning that:
Explicit type arguments can be inferred
In turn Eclipse (ECJ) doesn't report any problems with either formulation.
Which of the three approaches is correct?
On one hand raw types are rather nasty. If you try to put some other type argument e.g. Enum<Clause>::name will cause the compilation to fails so it's some extra protection.
On the other hand the above reference is equivalent to e -> e.name() lambda, and this formulation doesn't require type arguments.
Enviorment:
Java 8u91
IDEA 15.0.3 Community
ECJ 4.5.2
There is no such thing as a “raw method reference”. Whilst raw types exist to help the migration of pre-Generics code, there can’t be any pre-Generics usage of method references, hence there is no “compatibility mode” and type inference is the norm. The Java Language Specification §15.13. Method Reference Expressions states:
If a method or constructor is generic, the appropriate type arguments may either be inferred or provided explicitly. Similarly, the type arguments of a generic type mentioned by the method reference expression may be provided explicitly or inferred.
Method reference expressions are always poly expressions
So while you may call the type before the :: a “raw type” when it referes to a generic class without specifying type arguments, the compiler will still infer the generic type signature according to the target function type. That’s why producing a warning about “raw type usage” makes no sense here.
Note that, e.g.
BiFunction<List<String>,Integer,String> f1 = List::get;
Function<Enum<Thread.State>,String> f2 = Enum::name;
can be compiled with javac without any warning (the specification names similar examples where the type should get inferred), whereas
Function<Thread.State,String> f3 = Enum::name;
generates a warning. The specification says about this case:
In the second search, if P1, ..., Pn is not empty and P1 is a subtype of ReferenceType, then the method reference expression is treated as if it were a method invocation expression with argument expressions of types P2, ..., Pn. If ReferenceType is a raw type, and there exists a parameterization of this type, G<...>, that is a supertype of P1, the type to search is the result of capture conversion (§5.1.10) applied to G<...>;…
So in the above example, the compiler should infer Enum<Thread.State> as the parametrization of Enum that is a supertype of Thread.State to search for an appropriate method and come to the same result as for the f2 example. It somehow does work, though it generates the nonsensical raw type warning.
Since apparently, javac only generates this warning when it has to search for an appropriate supertype, there is a simple solution for your case. Just use the exact type to search:
public static <T extends Enum<T>> ColumnType<T, String> enumColumn(Class<T> klazz) {
return simpleColumn((row, label) -> valueOf(klazz, row.getString(label)), T::name);
}
This compiles without any warning.

How do the different enum variants work in TypeScript?

TypeScript has a bunch of different ways to define an enum:
enum Alpha { X, Y, Z }
const enum Beta { X, Y, Z }
declare enum Gamma { X, Y, Z }
declare const enum Delta { X, Y, Z }
If I try to use a value from Gamma at runtime, I get an error because Gamma is not defined, but that's not the case for Delta or Alpha? What does const or declare mean on the declarations here?
There's also a preserveConstEnums compiler flag -- how does this interact with these?
There are four different aspects to enums in TypeScript you need to be aware of. First, some definitions:
"lookup object"
If you write this enum:
enum Foo { X, Y }
TypeScript will emit the following object:
var Foo;
(function (Foo) {
Foo[Foo["X"] = 0] = "X";
Foo[Foo["Y"] = 1] = "Y";
})(Foo || (Foo = {}));
I'll refer to this as the lookup object. Its purpose is twofold: to serve as a mapping from strings to numbers, e.g. when writing Foo.X or Foo['X'], and to serve as a mapping from numbers to strings. That reverse mapping is useful for debugging or logging purposes -- you will often have the value 0 or 1 and want to get the corresponding string "X" or "Y".
"declare" or "ambient"
In TypeScript, you can "declare" things that the compiler should know about, but not actually emit code for. This is useful when you have libraries like jQuery that define some object (e.g. $) that you want type information about, but don't need any code created by the compiler. The spec and other documentation refers to declarations made this way as being in an "ambient" context; it is important to note that all declarations in a .d.ts file are "ambient" (either requiring an explicit declare modifier or having it implicitly, depending on the declaration type).
"inlining"
For performance and code size reasons, it's often preferable to have a reference to an enum member replaced by its numeric equivalent when compiled:
enum Foo { X = 4 }
var y = Foo.X; // emits "var y = 4";
The spec calls this substitution, I will call it inlining because it sounds cooler. Sometimes you will not want enum members to be inlined, for example because the enum value might change in a future version of the API.
Enums, how do they work?
Let's break this down by each aspect of an enum. Unfortunately, each of these four sections is going to reference terms from all of the others, so you'll probably need to read this whole thing more than once.
computed vs non-computed (constant)
Enum members can either be computed or not. The spec calls non-computed members constant, but I'll call them non-computed to avoid confusion with const.
A computed enum member is one whose value is not known at compile-time. References to computed members cannot be inlined, of course. Conversely, a non-computed enum member is once whose value is known at compile-time. References to non-computed members are always inlined.
Which enum members are computed and which are non-computed? First, all members of a const enum are constant (i.e. non-computed), as the name implies. For a non-const enum, it depends on whether you're looking at an ambient (declare) enum or a non-ambient enum.
A member of a declare enum (i.e. ambient enum) is constant if and only if it has an initializer. Otherwise, it is computed. Note that in a declare enum, only numeric initializers are allowed. Example:
declare enum Foo {
X, // Computed
Y = 2, // Non-computed
Z, // Computed! Not 3! Careful!
Q = 1 + 1 // Error
}
Finally, members of non-declare non-const enums are always considered to be computed. However, their initializing expressions are reduced down to constants if they're computable at compile-time. This means non-const enum members are never inlined (this behavior changed in TypeScript 1.5, see "Changes in TypeScript" at the bottom)
const vs non-const
const
An enum declaration can have the const modifier. If an enum is const, all references to its members inlined.
const enum Foo { A = 4 }
var x = Foo.A; // emitted as "var x = 4;", always
const enums do not produce a lookup object when compiled. For this reason, it is an error to reference Foo in the above code except as part of a member reference. No Foo object will be present at runtime.
non-const
If an enum declaration does not have the const modifier, references to its members are inlined only if the member is non-computed. A non-const, non-declare enum will produce a lookup object.
declare (ambient) vs non-declare
An important preface is that declare in TypeScript has a very specific meaning: This object exists somewhere else. It's for describing existing objects. Using declare to define objects that don't actually exist can have bad consequences; we'll explore those later.
declare
A declare enum will not emit a lookup object. References to its members are inlined if those members are computed (see above on computed vs non-computed).
It's important to note that other forms of reference to a declare enum are allowed, e.g. this code is not a compile error but will fail at runtime:
// Note: Assume no other file has actually created a Foo var at runtime
declare enum Foo { Bar }
var s = 'Bar';
var b = Foo[s]; // Fails
This error falls under the category of "Don't lie to the compiler". If you don't have an object named Foo at runtime, don't write declare enum Foo!
A declare const enum is not different from a const enum, except in the case of --preserveConstEnums (see below).
non-declare
A non-declare enum produces a lookup object if it is not const. Inlining is described above.
--preserveConstEnums flag
This flag has exactly one effect: non-declare const enums will emit a lookup object. Inlining is not affected. This is useful for debugging.
Common Errors
The most common mistake is to use a declare enum when a regular enum or const enum would be more appropriate. A common form is this:
module MyModule {
// Claiming this enum exists with 'declare', but it doesn't...
export declare enum Lies {
Foo = 0,
Bar = 1
}
var x = Lies.Foo; // Depend on inlining
}
module SomeOtherCode {
// x ends up as 'undefined' at runtime
import x = MyModule.Lies;
// Try to use lookup object, which ought to exist
// runtime error, canot read property 0 of undefined
console.log(x[x.Foo]);
}
Remember the golden rule: Never declare things that don't actually exist. Use const enum if you always want inlining, or enum if you want the lookup object.
Changes in TypeScript
Between TypeScript 1.4 and 1.5, there was a change in the behavior (see https://github.com/Microsoft/TypeScript/issues/2183) to make all members of non-declare non-const enums be treated as computed, even if they're explicitly initialized with a literal. This "unsplit the baby", so to speak, making the inlining behavior more predictable and more cleanly separating the concept of const enum from regular enum. Prior to this change, non-computed members of non-const enums were inlined more aggressively.
There are a few things going on here. Let's go case by case.
enum
enum Cheese { Brie, Cheddar }
First, a plain old enum. When compiled to JavaScript, this will emit a lookup table.
The lookup table looks like this:
var Cheese;
(function (Cheese) {
Cheese[Cheese["Brie"] = 0] = "Brie";
Cheese[Cheese["Cheddar"] = 1] = "Cheddar";
})(Cheese || (Cheese = {}));
Then when you have Cheese.Brie in TypeScript, it emits Cheese.Brie in JavaScript which evaluates to 0. Cheese[0] emits Cheese[0] and actually evaluates to "Brie".
const enum
const enum Bread { Rye, Wheat }
No code is actually emitted for this! Its values are inlined. The following emit the value 0 itself in JavaScript:
Bread.Rye
Bread['Rye']
const enums' inlining might be useful for performance reasons.
But what about Bread[0]? This will error out at runtime and your compiler should catch it. There's no lookup table and the compiler doesn't inline here.
Note that in the above case, the --preserveConstEnums flag will cause Bread to emit a lookup table. Its values will still be inlined though.
declare enum
As with other uses of declare, declare emits no code and expects you to have defined the actual code elsewhere. This emits no lookup table:
declare enum Wine { Red, Wine }
Wine.Red emits Wine.Red in JavaScript, but there won't be any Wine lookup table to reference so it's an error unless you've defined it elsewhere.
declare const enum
This emits no lookup table:
declare const enum Fruit { Apple, Pear }
But it does inline! Fruit.Apple emits 0. But again Fruit[0] will error out at runtime because it's not inlined and there's no lookup table.
I've written this up in this playground. I recommend playing there to understand which TypeScript emits which JavaScript.

Why does using Linq's .Select() return IEnumerable<dynamic> even though the type is clearly defined?

I'm using Dapper to return dynamic objects and sometimes mapping them manually. Everything's working fine, but I was wondering what the laws of casting were and why the following examples hold true.
(for these examples I used 'StringBuilder' as my known type, though it is usually something like 'Product')
Example1: Why does this return an IEnumerable<dynamic> even though 'makeStringBuilder' clearly returns a StringBuilder object?
Example2: Why does this build, but 'Example1' wouldn't if it was IEnumerable<StringBuilder>?
Example3: Same question as Example2?
private void test()
{
List<dynamic> dynamicObjects = {Some list of dynamic objects};
IEnumerable<dynamic> example1 = dynamicObjects.Select(s => makeStringBuilder(s));
IEnumerable<StringBuilder> example2 = dynamicObjects.Select(s => (StringBuilder)makeStringBuilder(s));
IEnumerable<StringBuilder> example3 = dynamicObjects.Select(s => makeStringBuilder(s)).Cast<StringBuilder>();
}
private StringBuilder makeStringBuilder(dynamic s)
{
return new StringBuilder(s);
}
With the above examples, is there a recommended way of handling this? and does casting like this hurt performance? Thanks!
When you use dynamic, even as a parameter, the entire expression is handled via dynamic binding and will result in being "dynamic" at compile time (since it's based on its run-time type). This is covered in 7.2.2 of the C# spec:
However, if an expression is a dynamic expression (i.e. has the type dynamic) this indicates that any binding that it participates in should be based on its run-time type (i.e. the actual type of the object it denotes at run-time) rather than the type it has at compile-time. The binding of such an operation is therefore deferred until the time where the operation is to be executed during the running of the program. This is referred to as dynamic binding.
In your case, using the cast will safely convert this to an IEnumerable<StringBuilder>, and should have very little impact on performance. The example2 version is very slightly more efficient than the example3 version, but both have very little overhead when used in this way.
While I can't speak very well to the "why", I think you should be able to write example1 as:
IEnumerable<StringBuilder> example1 = dynamicObjects.Select<dynamic, StringBuilder>(s => makeStringBuilder(s));
You need to tell the compiler what type the projection should take, though I'm sure someone else can clarify why it can't infer the correct type. But I believe by specifying the projection type, you can avoid having to actually cast, which should yield some performance benefit.

Resources