F
.env
ファイルを読み込みたい
- URL
.env
と書いたがini
ファイルなど同じように読める形式はもう少しあるはず. - シンプルは読み込み関数はない(?)らしい.
- 次のコードで環境変数に叩き込めるから後は環境変数読み込みの形で取ればよい.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | open System
open System.IO
let parseLine(line : string) =
Console.WriteLine (sprintf "Parsing: %s" line)
match line.Split('=', StringSplitOptions.RemoveEmptyEntries) with
| args when args.Length = 2 -> Environment.SetEnvironmentVariable(args.[0], args.[1])
| _ -> ()
let load() =
lazy (
Console.WriteLine "Trying to load .env file..."
let currentDir = Directory.GetCurrentDirectory()
let pDir = Directory.GetParent(currentDir).ToString() // 都合によって親ディレクトリの.envを読んでいるが必要なければ削除
let filePath = Path.Combine(pDir, ".env") // 親ディレクトリの.envを読んでいるので同じディレクトリにあるなら適切に書き換える
filePath
|> File.Exists
|> function
| false -> Console.WriteLine "No .env file found."
| true -> filePath |> File.ReadAllLines |> Seq.iter parseLine
)
let init = load().Value
// 環境変数から読み込む部分
let apiRootUrl = Environment.GetEnvironmentVariable "NEXT_PUBLIC_API_ROOT_URL"
|
bottom
| let undefined<'T> : 'T = failwith "Not implemented yet"
let stub1 (x : int) : float = undefined
let stub2 (x : 'T) : 'T = undefined
|
| let undefined<'T> : 'T = raise (NotImplementedException())
|
fsx実行: 競プロ用実行
| dotnet fsi hoge.fsx
dotnet fsi hoge.fsx < input.txt
|
fsxで他のfsxを読み込む
| #load "Script1.fsx"
open Script1
|
Fable
メモ
| dotnet new --install Fable.Template
dotnet new fable
|
Json
- 参考
C#
のコードを参考にすればよい mutable
と<-
を使うのが大事
| open System.Text.Json
open System.Text.Json.Serialization
open System.Text.Encodings.Web
open System.Text.Unicode
let mutable options = JsonSerializerOptions()
options.Encoder <- JavaScriptEncoder.Create(UnicodeRanges.All)
let jsonString = JsonSerializer.Serialize(items, options)
System.IO.File.WriteAllText(outputJsonFileName, jsonString, System.Text.Encoding.UTF8)
|
Stack overflow
AtCoderの木DPで, Pythonコードに沿って実装してみたらStack overflowしたのでその対処の記録.
- 再帰関数で stack overflow しないように末尾再帰に書き直すのはF#だけでなく関数プログラミングで必須技能なので練習しよう
- 再帰の回数の上限ではなくスタックに割り当てられるメモリの量に制限がある
- 管理は.NETではなくOS
- Linuxなら
ulimit -s
で変更できるはず - 参考: Python版
Stringにはreverseがない(?)ので代替策を見つけた
どなたか有識者の方, いい感じのメソッドがあれば教えてほしい. 今回はProject Euler Problem 4の回文数の問題を解いているときに出くわした. どうもStringにはreverseメソッドがないらしい. 検索した結果, 今回はこのページのコピペとして次のコードを採用した.
| let reverse (s : string) = s |> Seq.toArray |> Array.rev |> System.String
s |> Seq.rev |> System.String.Concat
|
あと最近F#のリファレンスがGitHubにうつったようだ. そのリンクも改めて貼っておこう.
GitHubのAlgorithmsAndDataStructureByFSharpにアルゴリズム系のコードと共にF#の「ライブラリ」という名の自分用コードサンプル集を作ってある. 具体的にはLibraryディレクトリがそう. そのうち競プロ用にいろいろ調べたことを改めてLibraryにまとめ直したい. 何はともあれ,
F#, とにかく情報がないので地道に貯めていく.
型プロバイダー FSharp.Data
の型プロバイダーには定数しか渡せない
- URL
- 下記コードで
FSharp.Data.JsonProvider<"http://localhost">
の<>
内は変数にできない
1
2
3
4
5
6
7
8
9
10
11
12 | #r "nuget: FSharp.Data"
open FSharp.Data
open FSharp.Data.HttpRequestHeaders
let toJson = fun (x: HttpResponse) ->
match x.Body with
| Text t -> t
| _ -> failwith "bytes"
/// http://localhost
type Root = FSharp.Data.JsonProvider<"http://localhost">
Http.Request("http://localhost", httpMethod = "GET") |> toJson |> fun t -> Root.Parse(t)
|
型プロバイダー 実行時のディレクトリ指定
- URL
ResolutionFolder=__SOURCE_DIRECTORY__
を指定する
| #r "nuget: FSharp.Data"
open FSharp.Data
type Comments = JsonProvider<"sampleResponse.json", ResolutionFolder=__SOURCE_DIRECTORY__>;;
|
関数に型をつける
ふつうの方法
| let f (i:int) (j:int): int = i * j
|
ラムダを使う方法
| let f: int -> int -> int =
fun i j -> i * j
|
空シーケンスの判定, 特にmatch
- 空シーケンスのリテラルがないので
s when Seq.isEmpty s
のように書く.
| let rec dropWhile p xs =
match xs with
| s when Seq.isEmpty s -> Seq.empty
| _ -> if p (Seq.head) then dropWhile p (Seq.tail xs) else (Seq.tail xs)
|
処理時間測定
| open System.Diagnostics
let sw = System.Diagnostics.Stopwatch()
sw.Start()
// 処理
sw.Stop()
stdout.WriteLine(sw.Elapsed)
|
遅延リストはとりあえずSeq
- 残念ながらHaskellのリストなどと同じ書き味にはならない
| Seq.initInfinite (fun i -> 2 * i + 1)
|
ファイルの読み書き
C# (.NET)
のメソッドを使おう - JSONの場合の注意
- 既定のエンコーダーと比較して
UnsafeRelaxedJsonEscaping
エンコーダーは文字をエスケープせずにそのまま渡すことについてより寛容 <
, >
, &
, '
などHTMLに影響する文字はエスケープされない s.Replace(@"\u002B", "+").Replace(@"\u003C", "<").Replace(@"\u0027", "'").Replace(@"\u0026", "&").Replace(@"\u003E", ">")
で置換する
| let fileName = "1.tmp.txt"
System.IO.File.WriteAllText(fileName, someString, System.Text.Encoding.Default)
|
複数行の文字列, ヒアドキュメント
C#と同じように書ける模様. 特に三重引用符または「@+クオート」で書ける. ついでに逐次的リテラル文字列の概念があり, 後者の「@+クォート」形式がそれ. 例を引用しておく.
| ".¥¥hoge¥¥hoge¥¥hoge.txt" // ふつうの文字列
@".¥hoge¥hoge¥hoge.txt" // 逐次的リテラル文字列
|
プロジェクト作成
VSCodeを前提にする.
- 下記の内容のファイルを
setup.txt
として作る. MySolution
とMyProject
は適宜修正. Ctrl+F2
で一斉置換できる.
Ctrl+Shift+P
でコマンドパレットを開いて`TRSTAT と打って実行.
setup.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | dotnet new sln -o MySolution
cd MySolution
mkdir src
dotnet new console -lang F# -o src/MyProject
dotnet sln add src/MyProject/MyProject.fsproj
mkdir tests
dotnet new xunit -lang F# -o tests/MyProjectTests
dotnet sln add tests/MyProjectTests/MyProjectTests.fsproj
cd tests/MyProjectTests
dotnet add reference ../../src/MyProject/MyProject.fsproj
dotnet add package FsUnit
dotnet add package FsUnit.XUnit
dotnet build
dotnet test
|