C#8: Switch expression return tuple - tuples

why this
(Func<Window> win1, int i1) = ( () => new Window(), 1);
and this
(int i2, int i3) = 1 switch {
1 => (2, 1),
_ => throw new ArgumentOutOfRangeException()
};
works.
but that doesn't
(Func<Window> win2, int i4) = 1 switch {
1 => (() => new Window(), 1),
_ => throw new ArgumentOutOfRangeException()
};

The reason behind these inconsistencies is because your different examples hit different aspects of deconstructors and type inference.
Your first case is an example of a side effect of an optimisation added to C# 7.1 which optimises away a deconstruct of a tuple. This was introduced to allow the use of a constructor pattern:
public class Person
{
public string Name { get; }
public int Age { get; }
public Person(string name, int age) => (Name, Age) = (name, age);
}
without incurring the overhead of assigning a tuple and then deconstructing it. The compiler "lowers" that contructor to:
public Person(string name, int age)
{
Name = name;
Age = age;
}
Therefore, when the compiler encounters:
(Func<Window> win1, int i1) = ( () => new Window(), 1);
it converts it to:
Func<Window> win1 = new Window();
int i1 1;
All types are known and so all is well.
Your next example can be better explained if we change it to:
var a = 1 switch {
1 => (2, 1),
_ => throw new ArgumentOutOfRangeException()
};
This expression takes advantage of the fact that the compiler ignores the throw when determining the type of a switch expression. There's only one other arm, which it can infer is of type (int, int). It chooses that as the return type for the switch expression and a is inferred to be of type (int, int).
With your example, you are then taking that tuple and deconstructing it into two int's: i1 and i2. Because the type of the expression is known, the compiler is happy that it knows how to deconstruct that expression.
Before addressing your last example, we again need to modify it slightly:
(Func<Window>, int) tmp = 1 switch {
1 => (() => new Window(), 1),
_ => throw new ArgumentOutOfRangeException()
};
This code compiles. The reason is because we are now using a target-typed switch expression. If the compiler cannot infer the type of the switch expression from the arms of that expression, then it looks to the target of the expression (in this case an assignment) to see if that has a type that satisfies all the arms of the switch expression. C# doesn't infer a delegate type for lambdas; it requires they be explicity typed or inferred. In this example, the type (Func<Window>, int) is a suitable type for all the arms of the switch expression, so that type is used.
This approach doesn't work for your example though as you have a deconstruct on the lhs of the assignment. The deconstruct needs to know the type it's deconstructing and the switch expression needs a target type. As you point out in a comment, there's a quirk of the compiler that satisfies both of these: delare a variable after the deconstruct:
(Func<Window> win2, int i4) tmp = 1 switch {
1 => (() => new Window(), 1),
_ => throw new ArgumentOutOfRangeException()
};
The compiler then lowers that to:
(Func<Window>, int) tmp = 1 switch {
1 => (() => new Window(), 1),
_ => throw new ArgumentOutOfRangeException()
};
(Func<Window> win2, int i4) = tmp;
The compiler certainly could avoid this and infer that variable itself, but that would need to be proposed and adopted as an enhancement to the language. Head on over to dotnet/csharplang discussions on github if you fancy doing that.
Update: I've created a discussion there: Should C# support mixing deconstructors and target-typed switch/option expressions as it seems an important point to discuss anyway.

Related

How to Define Something that Acts as a Dictionary of Unique Functions in F#?

