v ML jazycích (tedy i v F#) se používá termín "variable" v původním matematickém významu, kde většinou koncept měnitelnosti ani není zaveden. Snažím se zachovat původní terminologii, jinak budou třeba manuály k F# zmatečné. (navíc by asi bylo dobré, když už, použít "pojmenovaná konstanta", protože za konstantou si někdo může představit navázanou hodnotu).
Mutabilita je ve funkcionálním jazyce cesta do pekel, nicméně jde to i čistě funkcionálně, viz zde: http://leanprover.github.io/talks/NFM2022.pdf (slajdy s titulkem "Local Imperative Programming") — "Lean 4 is still a purely functional language." Vypadá to skoro jako černá magie.
Příklad:
def main : IO Unit := do let mut x := 1 repeat do IO.println s!"{x}" x := x + 1 unless x <= 10 do break
Tady je citace z článku “Do unchained”, co jsem už jednou posílal:
“we explore extending do notation with other imperative language features that can be added to simplify monadic code: local mutation, early return, and iteration. We present formal translation rules that compile these features back down to purely functional code”
Takže ten kód je čistě funkcionální, všechno, co je uvnitř “do” a vypadá imperativně, je jen syntaktický cukr.
Boltzmann má na náhrobku log, myšlen ale jako ln. Lepší se vždy ujistit, co ten symbol znamená, tak to je.
https://en.wikipedia.org/wiki/Boltzmann%27s_entropy_formula
14. 9. 2023, 20:17 editováno autorem komentáře
V F# nie je zvykom písať Printf.printf
, to je asi OCaml zlozvyk. :) Module Printf je priamo dostupný v programoch. Modul obsahuje širokú škálu print funkcií. V posledných dvoch verziách F# boli pridané bohaté možnosti interpolácie reťazcov. (To bolo dovtedy zvláštne opomenutie.) Medzi najčastejšie používanými je zrejme funkcia printfn
.
let msg = "an old falcon" printf "%s\n" msg printfn "%s" msg let n = 32 eprintfn $"error message {n}" let name = "Jone Doe" let age = 34 printfn $"{name} is {age} years old" let res = sprintf "Write five = %d and six = %d" (3+2) (3+3) printfn "%s" res let name2 = "Roger Roe" let age2 = 30 printfn $"""Name: %s{name2}, Age: %d{age2}"""
Dlho mi nešlo do hlavy, prečo nie je dostupná funkcia, ktorá bez všetkého vypíše premennú, podobne ako print v Pythone. Autori zrejme predpokladajú použitie .NET metódy Console.WriteLine
.
Poznámka k špecifikátoru %A
.
let data = [0..4] let output = $"The data is %A{data}"
Ten sa využíva na diagnostické vypísanie ľubovoľnej hodnoty, hlavne tých komplexnejších.
Pre pochopenie Unit typu. Toto je hodnota, nie funkcia:
let hello = printfn "Hello there"
Toto je funkcia:
let hello () = printfn "Hello there"
Funkcie musia z definície niečo vracať.
Poznámka k recordom. Pokiaľ je každý field na samostatnom riadku, tak je bodkočiarka voliteľná. Ionide automaticky takto formátuje.
Na rozdiel od jazykov, ktoré sa умудрили pridať recordy len v poslednej dobe, F# ich má od začiatku s využitým jednoduchej, priamočiarej syntaxe. Recordy považujem za základnú nevyhnutnosť pre programovacie jazyky, ktoré chcú ašpirovať na dátovú analýzu.
14. 9. 2023, 10:14 editováno autorem komentáře
Operátory :=
a !
pro práci s referencemi jsou zastaralé od verze 6.0 - viz https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/reference-cells#deprecated-constructs
Krom toho bych řekl, že ref
se v F# moc nepoužívá - stačí buď mutable
nebo se používá ref ze C#, který je v F# znám jako byref
, inref
, outref
,
Které? Myslím, že mají zavedné od verze 5 dost věcí:
"""OCaml 5 brings in support for concurrency through effect handlers and the new Input/Output library Eio, which lets developers compose asynchronous and synchronous code together."""
Ale nejsem samozrejme v obraze co se tyka neajkho vyzkumu. Myslel sem že efekty a zavislostni typy jsou top. Na efektech delaj i ve Scala: https://softwaremill.com/the-future-of-effects-in-scala/
Ale neberte mne moc vazne, mne zivi Python :D
14. 9. 2023, 20:30 editováno autorem komentáře
Obecně zbavit se nečistého kódu a zvýšit efektivitu (běhu). Ten překlad imperativního kódu do čistě funkcionálního je hodně dobrý. K té efektivitě stačí zavést FBIP (in situ modifikace perzistentnícn struktur). K těm typům — jasně, některé jazyky k tomu směřují, například Scala, ale aby pak kód za něco stál (aby byl čitelný a bez zbytečného boilerplatu), musí mít jazyk i implicitní koerce. To tak namátkou, ty jazyky se mezi sebou inspirují, jen ta implementace často dost dlouho trvá.
Ty reference jsou docela SG :) By mě zajímalo, nakolik jsou v jazyce vůbec nutné, stejného efektu jde ve FP dosáhnout i nějak takto:
structure Accu where value : Nat deriving Inhabited def main : IO Unit := do let mut acc : Accu := default for i in [:10] do acc := { acc with value := acc.value + i } IO.println s!"{acc.value}"