知乎周源微信_每周源代码34-F#的兴起

本文介绍了F#编程语言,它以其类型安全性、简洁性、高性能和脚本编写能力受到推崇。F#在Visual Studio中得到支持,并拥有自己的开发者中心。文章强调了F#的不可变性原则,类似于C#中的字符串,以及其函数式编程特性,如避免副作用。此外,还提到了F#中的计量单位支持和一些示例代码,展示了其在游戏开发中的应用。文章鼓励读者尝试学习F#,每年掌握一种新语言。
摘要由CSDN通过智能技术生成
知乎周源微信

知乎周源微信

First, let me remind you that in my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you thirty-fourth in a infinite number of posts of "The Weekly Source Code."

首先,让我提醒您,在我不断追求的阅读源代码以成为更好的开发人员的过程中,亲爱的读者,我在无限数量的“每周源代码”中向您展示第三十四位

F#, everyone is agog over F# and getting all functional. Again. ;) The F# September 2008 CTP came out a few weeks back and folks I'm talking to are digging it. Here's the goal:

F#,每个人都为F#感到痛苦,并获得了所有功能。 再次。 ;) F#2008年9月CTP发布了几周,我正在与之交谈的人们正在对此进行挖掘。 目标是:

"F# developed as a research programming language to provide the much sought-after combination of type safety, succinctness, performance, expressivity and scripting, with all the advantages of running on a high-quality, well-supported modern runtime system."

“ F#作为一种研究编程语言而开发,它提供了类型安全性简洁性性能表达性脚本编写等广受欢迎的组合,并具有在高质量,支持良好的现代运行时系统上运行的所有优点。”

Looks like it's more than a research language as it's inside Visual Studio and looking pretty with syntax highlighting and intellisense and everything. This might be old news to you, Dear Reader, but F# is reaching a very significant level of polish. This release is moving F# to the level of being a peer of C# and VB. It's got its own F# DevCenter at MSDN. How's that for legit?

它看起来不仅是一种研究语言,还因为它位于Visual Studio中,并且在语法高亮,智能感知等所有方面看起来都很漂亮。 亲爱的读者,这对您来说可能是个老新闻,但F#正在达到非常重要的水平。 此版本将F#提升为与C#和VB对等的水平。 它在MSDN上拥有自己的F#DevCenter 。 合法性如何?

Here's a great one paragraph explanation from Vertigo's Rick Taylor about what/why/how F#:

这是Vertigo的里克·泰勒( Rick Taylor)关于F#为何/为什么/如何进行的一段很棒的解释:

"Unless you specify otherwise, everything in F# is immutable, much like the string construct in C#. This extends to areas that you might not expect. For instance, once you set an int to some specific value, that's it – you can't change it, unless you have marked it as mutable. The reason for this is because the language is primarily a functional one. Programs in functional languages contain functions which return values, which are then further used, etc – but each value or set of values is its own entity, and to change it while within a function is to produce a side effect, something undesirable in a functional language. In the strictest sense, functions return values but do not alter their parameters, or the outside world (which, incidentally, gives rise to the monad pattern mentioned earlier). F# follows these rules of functional programming, but also allows you to break those rules with the mutable keyword."

“除非另外指定,否则F#中的所有内容都是不可变的,就像C#中的字符串构造一样。这扩展到了您可能不会想到的区域。例如,一旦将int设置为某个特定值,就可以了–您不能除非您将其标记为可变的,否则请对其进行更改,其原因是因为该语言主要是一种功能性语言,而使用功能性语言的程序所包含的函数会返回值,然后将其进一步使用,依此类推–但是每个值或一组值是它自己的实体,在函数中进行更改会产生副作用,这在函数式语言中是不可取的。从最严格的意义上讲,函数返回值但不更改其参数,或者返回外界(偶然地, ,产生前面提到的monad模式。F#遵循这些函数式编程规则,但也允许您使用mutable关键字来破坏这些规则。”

What's the best way to jump into F#? Well there's a few great ways. First, a little blatant self-promotion. I've done two F# podcasts with smart F# fanboys and there's great .NET Rocks and Herding Code episodes too.

跳入F#的最佳方法是什么? 好吧,有几种很棒的方法。 首先,有一点公然的自我促进。 我已经与聪明的F#粉丝一起完成了两个F#播客,并且还有很棒的.NET Rocks和Herding Code插曲。

Books

