How can I address an enumeration type defined in a module? - powershell-5.0

In one of our PowerShell modules we have defined an enumeration type:
myModule.psm1
[Flags()]
enum MyEnum {
Value1 = 1
Value2 = 2
Value3 = 4
}
Function Have-Some
(
[Parameter(Mandatory = $true, Position = 0)]
[MyEnum]
$enumValue
) {
}
Now, from a script I'd like to address this type to call the Have-Some function.
None of the below methods seems to work:
Have-Some Value1,Value2
Have-Some "Value1,Value2"
Have-Some [MyEnum]Value1,Value2
Have-Some [MyEnum]"Value1,Value2"
Have-Some [MyEnum]Value1 + [MyEnum]Value2
Have-Some [MyEnum]Value1 -bor [MyEnum]Value2
I always get the same (or similar) error:
Cannot process argument transformation on parameter 'enumValue'. Cannot convert value "[MyEnum]::Value1" to type "MyEnum". Error: "Unable to match the identifier name [MyEnum]::Value1 to a valid
enumerator name. Specify one of the following enumerator names and try again:
Value1, Value2, Value3"
What's the correct way to call the Have-Some function with two or more MyEnum flags?

Related

In Kotlin, what does "::class.simpleName" do?

val var1: Any = "Carmelo Anthony"
I'm under the impression ::class.simpleName returns the variable type of an object
when I do the following:
val var1Type = var1::class.simpleName
print(var1Type)
I get String and not Any
but when I do this
val var2: String = var1
I get a Type mismatch: inferred type is Any but String was expected
In Kotlin, the ::class operator exists in 2 forms:
TypeName::class - which returns a KClass object for the static type TypeName.
variableName::class - which returns a KClass object corresponding to the runtime type of variableName, and not variableName's static type. (Kotlin calls this the "bound type" in their documentation).
In your case, var1 has a runtime tytpe of String but a static type of Any.
So var1::class returns the KClass for String, not Any.
But Kotlin's type system, like most statically typed languages, does not allow for implicit narrowing conversion (i.e. given a variable var2 typed as String, you cannot assign-to var2 from another variable (var3) statically-typed as Any, because var3 could have a runtime type that's completely incompatible with String, e.g. an InputStream object.
...even if it's provable (by following the program by-hand) that the Any-typed value will always be a String.
Fortunately, however, Kotlin's type-checker is modern and its "Smart cast" feature follows the scope of type-narrowing when the is operator is used, which is neat (TypeScript has it too, I don't think any other language does though).
In situations where you can't use Smart-casts or can otherwise prove to yourself that a downcast is safe then use the as operator to perform an unsafe cast. Like so: var2: String = var1 as String.
(Somewhat confusingly, other languages use as as the operator for safe casts, argh).
In context:
fun main() {
val var1: Any = "Carmelo Anthony"
val var1Type = var1::class.simpleName
println("var1's type: " + var1Type) // <-- This will print the *runtime type* of `var1` (String), not its static type (which is `Any`, *not* `String`).
/*
val var2: String = var1 // <-- Fails beause `var1` is `Any`, and `Any` is "wider" than `String`, and narrowing conversions always considered unsafe in languages like Kotlin, Java, etc.
*/
val var2Unsafe: String = var1 as String; // <-- Doing this is unsafe because it will throw if `var1` is not a String.
val var2Safe : String? = var1 as? String; // <-- Doing this is safe because it `var2Safe` will be null if `var1` is not a String.
println(var2Unsafe)
println(var2Safe)
}
If you're familiar with other languages, then here's an incomplete table of equivalent operations and their syntax:
Kotlin
Java
JavaScript
C#
C++
Get static type
TypeName::class
TypeName.class
ConstructorName
typeof(TypeName)
typeid(TypeName)
Get runtime type
variableName::class
variableName.getClass()
typeof variableName (intrinsics) variableName.constructor (objects)
variableName.GetType()
typeid(variableName)
Get type from name (string)
Class.forName( typeName ).kotlin
Class.forName( typeName )
eval( typeName ) (never do this)
Statically-defined runtime type check
variableName is TypeName
variableName instanceof TypeName
typeof variableName === 'typeName' (intrinsics) or variableName instanceof ConstructorName (objects)
variableName is TypeName
Runtime dynamic type check
otherKClass.isInstance( variableName ) or otherKType.isSubtypeOf()
otherClass.isAssignableFrom( variableName.getClass() )
otherType.IsAssignableFrom( variableName.GetType() )
Unsafe narrowing (aka downcast)
val n: NarrowType = widerVar as NarrowType;
NarrowType n = (NarrowType)widerVar;
variableName as TypeName (TypeScript only)
NarrowType n = (NarrowType)widerVar;
Safe narrowing (downcast or null)
val n: NarrowType? = widerVar as? NarrowType;
NarrowType n? = widerVar as NarrowType;
dynamic_cast<NarrowType>( widerVar )
Conditional narrowing in scope
variableName is TypeName
func(x: unknown): x is TypeName guard functions (TypeScript only)
widerVar is TypeName n