It is my understanding that a Dictionary's elements must all be the same (ie: unit -> unit)
I need a way to add functions to an object, similar to a Dictionary, but my problem is that the functions have different Types. The only thing I can know for sure is that added functions will always follow a pattern of int -> 'T where 'T could be any Type. All functions in the object could be made to inherit from a shared type if needed. Here is a non-functioning example of how it would be used.
let myFunctions = Dictionary<int,int -> unit>()
let exampleFunction0 (x : int) : int = x + 1
let exampleFunction1 (x : int) : byte = (byte)x
let exampleFunction2 (x : int) : string[] = Array.create<string> 1 "test"
myFunctions.Add(0, exampleFunction0)
myFunctions.Add(1, exampleFunction1)
myFunctions.Add(2, exampleFunction2)
let randomNumber = System.Random().Next(3)
let result x = myFunctions.Item(randomNumber) x
It is important to note that which one of the functions that gets called is random and I cannot know it. The purpose of the dictionary is to hold the functions that will be called randomly. As in the examples, the results are not the same as I need the results to be different for each function. x will always be the same, but the result of the function will not.
The code will be in a library to be reused, so functions may be added that I will never see.
You need to unify the output types to make this work.
If all the types are known you should use a Discriminated Union.
type ReturnValues =
| Case0 of int
| Case1 of byte
| Case2 of string[]
let myFunctions = Dictionary<int,int -> ReturnValues>()
let exampleFunction0 (x : int) = x + 1 |> Case0
let exampleFunction1 (x : int) = (byte)x |> Case1
let exampleFunction2 (x : int) = Array.create<string> 1 "test" |> Case2
myFunctions.Add(0, exampleFunction0)
myFunctions.Add(1, exampleFunction1)
myFunctions.Add(2, exampleFunction2)
let randomNumber = System.Random().Next(3)
let result x : ReturnValues = myFunctions.Item(randomNumber) x
If you don't know all the types you can make all the return types obj (Dictionary<int,int -> obj>) using the box function or you can make all the return types implement a common interface.
What has ultimately solved the problem for me is to package together the Type and Object. This package is what the functions that will be added to the dictionary must return. This way there is a standard way for new types to be added after compilation.
open System.Collections.Generic
open System
// a package that can hold an object and its type
type package(x, y) =
member this.x : Type = x
member this.y : Object = y
//empty class for testing
type testClass() = class end
//custom types for testing
type fiy(x) =
member this.Value : string = x
type foe(x) =
member this.Value : testClass = x
//functions for testing
let func0 (x: int) : package = package(typeof<int>, x)
let func1 (x: int) : package = package(typeof<fiy>, fiy("potato"))
let func2 (x: int) : package = package(typeof<foe>, foe(testClass()))
let myFunctions = Dictionary<int, (int -> package)>()
//example use of adding a function
myFunctions.Add(0, (func0))
myFunctions.Add(1, (func1))
myFunctions.Add(2, (func2))
//pick a random number to test with; as we will have no idea which function will be ran
let randomNumber = System.Random().Next(3)
let pickedFunction x : package = (myFunctions.Item(randomNumber) x)
let ranFunction = pickedFunction 5 //just some filler number to test with
printfn "The type of the ranFunction is: %s" (ranFunction.x.ToString())

Rust accessing Option from mutex

I am having trouble understanding how to modify Option inside a Mutex.
When there's no Option, it works fine
let mut my_int = Arc::new(Mutex::new(5));
let my_int_clone = Arc::clone(&my_int);
thread::spawn(move || {
let mut my_int = my_int_clone.lock().unwrap();
*my_int += 1;
}).join();
let my_int_clone_print = Arc::clone(&my_int);
println!("Value: {}", my_int_clone_print.lock().unwrap());
However, when I wrap the value in Some, I had to manually use ref mut and such (I found it from here) because the lock().unwrap() returns MutexGuard, not the Option itself.
let mut my_int = Arc::new(Mutex::new(Some(5)));
let my_int_clone = Arc::clone(&my_int);
thread::spawn(move || {
let mut my_int = my_int_clone.lock().unwrap();
match *my_int {
Some(ref mut val) => {
*val += 1;
},
None => {
println!("Value is None. Doing nothing..");
}
}
}).join();
let my_int_clone_print = Arc::clone(&my_int);
println!("Value: {}", my_int_clone_print.lock().unwrap());
Any idea which Rust concept causes this? And also are there any more data types besides Option which returns MutexGuard and not its original value?
Actually, Mutex::lock returns Result<MutexGuard, ..> in both cases. Though, this type has interesting trait implementation: Deref and DerefMut. These allow explicit dereference via * operator. Consider this example with the explicit types:
let mutex = Mutex::new(1i32);
let mut guard: MutexGuard<'_, i32> = mutex.lock().unwrap();
// This dereferences to &mut i32
// because assignment operator works with &mut self.
*guard = 2;
// Nevertheless, for an explicit borrowing you need &mut
// because otherwise it would be moved from the guard.
let inner: &mut i32 = &mut *guard;
And, of course, you can use Option similarly:
let mutex = Mutex::new(Some(1i32));
let mut guard: MutexGuard<'_, Option<i32>> = mutex.lock().unwrap();
// Directly change inner value
*guard = Some(2);
// or use in match, notice &mut borrowing
match &mut *guard {
Some(x) => *x += 1,
None => {},
}
Notice, the last match example is exactly the same as yours but uses a slightly different syntax. Playground.
there any more data types besides Option which returns MutexGuard and not its original value?
MutexGuard can't return the original value because moving the value would invalidate the mutex. Instead, it's a wrapper that provides a mutable reference to the original value.
That's in no way specific to Option, a MutexGuard is what Mutex::lock always returns. For example, this code:
let m = Mutex::<bool>::new(false);
let () = m.lock().unwrap();
...will complain that the type returned by m.lock().unwrap() is std::sync::MutexGuard<'_, bool>.
MutexGuard gives out access to the data under the condition that the reference does not outlive the guard. *my_int += 1 works because MutexGuard implements DerefMut, which tells the * operator what reference to work on. And the * operator works perfectly fine with Option; for example:
let m = Mutex::<Option<i32>>::new(Some(0));
let mut my_int = m.lock().unwrap();
*my_int = Some(100);
Matching an *my_int can be done without ref mut, but then *my_int will copy the option (which works as long as its contents are Copy) and modifying the value will have no effect on the option itself. This is again in no way specific to MutexGuard, it's how matching works. The ref mut is required to give you mutable access to the data inside the option.

What is the equivalent to `thing = this() || that` in Swift 3?

In most languages I can write something like this:
this = this() || that()
If this() returns something false, like integer 0, that() will be evaluated. Pretty common idiom.
Swift 3 doesn't automatically cast Int to Bool so that idiom doesn't work. What is a succinct way to do it in Swift 3?
There's no exact equivalent in Swift, as:
No other types than Bool cannot be converted to Bool
You cannot write a function returning Bool or Int
(In most languages is a little bit exaggerated, you cannot write such thing in Java, C# or many other strongly-typed languages.)
The most similar thing in Swift is nil-coalescing operator -- ??.
Assume this() returns Int? (aka Optional<Int>), and that() returns Int (non-Optional):
func this() -> Int? {
//...
if someCondition() {
return intValue
} else {
return nil
}
}
func that() -> Int {
//...
return anotherIntValue
}
And use nil-coalescing operator like this:
let result = this() ?? that()
In this assignment, if this() returns non-nil value, then that() is not evaluated, and that non-nil value is assigned to result. When this() returns nil, that() is evaluated and the value is assigned to result.
The nil coalescing operator as covered by #OOPer:s answer is the fit for purpose idiom here, but as a side-note, you could implement functionality as the one your describe by overloading the || operator, e.g. for types that conform to some type constraint. E.g. using Integer as type constraint:
extension Bool {
init<T : Integer>(_ value: T) {
self.init(value != 0)
}
}
func ||<T: Integer>(lhs: T, rhs: #autoclosure () -> T) -> T {
return Bool(lhs) ? lhs : rhs()
}
var thisNum = 0
let thatNum = 12
thisNum = thisNum || thatNum
print(thisNum) // 12

Can we declare the type of parameters when we define curry-style functions?

If I define a function with tuple-style parameters, I can define the parameter types and the return types:
fun hello(name:String, code:int):String = "hello!"
But if I use curry-style, I can only do it like this:
fun hello name code = "hello!"
Is it possible to add parameter types or return types for the later one?
It is indeed possible:
fun hello (name : string) (code : int) : string = "hello!"
However, type-annotations are seldom needed or used in Standard ML, so it's most often preferred to omit them.
Another way to do this if the function isn't curried is to specify the full function type, a la Haskell,
val hello : string * int -> string =
fn (name, code) => "hello!"
You can do this with recursive functions too
val rec hello : string * int -> string =
fn (name, code) => hello ("hello!", 5)
Uncurried functions are a bit messier, though the type description is still nicer.
val hello : name -> int -> string =
fn name => fn code => "hello!"

Build a function object with properties in TypeScript

I want to create a function object, which also has some properties held on it. For example in JavaScript I would do:
var f = function() { }
f.someValue = 3;
Now in TypeScript I can describe the type of this as:
var f: { (): any; someValue: number; };
However I can't actually build it, without requiring a cast. Such as:
var f: { (): any; someValue: number; } =
<{ (): any; someValue: number; }>(
function() { }
);
f.someValue = 3;
How would you build this without a cast?
Update: This answer was the best solution in earlier versions of TypeScript, but there are better options available in newer versions (see other answers).
The accepted answer works and might be required in some situations, but have the downside of providing no type safety for building up the object. This technique will at least throw a type error if you attempt to add an undefined property.
interface F { (): any; someValue: number; }
var f = <F>function () { }
f.someValue = 3
// type error
f.notDeclard = 3
This is easily achievable now (typescript 2.x) with Object.assign(target, source)
example:
The magic here is that Object.assign<T, U>(t: T, u: U) is typed to return the intersection T & U.
Enforcing that this resolves to a known interface is also straight-forward. For example:
interface Foo {
(a: number, b: string): string[];
foo: string;
}
let method: Foo = Object.assign(
(a: number, b: string) => { return a * a; },
{ foo: 10 }
);
which errors due to incompatible typing:
Error: foo:number not assignable to foo:string
Error: number not assignable to string[] (return type)
caveat: you may need to polyfill Object.assign if targeting older browsers.
TypeScript is designed to handle this case through declaration merging:
you may also be familiar with JavaScript practice of creating a function and then extending the function further by adding properties onto the function. TypeScript uses declaration merging to build up definitions like this in a type-safe way.
Declaration merging lets us say that something is both a function and a namespace (internal module):
function f() { }
namespace f {
export var someValue = 3;
}
This preserves typing and lets us write both f() and f.someValue. When writing a .d.ts file for existing JavaScript code, use declare:
declare function f(): void;
declare namespace f {
export var someValue: number;
}
Adding properties to functions is often a confusing or unexpected pattern in TypeScript, so try to avoid it, but it can be necessary when using or converting older JS code. This is one of the only times it would be appropriate to mix internal modules (namespaces) with external.
So if the requirement is to simply build and assign that function to "f" without a cast, here is a possible solution:
var f: { (): any; someValue: number; };
f = (() => {
var _f : any = function () { };
_f.someValue = 3;
return _f;
})();
Essentially, it uses a self executing function literal to "construct" an object that will match that signature before the assignment is done. The only weirdness is that the inner declaration of the function needs to be of type 'any', otherwise the compiler cries that you're assigning to a property which does not exist on the object yet.
EDIT: Simplified the code a bit.
Old question, but for versions of TypeScript starting with 3.1, you can simply do the property assignment as you would in plain JS, as long as you use a function declaration or the const keyword for your variable:
function f () {}
f.someValue = 3; // fine
const g = function () {};
g.someValue = 3; // also fine
var h = function () {};
h.someValue = 3; // Error: "Property 'someValue' does not exist on type '() => void'"
Reference and online example.
As a shortcut, you can dynamically assign the object value using the ['property'] accessor:
var f = function() { }
f['someValue'] = 3;
This bypasses the type checking. However, it is pretty safe because you have to intentionally access the property the same way:
var val = f.someValue; // This won't work
var val = f['someValue']; // Yeah, I meant to do that
However, if you really want the type checking for the property value, this won't work.
I can't say that it's very straightforward but it's definitely possible:
interface Optional {
<T>(value?: T): OptionalMonad<T>;
empty(): OptionalMonad<any>;
}
const Optional = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.empty = () => OptionalCreator();
if you got curious this is from a gist of mine with the TypeScript/JavaScript version of Optional
An updated answer: since the addition of intersection types via &, it is possible to "merge" two inferred types on the fly.
Here's a general helper that reads the properties of some object from and copies them over an object onto. It returns the same object onto but with a new type that includes both sets of properties, so correctly describing the runtime behaviour:
function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
Object.keys(from).forEach(key => onto[key] = from[key]);
return onto as T1 & T2;
}
This low-level helper does still perform a type-assertion, but it is type-safe by design. With this helper in place, we have an operator that we can use to solve the OP's problem with full type safety:
interface Foo {
(message: string): void;
bar(count: number): void;
}
const foo: Foo = merge(
(message: string) => console.log(`message is ${message}`), {
bar(count: number) {
console.log(`bar was passed ${count}`)
}
}
);
Click here to try it out in the TypeScript Playground. Note that we have constrained foo to be of type Foo, so the result of merge has to be a complete Foo. So if you rename bar to bad then you get a type error.
NB There is still one type hole here, however. TypeScript doesn't provide a way to constrain a type parameter to be "not a function". So you could get confused and pass your function as the second argument to merge, and that wouldn't work. So until this can be declared, we have to catch it at runtime:
function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
if (typeof from !== "object" || from instanceof Array) {
throw new Error("merge: 'from' must be an ordinary object");
}
Object.keys(from).forEach(key => onto[key] = from[key]);
return onto as T1 & T2;
}
This departs from strong typing, but you can do
var f: any = function() { }
f.someValue = 3;
if you are trying to get around oppressive strong typing like I was when I found this question. Sadly this is a case TypeScript fails on perfectly valid JavaScript so you have to you tell TypeScript to back off.
"You JavaScript is perfectly valid TypeScript" evaluates to false. (Note: using 0.95)