图书

  • I enjoyed Robert's "Foundations of F#" book very much.

    我非常喜欢罗伯特的《 F#基础》一书。

  • Also, if you're a freaking ninja rocket scientist, you can always read "F# for Scientists." Seriously. I dare you to buy that, in person, at Borders. Freaking scientists. (Seriously, though, it's a fabulous book and you can get some free excerpts here)

    另外,如果您是个忍者火箭迷,可以随时阅读“ F#for Scientists” 。 说真的我敢于亲自在Borders购买。 令人发狂的科学家。 (严重的是,这是一本很棒的书,您可以在此处获得一些免费摘录)

  • Don Syme, the creator of F# has "Expert F#" available and it's very highly rated.

    F#的创建者Don Syme提供了“ Expert F# ”,并且获得了很高的评价。

F#博客 (F# Blogs)

Code

F#Eye for the C#Guy(F# Eye for the C# Guy)

However, as a F# newbie with a few years of Haskell in the back of my head, the presentation that has clicked with me the most was Leon's F# eye for the C# guy PowerPoint. Scandalous, I know, as you may know Leon as the cruel bully who called me Hanselgirl in public recently at TechEd Australia. I promptly boxed his ears (it was more of a slap-fight actually) and there was also a public arm-wrestling. Between the two of us I'm sure there was the potential to splice together one normal-sized male arm, but I digress. You can download his deck here, but I've also taken the liberty to put it on SlideShare and embedded it here.

但是,作为F#的新手,在我脑海中呆了几年的Haskell,对我来说印象最深刻的演示是Leon为C#家伙PowerPointF#眼。 我知道这是丑闻,您可能知道莱昂是残酷的恶霸,最近在澳大利亚TechEd公开场合叫我Hanselgirl 。 我Swift地把他的耳朵打了个拳(实际上更像是打耳光),还有一个公开的手臂摔跤。 我们确定在我们两个人之间有可能将一根正常大小的男性手臂拼接在一起,但我离题了。 您可以在此处下载他的卡座,但我也可以将其放到SlideShare上并嵌入到此处。

