Mimicking typedef in ActionScript? - actionscript

I'm working on some ActionScript code that needs to juggle a bunch of similar-but-not-interchangeable types (eg, position-in-pixels, internal-position, row-and-column-position) and I'm trying to come up with a naming scheme to minimize the complexity.
Additionally, I don't yet know what the best format for the "internal position" is – using int, uint and Number all have advantages and disadvantages.
Normally I'd solve this with a typedef:
typedef float pixelPos;
typedef int internalPos;
typedef int rowColPos;
Is there any way of getting similar functionality in ActionScript?

If you're using Flex or another command-line compiler to build your project, you could add a pass from an external preprocessor to your build process.
Doesn't get the type-safety, but otherwise appears to do what you want.

I have found an article titled Typedefs in ActionScript 3, which suggests using:
const pixelPos:Class = int;
But that doesn't work – the compiler complains that "Type was not found or was not a compile-time constant: pixelPos" (note: this also happens when I use Object instead of int).
Here is an example of code which doesn't compile:
const pixelPos:Class = int;
function add3(p:pixelPos):void { // <-- type not found on this line
return p + 3;
}

Just make it static const and you can register your own class. Like this:
static const MyClass:Class = int;
And you can't make a variable with this type:
var ert:MyClass; //error
private function ert2():MyClass {}; //error
But you can make an instance:
var ert:* = new MyClass();

Related

Does the using declaration allow for incomplete types in all cases?

I'm a bit confused about the implications of the using declaration. The keyword implies that a new type is merely declared. This would allow for incomplete types. However, in some cases it is also a definition, no? Compare the following code:
#include <variant>
#include <iostream>
struct box;
using val = std::variant<std::monostate, box, int, char>;
struct box
{
int a;
long b;
double c;
box(std::initializer_list<val>) {
}
};
int main()
{
std::cout << sizeof(val) << std::endl;
}
In this case I'm defining val to be some instantiation of variant. Is this undefined behaviour? If the using-declaration is in fact a declaration and not a definition, incomplete types such as box would be allowed to instantiate the variant type. However, if it is also a definition, it would be UB no?
For the record, both gcc and clang both create "32" as output.
Since you've not included language-lawyer, I'm attempting a non-lawyer answer.
Why should that be UB?
With a using delcaration, you're just providing a synonym for std::variant<whatever>. That doesn't require an instantiation of the object, nor of the class std::variant, pretty much like a function declaration with a parameter of that class doesn't require it:
void f(val); // just fine
The problem would occur as soon as you give to that function a definition (if val is still incomplete because box is still incomplete):
void f(val) {}
But it's enough just to change val to val& for allowing a definition,
void f(val&) {}
because the compiler doesn't need to know anything else of val than its name.
Furthermore, and here I'm really inventing, "incomplete type" means that some definition is lacking at the point it's needed, so I expect you should discover such an issue at compile/link time, and not by being hit by UB. As in, how can the compiler and linker even finish their job succesfully if a definition to do something wasn't found?

How to declare const char* in .cpp file

There are many questions about declaring const string in .h files, this is not my case.
I need string (for serialization purposes if it is important) to use in
My current solution is
// file.cpp
static constexpr const char* const str = "some string key";
void MyClass::serialize()
{
// using str
}
void MyClass::deserialize()
{
// using str
}
Does it have any problems? (i.e. memory leaks, redefinitions, UB, side effects)?
P.S. is using #define KEY "key" could be better here (speed/memory/consistency)?
Since you mentioned C++17, the best way to do this is with:
constexpr std::string_view str = "some string key";
str will be substituted by the compiler to the places where it is used at compile time.
Memory-wise you got rid of storing the str in run-time since it is only available at compile time.
Speed-wise this is also marginally better because less indirections to get the data in runtime.
Consistency-wise it is also even better since constexpr is solely used for expressions that are immutable and available at compile time. Also string_view is solely used for immutable strings so you are using the exact data type needed for you.
constexpr implies the latter const, which in turn implies the static (for a namespace-scope variable). Aside from that redundancy, this is fine.

Const constructor vs. static final canonical values

As per this excellent explanation const expressions in Dart are "deeply immutable" meaning that nothing inside can ever change and therefore the entire expression will always denote the same thing. This is useful for the compiler, because it can generate the entire object graph once and re-use it every time such an expression occurs, and it is useful for the programmer to know that such an expression –even when it is deeply nested– still follows value-semantics and won't do anything behind my back.
I am using those optimizations by the compiler to use a well-structured object model (instead of hand-encoding it in a bit-vector, for example) and still get good performance. Since we can get some of those benefits also by "explicitly hashing" some values by making them run-time constants with the static final idiom, the question arises which of the two is good style to use in which case?
Consider the following example:
enum ShaftType { RING, SUN, CARRIER }
class Shaft {
final int index;
final ShaftType type;
Shaft(this.type, this.index) {
assert((type == ShaftType.CARRIER) == (index == null));
}
const Shaft.CARRIER()
: type = ShaftType.CARRIER,
index = null;
const Shaft.RING(this.index) : type = ShaftType.RING;
const Shaft.SUN(this.index) : type = ShaftType.SUN;
}
class GearPath {
final Shaft input, output, fixed;
GearPath({this.input, this.output, this.fixed}) {
// input and output must be set
assert(null != input && null != output);
// fixed shaft can't be anything else
assert(fixed != input && fixed != output);
}
GearPath.carrierToFirstRingFixedSun(int i)
: input = const Shaft.CARRIER(),
output = const Shaft.RING(0),
fixed = new Shaft.SUN(i) {}
static final singleFixedSunUp = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.RING(0),
fixed: const Shaft.SUN(0),
);
static final directDrive = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.CARRIER(),
fixed: null,
);
// ...
}
I can't make the main Shaft(..) and GearStage(..) constructors const because I want to check some constraints, but I can provide special-case constructors (such as Shaft.SUN(int i), Shaft.CARRIER()) which comply with those constraints (at least partially) by design and provide users legible shorthands for those common values.
On the other hand, when a const constructor would have no arguments, then I can as well write it as a static final member as I have done with GearStage.directDrive. If all users refer to this static member instead of re-creating the value again, we also get the benefit of sharing memory and fast comparisons (reference to same object). I can't declare the right-side of this definition as const, because it uses the non-const constructor, but developers can see from context that this is indeed a constant value and not global mutable singleton hidden in the static field. So for practical purposes it should be just as good as a const constructor, right?
Since I haven't found this described any where as a best practice my question is simply if this is indeed a good way to combine and trade-off between const constructors and static final "named value instances"?
Finally, I wonder if there is a way to declare GearPath.carrierToFirstRingFixedSun(int i) also as a const constructor? Currently I can't because const Shaft.SUN(i) complains about i not being constant.
(full code of example)
Dart 2 will allow you to have asserts in const constructors (as long as your condition can be computed as a const expression).
Then you will be able to write:
GearPath({this.input, this.output, this.fixed})
: // input and output must be set
assert(null != input && null != output),
// fixed shaft can't be anything else
assert(!identical(fixed, input) && !identical(fixed, output));
Until then, you can't have both validation and const expressions.
You still will not be able to make GearPath.carrierToFirstRingFixedSun(int i) const because it i is not constant. The const Shaft.SUN(i) is still not a valid const expression, even if i is the parameter of a const constructor. Each const Constructor(...) invocation must still create exactly one object, even if it occurs in the initializer list of another const constructor.
As a rule-of-thumb, you should consider whether exposing a value as const instead of final is something you want to commit to. When you make the variable const, it means that someone else can use the value in another const expression, and then changing the variable to final will be a breaking change. Saying that something is const is a commitment that you should choose deliberately, not just because you can. So, consider the use-cases of your variable. If you don't see it being used in other const expressions, then just make it final.

