使用函数式编程语言 ELM 开发游戏

简介:

这是我首次准备就有关用 elm 进行游戏开发的内容撰写一个系列的文章. 这是一种能编译成 html 和 javascript,以便你可以将其直接部署到web服务器上,或者打包到 nw.js 中以创建一个独立的应用或者游戏,这样的编程语言. 没有多少教程可以参考,但是随着我的慢慢进步之中我已经了解到了越来越多的东西. 因为 elm 正处在积极的发展过程中,如果或者当我的文章有点过时的时候,我将会对它们进行更新. 也会慢慢纠正我在里面留下的错误 …

函数式编程 (FP) 是一种令人惊异的边界不清的范式. 不少人对它都有很多不同的认识,而它所为我呈现的,则是一个希望能编写更加简单的可组合式代码的群体, 以避免强 耦合 并创建出易于调试的软件.

Games
从很多编程的领域看来,游戏开发是最适合面向对象的而且游戏总是带很多状态。从表面上看,面向对象这种方法很适合。当我使用 Functional Programming的时候,我发现这种方法也很适合游戏编程,而且我也对如何解决问题很感兴趣。

为什么我选择用Functional Programming开发游戏呢? 简单的说,我对传统的软件设计方法感到厌倦。命令式的面向对象代码对导致一下过度设计的问题,而且很不美观。

这仅仅是我的个人观点,所以请放松,但是如果你渴望一些不同的事物,为什么不来functional的路上看看呢。

Iteration

看看下面最简单的js例子,对于一个数组取平方。使用"命令式"的代码你会描述一些将要发生的事情。而用functional代码(声明式编程的子集),你去描述你想要做的事情。所以"命令式"的风格中我们会定义一个临时的index变量然后创建一个循环,遍历一遍数组,然后每个value取平方。

var numbers = [1,2,3,4,5,6,7,8,9],
    i;
for (i = 0; i < numbers.length; i++) {
    numbers[i] *= numbers[i];
}

相比起来,functional的方法路线呢,如果你写js可以考虑下lodash这个库。然而使用一个专门是functional programming的语言,会比的很容易,所以我们使用elm来做这件事。

import List (..)
square : Int -> Int
square n =
    n * n
numbers : List Int
numbers =
    map square [1..9]

使用elm我们不需要定义临时变量,我们也会创建一个数组更容易,而且定义一个function复用。通过map我们将每个list的数字取平方,然后返回一个新的list。

正如你看到的,functions是对于传进来的每个变量有类型提示的。import List (..)这一行简单引入了核心list function,elm自带的这些function 提供了 map和filter的方法。

var _ = require('lodash');
var square = _.curryRight(_.map, 2)(function(n){
  return n *n;
});
square([1,2,3,4,5,6,7,8,9]);

Filtering

现在设想一下我们想从数组中移除奇数,然后只平方哪些过滤后的数组。通常,“命令式”的js是这样写的:

var numbers = [1,2,3,4,5,6,7,8,9],
    squaredNumbers = [],
    i;
for (i = 0; i < numbers.length; i++) {
    if (numbers[i] % 2 == 0) {
        squaredNumbers.push(numbers[i] * numbers[i]);
    }
}
numbers = squaredNumbers;

当然,这样写可以用,但是定义另外一个数组看起来很乱,而且我们还是得写循环。这就是"命令式"代码最不具有新意的地方。你可能会在你的代码的1000个地方重复写上面的代码。

现在我们试试functional 的写法:

isEven : Int -> Bool
isEven n =
    n % 2 == 0
numbers : List Int
numbers =
    map square (filter isEven [1..9])

我们在numbers里增加一个filter,然后这块方法就变得可以复用了,我们不需要对于有点不同的需求写重复代码。

这里就是functional programming闪耀的地方了,你花了更少的时间在编写想要的做的东西上,而且代码阅读起来也很方便。还有就是这证明了方法是可以链式调用的。

文章转载自 开源中国社区 [http://www.oschina.net]

相关文章
|
2月前
|
缓存 JavaScript 前端开发
精通JavaScript修饰器:超越传统编程范式的进阶技巧
在JavaScript中,修饰器(Decorator)是一种特殊的语法,用于修改类、方法或属性的行为。修饰器提供了一种简洁而灵活的方式来扩展和定制代码功能。本文将详细介绍JavaScript修饰器的概念、语法和应用场景,并提供相关的代码示例。
|
3月前
|
JavaScript Go Python
我愿称之为最容易上手的编程语言——Yaklang(I)
我愿称之为最容易上手的编程语言——Yaklang(I)
46 0
|
8月前
让我设计一门编程语言或开发一套解决框架
让我设计一门编程语言或开发一套解决框架
70 2
|
8月前
|
存储 Java 编译器
GO语言基础语法探究:简洁高效的编程之道2
GO语言基础语法探究:简洁高效的编程之道
|
8月前
|
安全 Go C语言
GO语言基础语法探究:简洁高效的编程之道 3
GO语言基础语法探究:简洁高效的编程之道
|
8月前
|
存储 自然语言处理 编译器
GO语言基础语法探究:简洁高效的编程之道 1
GO语言基础语法探究:简洁高效的编程之道
|
机器学习/深度学习 前端开发 JavaScript
Web开发及人机交互导论 实验八 JavaScript程序结构
Web开发及人机交互导论 实验八 JavaScript程序结构
202 0
Web开发及人机交互导论 实验八 JavaScript程序结构
|
缓存 前端开发 API
ReactiveCocoa 进阶,轻松搞定函数式编程框架
函数式编程已经变得越来越流行,而且也有很大的优势,作为iOS开发者,函数式编程框架**ReactiveCocoa**到底怎么使用呢, 接下来我们来深入介绍**ReactiveCocoa**及其在**MVVM**中的用法。
138 0
|
设计模式 自然语言处理 JavaScript
7 行代码 3 分钟:从零开始实现一门编程语言
本文介绍了多种解释器实现。通过修改最后一个解释器,你应该可以快速测试关于编程语言的新想法。如果你希望有一种语法不一样的语言,就可以构建一个解析器,把 s-表达式转储。这样,你就可以干净利落地将语法设计与语义设计分开。
429 0
7 行代码 3 分钟:从零开始实现一门编程语言
|
存储 Java 程序员
C++ 开发者快速学习 Objective-C 语言核心语法
本文将讨论 Objective-C 语言的核心语法。这部分开始详述一些具体的语法。正如你期待的一样,涉及到了定义和类。
224 0