Open4

AtCoderやる上でF#7.0でになったことでできるようになったこと

sanorsanor

F# 5.0

文字列補間

回答の表示が楽になる。

https://learn.microsoft.com/ja-jp/dotnet/fsharp/whats-new/fsharp-50#string-interpolation

let name = "Phillip"
let age = 29
printfn $"Name: {name}, Age: {age}"

printfn $"I think {3.0 + 0.14} is close to {System.Math.PI}!"

型を強制する

let name = "Phillip"
let age = 29

printfn $"Name: %s{name}, Age: %d{age}"

// Error: type mismatch
// printfn $"Name: %s{age}, Age: %d{name}"

複数行に分けることも可能。

let str =
    $"""The result of squaring each odd item in {[1..10]} is:
{
    let square x = x * x
    let isOdd x = x % 2 <> 0
    let oddSquares xs =
        xs
        |> List.filter isOdd
        |> List.map square
    oddSquares [1..10]
}
"""

スライスの挙動

例外を投げたり投げなかったりしたので空のスライスを返すよう、挙動に一貫性を持たせた。
スライスの利用で例外を気にする必要がなくなる。

let l = [ 1..10 ]
let a = [| 1..10 |]
let s = "hello!"

// Before: 空のリストを返す
// F# 5: 同じ
let emptyList = l[-2..(-1)]

// Before: 例外を投げる
// F# 5: 空の配列を返す
let emptyArray = a[-2..(-1)]

// Before: 例外を投げる
// F# 5: 空の文字列を返す
let emptyString = s[-2..(-1)]

https://github.com/fsharp/fslang-design/blob/main/FSharp-5.0/FS-1077-tolerant-slicing.md

3D, 4D配列の固定インデックスを使用したスライス

これは使うことはないかも。
z=0

x\y 0 1
0 0 1
1 2 3

z=1

x\y 0 1
0 4 5
1 6 7

個の配列からスライス[| 4;5 |]を取り出す。

// First, create a 3D array to slice

let dim = 2
let m = Array3D.zeroCreate<int> dim dim dim

let mutable count = 0

for z in 0..dim-1 do
    for y in 0..dim-1 do
        for x in 0..dim-1 do
            m[x,y,z] <- count
            count <- count + 1

// Now let's get the [4;5] slice!
m[*, 0, 1]
sanorsanor

F# 6.0

配列等の参照にexpr[idx]が使える

元々、a.[1]のようにピリオドが必要だったのがa[1]で済むようになった。

let a = [|1;2;3;4;5|]
printfn $"{a[1]}" // 2

インデント構文の改訂

これで警告が生成されなくなったらしい(LangVersionタグの指定では再現しない)。
あまりこういう書き方をする人はいないかもしれないが、直感的に合ってそうなインデントで警告が出なくなったのはいいことでしょう。

let c = [
    1
    2
]

整数型の暗黙の型変換

F#では任意の数値リテラルはintとして扱われるようになっており、int64として扱わせたい場合は明示的に10Lと指定しなければいけなかった。F#6.0以降から、以下のような場合に各要素はint64として渡される。

let f (data: seq<int64>) = Seq.sum data
f [| 1; 2; 3; |]

// これはNG
// let a = [| 1; 2; 3; |]
// f a

// これはOK
let a : int64 array = [| 1; 2; 3; |]
f a |> printfn "%d"

暗黙の型変換

C#で以下の演算子で定義される暗黙の型変換について、F#でも暗黙の型変換が行われるようになりました。内部的にはop_Implicitメソッドを生成しており、これがC#同様に暗黙的に呼ばれるようになった。

public static implicit operator TypeName(SomeType value);

2進数、8進数の書式指定子

以下のコードを実行すると

printf "%o" 123
printf "%B" 123

以下のように8進数、2進数で出力してくれる。

173
1111011

AtCoder的にこれはかなり役に立ちそう。

sanorsanor

F#7.0の内容はあまり競技プログラミングに関係しなさそう。