Kotlin: "Type inference failed"

Does someone know what goes I'm doing wrong here?
// ...
val alphabet = ('a'..'z').toList()
val str = "testing"
val arr = str.split("")
for (char in arr) {
var i = alphabet.indexOf(char) // Throws Error!
// ...
}
The indexOf-method results in
"Error:(10, 26) Kotlin: Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly."
I have tried to "var i: Int = alphabet.indexOf(char)" and "alphabet.indexOf(char) as Int". The same result ...
What's the issue here?
I believe that your problem is that you think that the variable char contains a Char value. If that were the case, then it would make sense for indexOf to be accepting a Char value and then finding the location of that character in a list of characters (List<Char>) on which the method is being called.
But str.split() is returning a List<String>, not a List<Char>, and so char is a String. So you are asking the indexOf method to tell you the location of a String in a list of characters (List<Char>). That doesn't make sense. That's the basis of the problem. Exactly how that translates to the error you're getting from the Kotlin compiler, I'm not sure.
To make it clear, this line produces the same error:
var i = alphabet.indexOf("c") // Throws Error!
but the compiler likes this line just fine:
var i = alphabet.indexOf('c') // No Error!!!

What is the difference between compareTo and equals in Kotlin?

I want to fully understand the different between compareTo and equals.
I have used this code while trying to understand the difference between them:
println("${'A'.compareTo('b')}")
println("${'A'.equals('b')}")
While using compareTo I get -1 as a result. Nothing is wrong here.
It is also mentioned in the documentation that I will get -1 as a result if the strings are not the same:
Compares this object with the specified object for order. Returns zero if this object is equal to the specified other object, a negative number if it's less than other, or a positive number if it's greater than other.
And while using equals the result that I got was false, then again it looks good as the documentation mentioned - this method will return a boolean:
Indicates whether some other object is "equal to" this one.
Maybe I am missing something really simple, but in the described case, what is the difference between those methods (other than the value that is coming from compareTo and equals)?
The difference between equals and compareTo comes from a few sources.
First, equals is inherited from the Any type in Kotlin, so it is a method attached to all values in the language.
compareTo is inherited from the Comparable type, specifically meaning only its inheritors of:
Boolean, Byte, Char, Double, Duration, Enum, Float, Int etc...
will have the method.
Second, the signature of returned value is different.
Equals has a return of Boolean, meaning you only have true or false being returned from the method call. This will only tell you directly if they are the same or not, with no extra information
The compareTo method has a return of Int, which is a magnitude of the difference between the comparison of the input type. The comparison can not be between different types.
The return of a positive Integer that the Receiver value, is greater than the input value being checked against
To clarify, the Receiver is the variable or instance that the compareTo method is being called on.
For example:
val myValue: Boolean = false
val myCheck: Boolean = true
myValue.compareTo(myCheck) // Return: 1
In that code, the Receiver would be myValue because it is calling the method compareTo. Kotlin interprets true to be a greater value than false so myValue.compareTo(myCheck) will return1`
The return of 0 means that the Receiver value is the same value as the input parameter value.
val myValue: Boolean = true
val otherValue: Boolean = true
myValue.compareTo(otherValue) // Return: 0
The return of a negative number is a magnitude of difference between the two values, specific to each type based on the Receiver value being considered a value of less than the input parameter.
val myString = "zza"
val otherString = "zzz"
myString.compareTo(otherString) // Return: -25
The equality being a bit complicated to explain, but being the same length with only 1 Char place being different, it returns the difference of the Char values as an Int.
val myString = "zz"
val otherString = "zzz"
myString.compareTo(otherString) // Return: -1
In this case the difference is literally the existence of 1 Char, and does not have a value difference to assign.
For equals, the comparative other can be of Any type, not specifically the same type as the Receiver like in compareTo.
The equals method is also an operator function and can be syntactically used such as:
val myString: String = "Hello World"
val otherString: String = "Hello World"
myString == otherString // Return: true
Any non-null value can not be equal to null:
val myString = "Hello World"
val maybeNull: String? = null
myString == maybeNull // Return: false
Equality is specific to each type and has it's own specific documentation to clarify its nuances: Kotlin Equality

Using method_getReturnType to call specific types of instance member functions

I'm new to Objective-C so I don't have much idea about the language.
What I'm trying to do is go through all available instance methods of an object and call the ones that take no arguments, return bool and start with the string "func".
Here's how I get the methods:
uint32_t methodCount = 0;
Method * methods = class_copyMethodList(object_getClass(self), &methodCount);
I iterate through the methods and when the above condition matches, try to call them:
NSString * methodName = [NSString stringWithUTF8String:sel_getName(method_getName(method))];
char retTyp[10];
method_getReturnType(method, retTyp, 10);
const char * desiredRetType = "B";
if([methodName hasPrefix:#"func"] &&
(0 == strncmp(retTyp, desiredRetType, strlen(desiredRetType))) &&
(2 == method_getNumberOfArguments(method)))
{
bool * (* testMethod) (id, Method) = (void (*) (id, Method, ...)) method_invoke;
result = testMethod(self, method);
}
I had to experimentally figure out what the return type string is (turns out it's "B" for bool), and the number of arguments.
I'm getting the following error on the line where I'm trying to call the function using method_invoke:
cannot initialize a variable of type 'bool *(*)(__strong id, Method)' (aka 'bool *(*)(__strong id, objc_method *)') with an rvalue of type 'void (*)(__strong id, Method, ...)' (aka 'void (*)(__strong id, objc_method *, ...)'): different return type ('bool *' vs 'void')
Is there a better way to way to do this than class_copyMethodList?
How do I cast the function correctly so as to not get an error?
Is it possible that the method_getReturnType() conversion of return
types may change from system to system? Or is it always B for bool?
NVM, I figured it out. Instead of using method_invoke on the method name, I did this:
NSString * methodName = [NSString stringWithUTF8String:sel_getName(method_getName(method))];
char retTyp[10];
method_getReturnType(method, retTyp, 10);
const char * desiredRetType = "B";
if([methodName hasPrefix:#"func"] &&
(0 == strncmp(retTyp, desiredRetType, strlen(desiredRetType))) &&
(2 == method_getNumberOfArguments(method)))
{
SEL testMethod = method_getName(method);
return [self performSelector:testMethod];
}

What is the point of coercions like Int(Cool)?

The Perl 6 Web site on functions says
Coercion types can help you to have a specific type inside a routine, but accept wider input. When the routine is called, the argument is automatically converted to the narrower type.
sub double(Int(Cool) $x) {
2 * $x
}
say double '21'; # 42
say double Any; # Type check failed in binding $x; expected 'Cool' but got 'Any'
Here the Int is the target type to which the argument will be coerced, and Cool is the type that the routine accepts as input.
But what is the point for the sub? Isn't $x just an Int? Why would you restrict the caller to implement Cool for the argument?
I'm doubly confused by the example because Int already is Cool. So I did an example where the types don't share a hierarchy:
class Foo { method foomethod { say 'foomethod' } }
class Bar {}
class Quux is Foo {
# class Quux { # compile error
method Bar { Bar.new }
}
sub foo(Bar(Foo) $c) {
say $c.WHAT; # (Bar)
# $c.foomethod # fails if uncommented: Method 'foomethod' not found for invocant of class 'Bar'
}
foo(Quux.new)
Here the invocant of foo is restricted to provide a Foo that can be converted to a Bar but foo cannot even call a method of Foo on $c because its type is Bar. So why would foo care that the to-be-coerced type is a Foo in the first place?
Could someone shed some light on this? Links to appropriate documentation and parts of the spec are appreciated as well. I couldn't find anything useful there.
Update Having reviewed this answer today I've concluded I had completely misunderstood what #musiKk was getting at. This was revealed most clearly in #darch's question and #musiKk's response:
#darch: Or is your question why one might prefer Int(Cool) over Int(Any)? If that's the case, that would be the question to ask.
#musiKk: That is exactly my question. :)
Reviewing the many other answers I see none have addressed it the way I now think it warrants addressing.
I might be wrong of course so what I've decided to do is leave the original question as is, in particular leaving the title as is, and leave this answer as it was, and instead write a new answer addressing #darch's reformulation.
Specify parameter type, with no coercion: Int $x
We could declare:
sub double (Int $x) { ... } # Accept only Int. (No coercion.)
Then this would work:
double(42);
But unfortunately typing 42 in response to this:
double(prompt('')); # `prompt` returns the string the user types
causes the double call to fail with Type check failed in binding $x; expected Int but got Str ("42") because 42, while looking like a number, is technically a string of type Str, and we've asked for no coercion.
Specify parameter type, with blanket coercion: Int() $x
We can introduce blanket coercion of Any value in the sub's signature:
sub double (Int(Any) $x) { ... } # Take Any value. Coerce to an Int.
Or:
sub double (Int() $x) { ... } # Same -- `Int()` coerces from Any.
Now, if you type 42 when prompted by the double(prompt('')); statement, the run-time type-check failure no longer applies and instead the run-time attempts to coerce the string to an Int. If the user types a well-formed number the code just works. If they type 123abc the coercion will fail at run-time with a nice error message:
Cannot convert string to number: trailing characters after number in '123⏏abc'
One problem with blanket coercion of Any value is that code like this:
class City { ... } # City has no Int coercion
my City $city;
double($city);
fails at run-time with the message: "Method 'Int' not found for invocant of class 'City'".
Specify parameter type, with coercion from Cool values: Int(Cool) $x
We can choose a point of balance between no coercion and blanket coercion of Any value.
The best class to coerce from is often the Cool class, because Cool values are guaranteed to either coerce nicely to other basic types or generate a nice error message:
# Accept argument of type Cool or a subclass and coerce to Int:
sub double (Int(Cool) $x) { ... }
With this definition, the following:
double(42);
double(prompt(''));
works as nicely as it can, and:
double($city);
fails with "Type check failed in binding $x; expected Cool but got City (City)" which is arguably a little better diagnostically for the programmer than "Method 'Int' not found for invocant of class 'City'".
why would foo care that the to-be-coerced type is a Foo in the first place?
Hopefully it's now obvious that the only reason it's worth limiting the coerce-from-type to Foo is because that's a type expected to successfully coerce to a Bar value (or, perhaps, fail with a friendly message).
Could someone shed some light on this? Links to appropriate documentation and parts of the spec are appreciated as well. I couldn't find anything useful there.
The document you originally quoted is pretty much all there is for enduser doc. Hopefully it makes sense now and you're all set. If not please comment and we'll go from there.
What this does is accept a value that is a subtype of Cool, and tries to transform it into an Int. At that point it is an Int no matter what it was before.
So
sub double ( Int(Cool) $n ) { $n * 2 }
can really be thought of as ( I think this is how it was actually implemented in Rakudo )
# Int is a subtype of Cool otherwise it would be Any or Mu
proto sub double ( Cool $n ) {*}
# this has the interior parts that you write
multi sub double ( Int $n ) { $n * 2 }
# this is what the compiler writes for you
multi sub double ( Cool $n ) {
# calls the other multi since it is now an Int
samewith Int($n);
}
So this accepts any of Int, Str, Rat, FatRat, Num, Array, Hash, etc. and tries to convert it into an Int before calling &infix:<*> with it, and 2.
say double ' 5 '; # 25
say double 2.5; # 4
say double [0,0,0]; # 6
say double { a => 0, b => 0 }; # 4
You might restrict it to a Cool instead of Any as all Cool values are essentially required to provide a coercion to Int.
( :( Int(Any) $ ) can be shortened to just :( Int() $ ) )
The reason you might do this is that you need it to be an Int inside the sub because you are calling other code that does different things with different types.
sub example ( Int(Cool) $n ) returns Int {
other-multi( $n ) * $n;
}
multi sub other-multi ( Int $ ) { 10 }
multi sub other-multi ( Any $ ) { 1 }
say example 5; # 50
say example 4.5; # 40
In this particular case you could have written it as one of these
sub example ( Cool $n ) returns Int {
other-multi( Int($n) ) * Int($n);
}
sub example ( Cool $n ) returns Int {
my $temp = Int($n);
other-multi( $temp ) * $temp;
}
sub example ( Cool $n is copy ) returns Int {
$n = Int($n);
other-multi( $n ) * $n;
}
None of them are as clear as the one that uses the signature to coerce it for you.
Normally for such a simple function you can use one of these and it will probably do what you want.
my &double = * * 2; # WhateverCode
my &double = * × 2; # ditto
my &double = { $_ * 2 }; # bare block
my &double = { $^n * 2 }; # block with positional placeholder
my &double = -> $n { $n * 2 }; # pointy block
my &double = sub ( $n ) { $n * 2 } # anon sub
my &double = anon sub double ( $n ) { $n * 2 } # anon sub with name
my &double = &infix:<*>.assuming(*,2); # curried
my &double = &infix:<*>.assuming(2);
sub double ( $n ) { $n * 2 } # same as :( Any $n )
Am I missing something? I'm not a Perl 6 expert, but it appears the syntax allows one to specify independently both what input types are permissible and how the input will be presented to the function.
Restricting the allowable input is useful because it means the code will result in an error, rather than a silent (useless) type conversion when the function is called with a nonsensical parameter.
I don't think an example where the two types are not in a hierarchical relationship makes sense.
Per comments on the original question, a better version of #musiKk's question "What is the point of coercions like Int(Cool)?" turned out to be:
Why might one prefer Int(Cool) over Int(Any)?
A corollary, which I'll also address in this answer, is:
Why might one prefer Int(Any) over Int(Cool)?
First, a list of various related options:
sub _Int_strong (Int $) {} # Argument must be Int
sub _Int_cool (Int(Cool) $) {} # Argument must be Cool; Int invoked
sub _Int_weak (Int(Any) $) {} # Argument must be Any; Int invoked
sub _Int_weak2 (Int() $) {} # same
sub _Any (Any $) {} # Argument must be Any
sub _Any2 ( $) {} # same
sub _Mu (Mu $) {} # Weakest typing - just memory safe (Mu)
_Int_strong val; # Fails to bind if val is not an Int
_Int_cool val; # Fails to bind if val is not Cool. Int invoked.
_Int_weak val; # Fails to bind if val is not Any. Int invoked.
_Any val; # Fails to bind if val is Mu
_Mu val; # Will always bind. If val is a native value, boxes it.
Why might one prefer Int(Cool) over Int(Any)?
Because Int(Cool) is slightly stronger typing. The argument must be of type Cool rather than the broader Any and:
Static analysis will reject binding code written to pass an argument that isn't Cool to a routine whose corresponding parameter has the type constraint Int(Cool). If static analysis shows there is no other routine candidate able to accept the call then the compiler will reject it at compile time. This is one of the meanings of "strong typing" explained in the last section of this answer.
If a value is Cool then it is guaranteed to have a well behaved .Int conversion method. So it will not yield a Method not found error at run-time and can be relied on to provide a good error message if it fails to produce a converted to integer value.
Why might one prefer Int(Any) over Int(Cool)?
Because Int(Any) is slightly weaker typing in that the argument can be of any regular type and P6 will just try and make it work:
.Int will be called on an argument that's passed to a routine whose corresponding parameter has the type constraint Int(...) no matter what the ... is. Provided the passed argument has an .Int method the call and subsequent conversion has a chance of succeeding.
If the .Int fails then the error message will be whatever the .Int method produces. If the argument is actually Cool then the .Int method will produce a good error message if it fails to convert to an Int. Otherwise the .Int method is presumably not a built in one and the result will be pot luck.
Why Foo(Bar) in the first place?
And what's all this about weak and strong typing?
An Int(...) constraint on a function parameter is going to result in either:
A failure to type check; or
An.Int conversion of the corresponding argument that forces it to its integer value -- or fails, leaving the corresponding parameter containing a Failure.
Using Wikipedia definitions as they were at the time of writing this answer (2019) this type checking and attempted conversion will be:
strong typing in the sense that a type constraint like Int(...) is "use of programming language types in order to both capture invariants of the code, and ensure its correctness, and definitely exclude certain classes of programming errors";
Currently weak typing in Rakudo in the sense that Rakudo does not check the ... in Int(...) at compile time even though in theory it could. That is, sub double (Int $x) {}; double Date; yields a compile time error (Calling double(Date) will never work) whereas sub double (Int(Cool) $x) {}; double Date; yields a run time error (Type check failed in binding).
type conversion;
weak typing in the sense that it's implicit type conversion in the sense that the compiler will handle the .Int coercion as part of carrying out the call;
explicit type conversion in the sense that the Int(...) constraint is explicitly directing the compiler to do the conversion as part of binding a call;
checked explicit type conversion -- P6 only does type safe conversions/coercions.
I believe the answer is as simple as you may not want to restrict the argument to Int even though you will be treating it as Int within the sub. say for some reason you want to be able to multiply an Array by a Hash, but fail if the args can't be treated as Int (i.e. is not Cool).
my #a = 1,2,3;
my %h = 'a' => 1, 'b' => 2;
say #a.Int; # 3 (List types coerced to the equivalent of .elems when treated as Int)
say %h.Int; # 2
sub m1(Int $x, Int $y) {return $x * $y}
say m1(3,2); # 6
say m1(#a,%h); # does not match
sub m2(Int(Cool) $x, Int(Cool) $y) {return $x * $y}
say m2('3',2); # 6
say m2(#a,%h); # 6
say m2('foo',2); # does not match
of course, you could also do this without the signature because the math operation will coerce the type automatically:
sub m3($x,$y) {return $x * $y}
say m3(#a,%h); # 6
however, this defers your type check to the inside of the sub, which kind of defeats the purpose of a signature and prevents you from making the sub a multi
All subtypes of Cool will be (as Cool requires them to) coerced to an Int. So if an operator or routine internal to your sub only works with Int arguments, you don't have to add an extra statement/expression converting to an Int nor does that operator/routine's code need to account for other subtypes of Cool. It enforces that the argument will be an Int inside of your sub wherever you use it.
Your example is backwards:
class Foo { method foomethod { say 'foomethod' } }
class Bar {}
class Quux is Bar {
method Foo { Foo.new }
}
sub foo(Foo(Bar) $c) {
#= converts $c of type Bar to type Foo
#= returns result of foomethod
say $c.WHAT; #-> (Foo)
$c.foomethod #-> foomethod
}
foo(Quux.new)