F# Eye for the C# Guy F#Eye for the C#Guy
View SlideShare presentation or Upload your own. (tags: f# c#)
查看SlideShare 演示文稿上传自己的 演示文稿。 (标签: f# c# )

I had intellectualized slides 42 through 45, but the way he described it clicked. He did what I would do:

我已经将幻灯片42到45进行了智能化处理,但是他所描述的方式吸引了人们的注意。 他做了我会做的事情:

"I worked this out using Reflector. I did not work this out from reading books or papers or listening to podcasts or quizzing intelligent people. A simple let statement is a static function, under the hood. When you see let, think function."

“我使用Reflector来解决这个问题。我没有通过阅读书籍或论文,听播客或测验聪明的人来解决这个问题。简单的let语句实际上是一个静态函数。当您看到let时,请考虑一下函数。”

Check out those few slides,. It's a great deck, and I'm sure Leon wouldn't mind YOU, Dear Reader, showing his talk at your local User Group or having a Programmer's Lunch at work and taking complete credit for it. That's what I fully plan on doing. ;) Suck it Bambrick!*

看看那几张幻灯片。 这是一个很好的平台,亲爱的读者,我敢肯定,Leon不会介意您在您当地的用户组中发表他的演讲,或者在工作中享用程序员午餐,并完全赞扬它。 这就是我完全计划做的事情。 ;)吮吸Bambrick!*

Let's see three bits of code.

让我们看看三位代码。

首先,一些基本的东西。 (First, something basic.)

Remember there are no variables. No side-effects.

记住没有变量。 没有副作用。

#light

let sqr x = x * x
let multiply x y = x * y

print_int (sqr 3)
print_int (multiply 3 4)

// recursive function fibonacci series using pattern matching
let rec fib x =
match x with
| x when x <= 0 -> failwith "An integer greater than 0 is required."
| 1 -> 1
| 2 -> 1
| x -> fib (x - 1) + fib (x - 2)

print_int (fib 15)

// functions as values
let add x y = x + y
let a1 = add 3
let a2 = a1 4

print_int a2

第二,有光泽。 (Second, something shiny.)

Units of Measure in F#. What? Andrew Kennedy's PhD thesis from 13 years ago just happens to be a feature in F#. He's done a three part series:

F#中的计量单位。 什么? 13年前的安德鲁·肯尼迪(Andrew Kennedy)的博士学位论文恰好是F#的特色。 他完成了一个三部分的系列:

Basically they've added static checking and inferences for units-of-measure. Not any specific ones, but the concept itself.

基本上,他们为度量单位添加了静态检查和推断。 不是任何特定的,而是概念本身。

"As far as F# is concerned, ft and m have nothing to do with each other. It's up to you, the programmer, to define appropriate conversion factors."

“就F#而言,ft和m彼此无关。程序员(取决于您)定义合适的转换因子。”

Here's a screenshot from his blog that says a thousand words and showcases the FSharp.Math.PhysicalConstants namespace, along with the International System of Units (SI) namespace.

这是他博客中的一幅截图,上面写着一千个单词,展示了FSharp.Math.PhysicalConstants命名空间以及国际单位制(SI)命名空间。

image

Also from Andrew's blog:

同样来自安德鲁的博客:

"You can define mutually recursive measures using "and" to connect them and placing the Measure attribute immediately before the name of the measure:"

“您可以使用“和”来定义相互递归的度量,以将它们连接起来,并将Measure属性直接置于度量名称之前:”

type [<Measure>] km = 
static member toM = 1.0/1000.0<m/km>
and [<Measure>] m =
static member toKm = 1000.0<km/m>

第三,有些愚蠢。 (Third, something silly.)

A fun little 2D Tron-Clone game from last year, written in only 182 lines of F# by Phil Trelford. You can download it from hubFS and read how he wrote it on the Applied Games Group Blog. The game even supports Xbox 360 controllers! Sweet.

去年一个有趣的小型2D Tron-Clone游戏,仅由Phil Trelford用182行F#编写。 您可以从hubFS下载它,在Applied Games Group Blog上阅读他的写法。 该游戏甚至支持Xbox 360控制器! 甜。

Here's all 182 lines, not counting the first 4 lines of comments.

这是全部182行,不包括注释的前4行。

//-----------------------------------------------------------------------------
// LightCycles.fs Mini game using windows forms
// 2007 written by Phillip Trelford
//-----------------------------------------------------------------------------

#light

#if DIRECTX
#R @"C:\WINDOWS\assembly\GAC_32\Microsoft.DirectX\2.0.0.0__31bf3856ad364e35\Microsoft.DirectX.dll" // Feb 206
open Microsoft.DirectX.XInput // Required to read XBox 360 controllers
#endif

open System
open System.Drawing
open System.Windows.Forms

/// Game states
type GameState = | Start | Play | Over

/// Form key handler type
type KeyHandler (form:Form) =
do form.KeyPreview <- true
let keys = Enum.GetValues (type Keys) :?> (Keys [])
let keysDown = Array.create keys.Length false
let FindKeyIndex code = keys |> Array.find_index (fun x -> code = x)
do form.KeyDown.Add (fun e -> keysDown.[FindKeyIndex e.KeyCode] <- true)
do form.KeyUp.Add (fun e -> keysDown.[FindKeyIndex e.KeyCode] <- false)
member this.IsKeyDown (keyCode:Keys) = keysDown.[FindKeyIndex keyCode]
member this.AnyKeyDown () = keysDown |> Array.exists (fun x -> x)

/// Player direction type
type Direction = | Left | Right | Up | Down

/// Player type
type Player (color,startX,startY,direction,keys,keyHandler:KeyHandler) =
let mutable x = startX
let mutable y = startY
let mutable d = direction

member this.Color = color
member this.X = x
member this.Y = y
member this.Keys = keys

/// Reset player to start values
member this.Reset () = x <- startX; y <- startY; d <- direction

/// Updates player position
member this.Update i =
// Read keyborad
let mutable newD = d
let up, down, left, right = keys
if keyHandler.IsKeyDown(up) then newD <- Up
if keyHandler.IsKeyDown(down) then newD <- Down
if keyHandler.IsKeyDown(left) then newD <- Left
if keyHandler.IsKeyDown(right) then newD <- Right
#if DIRECTX
// Read XBox 360 controller
let state = Controller.GetState(i)
if state.IsConnected then
let pad = state.GamePad
if pad.UpButton then newD <- Up
if pad.DownButton then newD <- Down
if pad.LeftButton then newD <- Left
if pad.RightButton then newD <- Right
#endif
/// Don't allow suicide move
match (d,newD) with
| (Left, Right) | (Right, Left) | (Up, Down) | (Down, Up) -> ()
| _ -> d <- newD
/// Update position with direction
match d with
| Up -> y <- y - 1
| Down -> y <- y + 1
| Left -> x <- x - 1
| Right -> x <- x + 1

/// Main form
let form = new Form (Text="Light Cycles", Width=680, Height=544)

do /// Layout for game window and status panel
let layout = new TableLayoutPanel(Dock=DockStyle.Fill, ColumnCount = 2)
layout.ColumnStyles.Add( ColumnStyle(SizeType = SizeType.Percent, Width = 100.0f ) ) |> ignore
layout.ColumnStyles.Add( ColumnStyle(SizeType = SizeType.Absolute, Width = 128.0f) ) |> ignore
/// Play area in pixels
let playArea = 500
/// Game play area bitmap
let bm = new Bitmap(playArea, playArea)
/// Clears screen
let ClearScreen () =
using (Graphics.FromImage(bm)) (fun graphics -> graphics.Clear(Color.Black))
/// Draws text to screen
let DrawText s =
using (Graphics.FromImage(bm)) (fun graphics ->
let rect = new RectangleF(0.0f,0.0f,float32 playArea,float32 playArea)
let align = new StringFormat(Alignment=StringAlignment.Center, LineAlignment=StringAlignment.Center)
graphics.DrawString(s, form.Font, Brushes.White, rect, align)
)
// Initialise screen
ClearScreen ()
DrawText "Press any key to start"
/// PictureBox to contain game bitmap
let pictureBox = new PictureBox(Dock=DockStyle.Fill)
pictureBox.Image <- bm
layout.Controls.Add(pictureBox)

let keyHandler = KeyHandler (form)

/// Players array
let players =
[| Player (Color.Red,playArea/2+20,playArea/2,Down,(Keys.Q,Keys.A,Keys.Z,Keys.X),keyHandler);
Player (Color.LightBlue,playArea/2-20,playArea/2,Up,(Keys.P,Keys.L,Keys.N,Keys.M),keyHandler) |]
players |> Array.iter (fun player -> bm.SetPixel(player.X,player.Y,player.Color))

/// Display player controls
let statusPanel = new TableLayoutPanel(Dock=DockStyle.Fill, ColumnCount=1, BackColor=Color.DarkGray)
players |> Array.iteri (fun i player ->
let name =
[| ((new Label (Text=sprintf "Player %d" i, ForeColor=player.Color)) :> Control) |]
let up, down, left, right = player.Keys
let controls =
Array.combine [|"Up";"Down";"Left";"Right"|] [|up;down;left;right|]
|> Array.map (fun (name,key) -> (new Label (Text=sprintf "%s '%O'" name key)) :> Control )
Array.append name controls
|> statusPanel.Controls.AddRange
)
layout.Controls.Add(statusPanel)
form.Controls.Add(layout)

/// Game play - returns true if there has been a collision otherwise false
let PlayGame () =
let collisions = players |> Array.mapi (fun i player ->
player.Update i
let x, y = (player.X, player.Y)
let wall = x < 0 || x >= playArea || y < 0 || y >= playArea
if wall then
true
else
let bgColor = bm.GetPixel(x, y)
bm.SetPixel (x, y, player.Color)
players |> Array.exists (fun player -> let c = player.Color in c.R = bgColor.R && c.G = bgColor.G && c.B = bgColor.B )
)
pictureBox.Refresh ()

match collisions |> Array.tryfind_index (fun x -> x = true) with
| Some(i) -> i
| None -> (-1)

/// Current game state
let gameState = ref GameState.Start
let gameOverWaitCount = ref 200
let r = new Random()

/// Timer instance
let timer = new Timer()
timer.Interval <- 1000/50
// Timer event
timer.Tick.Add (fun _ ->
match !gameState with
| Start ->
if keyHandler.AnyKeyDown () then
ClearScreen ()
gameState := GameState.Play

| Play ->
let i = PlayGame ()
if i>=0 then
gameState := GameState.Over
gameOverWaitCount := 200
DrawText (sprintf "Game Over - Play %d Lost" i)
pictureBox.Refresh ()
| Over ->
// Shake screen
form.Left <- form.Left + if !gameOverWaitCount > 150 then r.Next(5) - 2 else 0
// Decrement Game Over wait
decr gameOverWaitCount
if !gameOverWaitCount <= 0 then
gameState := GameState.Start
players |> Array.iter (fun player -> player.Reset ())
ClearScreen ()
DrawText "Press any key to start"
pictureBox.Refresh ()
)
timer.Start ()

[<STAThread>]
do Application.Run(form)

Try to learn ONE new language each year!

尝试每年学习一种新语言!

Related Posts

相关文章

* Oh, relax, Dear Reader. Leon and I are, like, totally, BFF. We're peas and carrots. Truly. The bastard.

*噢,放松,亲爱的读者。 莱昂和我完全是BFF。 我们是豌豆和胡萝卜。 真的混蛋

翻译自: https://www.hanselman.com/blog/the-weekly-source-code-34-the-rise-of-f

知乎周源微信

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值