Why does the F# compiler give an error for one case but not the other?

I'm working on a platform invoke call from F#, and I am getting a compiler error I really can't make that much sense out of. First, let me show the C signature of what I am doing:
int Foo(
ULONG_PTR *phHandle,
DWORD flags
);
In F#, I think the correct way to invoke this natively is as so:
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
[<Out>]nativeint& phHandle,
uint32 flags
)
If I try to call this in a class, I get a compilation error when calling it like so:
type Class1() =
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
member this.Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
The error is:
A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
Weirdly, when I do this all in a module, the compilation errors go away:
module Module1 =
[<DllImport("somedll.dll")>]
extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
let Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
Why does this compile as a module, but not as a class?
I don't think it's valid to define an extern method within a class in F#.
If you pull up the F# 3.0 language specification and search for DllImport, near the bottom is a table listing some special attributes and how they can be used. The text for [<DllImport>] says:
When applied to a function definition in a module, causes the F# compiler to ignore the implementation of the definition, and instead compile it as a CLI P/Invoke stub declaration.
That seems to indicate that it's only valid to declare extern methods (that use [<DllImport>]) on functions defined in a module; it doesn't say anything about class members though.
I think you're running into a compiler bug. Please submit this code to fsbugs#microsoft.com so they can fix the error message emitted by the compiler -- it should really be giving you an error about defining an extern method in a class since that's not allowed by the language spec.
Whether this is a bug not withstanding, maybe this is what's going on: If APlatformInvokeCall were considered a static member function, that member have a single argument of tuple type. Tuples are compiled into objects of generic type (see here, at the bottom, or 5.1.3 in the spec). In this case that tuple is
System.Tuple<nativeint&, uint32>
But ECMA 335 II.9.4 says you can't instantiate generic types at byref types. This explains the error reported.
This explanation fits the fact mentioned above that Class1 works (well, compiles) if you modify the extern declaration and call to take instead a single argument. It also fits the fact that the module version works, since in that version there is no considering APlatFormInvokeCall a member function.
The simple solution is to check the spec, here is the class definition grammar:
type type-name pat_opt as-defn)opt =
class
class-inherits-decl_opt
class-function-or-value-defns_opt
type-defn-elements
end
then we have
class-function-or-value-defn :
attributes_opt staticopt let rec_opt function-or-value-defns
attributes_opt staticopt do expr
which doesn't allow extern.
and
type-defn-element :
member-defn
interface-impl
interface-signature
which isn't what you want either.
As a result, we can see that using extern as you are trying to use it can't be done inside a class.

Why does Dart have compile time constants?

Dart has the concept of compile-time constants. A compile-time constant is parsed and created at compile time, and canonicalized.
For example, here is a const constructor for Point:
class Point {
final num x, y;
const Point(this.x, this.y);
}
And here's how you use it:
main() {
var p1 = const Point(0, 0);
var p2 = const Point(0, 0);
print(p1 == p2); // true
print(p1 === p2); // true
}
This is a non-obvious feature, with seemingly no parallels to features in other dynamic languages. There are restrictions on const objects, like all fields must be final and it must have a const constructor.
Why does Dart have compile-time constants?
From the mailing list, Florian Loitsch writes:
The canonicalization property of compile-time constants is nice, but
not the main-reason to have them. The real benefit of compile-time
constants is, that they don't allow arbitrary execution at
construction and can therefore be used at places where we don't want
code to executed. Static variables initializers, for example, were
initially restricted to compile-time constants to avoid execution at
the top-level. In short, they make sure that a program starts with
'main' and not somewhere else.
Lasse's answer here helped me a lot
So, what are compile-time constants good for anyway?
They are useful for enums.
You can use compile-time constant values in switch cases.
They are used as annotations.
Compile-time constants used to be more important before Dart switched
to lazily initializing variables. Before that, you could only declare
an initialized global variable like "var x = foo;" if "foo" was a
compile-time constant. Without that requrirement, most programs can be
written without using any const objects

Resources