聊聊什么是多范式编程语言

2023-11-16 09:54:13 +08:00
 Moonbit

想要知道什么是多范式,就不得不提,编程语言是干什么的。

范式与抽象

在我看来,编程语言便是对我们所要描述的问题的一种抽象。抛开最底层、完全模拟计算机运算的汇编语言不谈,每一种语言都根据所要解决的问题进行了抽象。C 语言作为贴近底层的系统开发语言,提供了结构化的流程控制以及过程/函数,来简化指令序列的定义; Go 语言目标是服务器语言,提供了轻量的协程以及通道,来提供更好的并发支持; Haskell 语言是一个函数式语言,因此没有什么是可以变的,执行运算不过是简化表达式; Java 语言将万物视为对象,命令也不过是让对象进行动作;更加针对特定领域的如将法律转化为程序的 Catala 或是用于定义逻辑的 Prolog 等……在每个语言提出一些特性之后,后续的语言都会有所选择地学习借鉴一些特性,或者是在抽象所及范围内进行模拟。例如,Java 便通过将函数看作对象的方式兼容了函数式编程。

范式,就是一种体系,既包括了我们如何看待世界(表达式?对象?或是断言逻辑?),又包括了在这些世界观下解决问题的常见的模式。例如,Haskell 所探索出的通过 Monad 来表示副作用的计算,便成为了函数式编程范式的一部分,被后续的 Scala 等多种语言吸收借鉴;而 GoF 提出的设计模式也广为流传,被大量应用,是面向对象开发时的必备经典。多范式编程语言,顾名思义,就是支持其中的多种范式,方便我们在面对不同问题时能采用最恰当的视角,来解决问题。

让我们以月兔 MoonBit 这一国产编程语言为例。假如说我们想模拟猫狗狭路相逢,坐标分别为-1 和 1 ,狗向猫进一步,猫退一步,如此重复五个回合。

函数式编程

● 如果我们视这个“世界”为表达式,我们可以用函数式编程。

我们视这个“世界”为表达式。我们首先定义模拟环境的数据结构,包含一猫一狗,各有坐标,则有:

struct Cat { location: Int }
struct Dog { location: Int }
struct World { cat: Cat; dog: Dog }

之后,我们定义状态改变的运算函数,如:

fn dog_forward(world: World) -> World {
  { .. world, dog: { .. world.dog, location : world.dog.location - 1 }}
}

fn cat_backward(world: World) -> World {
  { .. world, cat: { .. world.cat, location : world.cat.location - 1 }}
}

最后,我们则可以将它们组合起来,构成我们的模拟:

let simulation: (World) -> World = repeat(compose(dog_forward, cat_backward), 5)

可以看到,我们定义的都是表达式的组合。完整代码在这里:https://try.moonbitlang.com/#9e994c2c

命令式编程

● 如果我们视这个“世界”为冯诺依曼机,我们可以用命令式编程。

我们视这个“世界”为一个内存,而我们则通过指令来修改这个世界。我们同样先定义我们的模拟环境的数据结构,包含一猫一狗,各有坐标,则有:

struct Cat { mut location: Int }
struct Dog { mut location: Int }
struct World { mut cat: Cat; mut dog: Dog}

之后,我们定义改变状态的指令序列,或者说“过程”,如:

fn dog_forward(world: World) -> Unit {
  world.dog.location = world.dog.location - 1
}

fn cat_backward(world: World) -> Unit {
  world.cat.location = world.cat.location - 1
}

最后,我们同样组合起来:

fn simulation(world: World) {
  var i = 0
  while i <= 5 {
    dog_forward(world)
    cat_backward(world)
    i = i + 1
  }
}

可以看到,我们所做的都是在操纵内存中存储的数据,修改“世界”的状态。完整代码在这里:https://try.moonbitlang.com/#b56d6ac7

面向对象编程

● 如果我们视这个“世界”为对象的世界,我们可以用面向对象编程。

我们将猫和狗视为对象。作为对象,它们都具有状态和行为;而它们都是动物,部分行为也是类似的。我们可以先定义动物的状态和行为,例如,它们具有位置;它们可以移动:

interface Animal {
  location(Self) -> Int
  move(Self) -> Unit
}

之后,我们可以定义猫和狗,以及它们的行为。在月兔中,我们采用 structural typing ,于是有:

struct Cat { mut loc: Int }
struct Dog { mut loc: Int }

fn location(self: Cat) -> Int {
  self.loc
}
fn move(self: Cat, distance: Int) -> Unit {
  self.loc = self.loc + distance
}

fn location(self: Dog) -> Int {
  self.loc
}
fn move(self: Dog, distance: Int) -> Unit {
  self.loc = self.loc + distance
}

最后,我们可以定义我们的模拟环境的状态,以及行为:

struct World { mut c: Cat; mut d: Dog}
fn World::new() -> World { { c : { loc: -1 }, d : { loc: 1 } } }
fn cat(self: World) -> Cat { self.c }
fn dog(self: World) -> Dog { self.d }
fn simulate(self: World) -> Unit {
  var i = 0
  while i <= 5 {
    self.dog().move(-1)
    self.cat().move(-1)
    i = i + 1
  }
}

完整代码在这里:https://try.moonbitlang.com/#2d60fce4

总结

范式是一个体系,用来描述我们所面对的问题,并提供了一套方法论,来配套解决方法。但是我们也需要意识到,在软件工程中,不存在所谓的“银弹”,没有什么范式是可以一套打天下的。每一种范式都会有自己的优缺点。例如,想要用纯函数式编程来做输入输出,就可能会遇到 Monad 这个棘手的概念;而用面向对象编程开发,则不免陷入 GoF 提出的各种设计模式的纠缠,而究其原因则来源于面向对象的一些缺陷。

月兔编程语言,以及众多现代编程语言,支持多范式编程,就是希望能提供一把瑞士军刀,以最合适的角度切入问题,解决问题。

1194 次点击
所在节点    编程
6 条回复
SWALLOWW
2023-11-16 10:20:04 +08:00
牛逼,跟昨天听的分享表达的一样,语言是能影响思维
492
2023-11-16 10:25:01 +08:00
牛逼,学到了哥!
tyzandhr
2023-11-16 10:30:32 +08:00
骚年,你渴望|>吗
nagisaushio
2023-11-16 10:31:31 +08:00
一直 monad 一直爽
zagfai
2023-11-16 13:32:03 +08:00
python~
swordcoming9527
2023-11-19 21:42:32 +08:00
稍微看了一下官网介绍和语言文档,语法几乎借用了我喜欢的 rust ,专注于 wasm 。
如果这门语言是华为的,用于鸿蒙应用的开发,再打着国产的旗号才有机会成功。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/992328

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX