Pony语言学习(八):引用能力(Reference Capabilities)

2023-05-16

(如果你有更好的翻译,请务必联系我。我们需要和Rust术语做到翻译看齐)

一.总览(特译:https://tutorial.ponylang.io/reference-capabilities.html):

我们已经学了很多有关Pony类型系统的知识,之后是表达式语法,在有关引用能力的这章里,我们会学到另一Pony类型系统组件级别的知识点。目前好像没有一款主流编程语言支持这一特性。那么什么是引用能力?

Pony语言还支持一种不同的能力——引用能力。对象能力(object capabilities)允许你在对象上作些文章,引用能力却阻止你为了做更多事而申请使用更多内存。比如说,你可以使用这块内存但仅仅是为了读取它,而不是更改它。这就是引用能力,它拒绝操作的权限。

引用能力是使得Pony语言与众不同的核心。在简介里,你或许读到过Pony的优点:

而引用能力就是Pony语言拿来实现上述这些超赞的特性的。不要害怕,咱们现在开始吧!

官方指导:https://www.ponylang.io/learn/#reference-capabilities。你可以里面提到的网址进行广泛的对象能力的理解性学习

二、引用能力

(一).基础概念

虽然其中有些你可能已经熟能成诵了,但为了完整性,还是要啰嗦几句:

1.难以创建能分享的可变数据(Shared mutable data is hard):

在并发开发中,最需重视的问题就是可变数据。设想有两个不同的线程均有权访问某一块数据并且都想更新它(同时!)。最好的情况是,它们两个各有一份不同版本的数据,而最坏的情况是它们都在试图更新一块garbage。最标准的方法(主流)是使用锁来防止数据写入同时发生。这种情况下就导致性能大大降低且作为使用者难以获得权限,从而引出无数bug!

2.不变数据可以被安全分享(Immutable data can be safely shared):

既然数据是不变的,那么也就是说永远不会更新,从而也就避免了由更新引发的并发性问题。

3.孤立数据是安全的(Isolated data is safe):

如果一块数据只有一个引用我们就叫它是孤立的(isolated)(注:0引用如果处理的好的话学名叫垃圾)。既然只有对此只有一个引用,孤立数据就不可能被多个线程分享(此处类比一夫一妻制),所以也不存在并发性问题。

4.孤立数据可能很复杂(Isolated data may be complex):

所谓的孤立数据可能是指一个字节,抑或是一大块带很多引用的数据结构。而我们就看这块数据能不能被当成一个整体,如果能,我们就可以把它设置成isolated。当然,还有一个孤立边界(isolation boundary)需要了解。isolated数据满足:

  1. 在孤立边界外必须有一个对于边界内的对象的引用。
  2. 对于边界内,可以有任意数量的引用,但都不能指向边界外的对象。

5.每个actor都是一个独立线程(Every actor is single threaded):

只含有一个actor的代码永远不会并发运行。只有我们想要在actor间分享数据时才可能出现问题。

(二)类型修饰符:

在C/C++中,你可能使用过const来修饰类型,你也见过某些场景让你说出int const和const int的区别。const在那里就是类型修饰符。在Pony的引用能力实现中,我们使用类型修饰符的方法。在数组那节我们见到了Array[T] ref Array[T] val。下面我们就来看看具体实现。

(三)引用能力列表:

  • Isolated,写作 iso,表示孤立数据结构。如果你有一个iso变量,你就知道没有其他变量可以访问这份数据(相当于不存在其他引用,包括二次及以上引用)。因此你可以随意更改它,最后把它交给另一个actor(之后意味着你放弃了这个引用的所有权,把它送给了另一个actor)。
  • Value,写作 val,表示那些不可变的数据结构。如果你有一个val 变量,你就知道没有人可以改变它的数据。从而你可以随便读它的数据并和其他actor分享(区别分享送给,分享意味着你保留了引用的所有权)。
  • Reference,写作 ref,表示可变的数据结构并且是非孤立的,换句话说,就是普通的数据。如果你有一个ref 变量,你就知道你可以随意进行读写,且很多变量都可以访问到同样的数据(你不能同时读和写,但别人可以同时读)。但你不能和其他actor分享。
  • Box,写作box,表示那些对你来说是只读的变量。这些数据可能是不变的,与其他actor共享的或者说有其他变量可以改变它的数据(打个比方,可以是一个actor有一个reference,你有一个box,特别像服务器和客户端)。box 变量可以被用于安全地读取数据。可能听上去没什么意义,但它允许你为val 和 ref 变量写出同样的代码(毕竟Pony并不支持重载),只要代码不写入数据。
  • Transition,写作 trn,表示当你同一时间拥有对某一数据的box引用,还想向其中写入数据。当然了,你也可以把trn 变量转换成val 变量,从而保证可以被安全地传递到其他actor。
  • Tag,写作tag,表示那些只是用来当标识的变量。你既不能读也不能写,但你可以储存或比较不同的tag 变量(了解Erlang / Elixir的读者可能联想到原子,想到这里非常好。对那些不熟悉原子概念的读者,我挑了一篇写的比较好的erlang原子介绍:https://blog.csdn.net/cloveses/article/details/77945856)。

引用能力的书写:

String iso // An isolated string
String trn // A transition string
String ref // A string reference
String val // A string value
String box // A string box
String tag // A string tag

延伸阅读:

如何创建不同引用能力的对象:

后面我们会学到一个更好的方法:复原能力(Recovering Capabilities)

阅读任务:https://tutorial.ponylang.io/reference-capabilities/guarantees.html

三、耗散和解构读取(Consume and Destructive Read):

(一)耗散:

在日常编码中,把一个变量移动到另一个变量很是常见,换句话说,就是给数据改了个名。在Pony里,我们使用consume关键字,把数据从变量的壳子里抽出来,放到另一个变量里,此时原先的那个变量也就仅仅是个空壳:

fun test(a: Wombat iso) =>
  var b: Wombat iso = consume a // Allowed!
  var c: Wombat tag = a // Not allowed!

那么我能耗散一个字段(field)吗?NO!耗散变量意味着它会成为空壳。你没有办法确保是否有其它别名会访问这块字段。我们使用解构读取来解决这个问题。

(二)解构读取:

我们之前提到过,Pony中的赋值语句会返回变量的旧值(记得吗,万物皆表达式,赋值语句也是表达式,所以它也要返回),这就叫解构读取(destructive read):

class Aardvark
  var buddy: Wombat iso

  new create() =>
    buddy = recover Wombat end

  fun ref test(a: Wombat iso) =>
    var b: Wombat iso = buddy = consume a // Allowed!

四、复原能力(Recovering Capabilities):

recover表达式允许你提升引用能力。一个可变的引用能力(iso trn ref)可以成为任意引用能力,而一个不可变的引用能力(val box)可以成为任何一个不可变的或不透明的(tag)引用能力。

(一)哪里有用?:

recover表达式最直接的应用就是获得一个你可以传给其他actor的 iso 变量。但它还可以用来做其他事情,比如:

  • 创建一个周期的不变数据结构,也就是,你在recover表达式里创造了一个复杂的可变数据结构后,将ref 型结果提升到val 型。
  • 将一个iso 变量作为ref 借用过来,对其做一系列可变的复杂操作,最后以iso 形式返回。
  • 从一个iso 解压出一个可变字段最后又以iso 形式返回

 

(二)接收方自动复原:

当你有一个iso或trn型的接收方时,你通常不能调用ref 型的方法。这是因为接收方也是方法的一个参数,这意味着,函数体和调用方可以同时访问接收方。同时这也意味着,你需要给receiver换个名,iso型 => tag型,trn型 => box型,两种结果类型均不是ref的子类型。

但是有一个办法可以绕过这样繁琐的步骤。如果方法所有的参数相对于调用方是可发送的(sendable),那么这个方法的返回值不是 可发送的 就是 不被调用方使用的, 于是我们就可以“自动复原”接收方。

五、假名(Aliasing):

Aliasing means having more than one reference to the same object, within the same actor. This can be the case for a variable or a field.

在Pony里,我们可以为某些引用能力加假名,但不是全部。

(一)假名和拒绝保护(Aliasing and deny guarantees): 

如果我们尝试为一个iso变量加假名,我们就破坏了iso引用能力的原则——只有一个引用:

fun test(a: Wombat iso) =>
  var b: Wombat iso = a // Not allowed!

按上文讲,iso => tag, trn => box,那么其他的引用能力呢?

在以下三种情况下你需要假名:

  1. 当你给你一个变量或字段赋值时
  2. 当你把值当作参数传给方法时
  3. 当你调用一个方法时,接收方调用的假名就被创建了。它和this对函数体有同样的权限。

(二)临时类型(Ephemeral types):

在Pony里,万物皆表达式,而表达式便就有值,那么cosume a的值是什么?事实上,它不是a的类型,而是a的临时类型。为了区别,我们在之后加一个^表示临时:

fun test(a: Wombat iso): Wombat iso^ =>
  consume a

(三)假名类型:

An alias type is a way of saying “whatever we can safely alias this thing as”.

 类型A => 假名类型 A!

fun test(a: A) =>
  var b: A! = a
//Here, we’re using A as a type variable, which we’ll cover later.
//So A! means “an alias of whatever type A is”.

阅读任务:传递与分享引用(Passing and Sharing References)、能力子类型(Capability Subtyping)、组合能力(Combining Capabilities)

六、箭头类型(视角)(Arrow Types aka Viewpoints):

(一)使用this->视角:

例如:

class Wombat
  var _friend: Wombat

  fun friend(): this->Wombat => _friend

组合能力里我们学到了源自box 的ref / val 返回一个box。如果我们想让上面这个类智能地返回对象,即接收方是ref时就返回ref,val亦如此。我们使用this->来实现。

(二)使用类型参数视角(Using a type parameter as a viewpoint):

(建议先学完泛型再回来看)来自标准库的例子:

class ListValues[A, N: ListNode[A] box] is Iterator[N->A]

这里,N被限制为是ListNode[A] box的子类型,同时这个类还实现了一个接口Iterator,使得我们可以迭代类型N -> A 的值

(三)使用box->视角:

同样来自标准库的例子:

interface Comparable[A: Comparable[A] box]
  fun eq(that: box->A): Bool => this is that
  fun ne(that: box->A): Bool => not eq(that)

这意味着不论A指向什么,我们只需要读取that。

阅读任务:引用能力表

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pony语言学习(八):引用能力(Reference Capabilities) 的相关文章

  • OpenCV—PnP单目测距

    OpenCV PnP单目测距 使用单目相机结合OpenCV的pnp解算实现单目测距 xff08 需要知道物体的长宽 xff09 开始用的opencv 自带的标定api 标定相机 xff0c 但是标定结果和matlab的结果有出入 xff0c
  • 【具体实现过程】百度地图POI区域的边界经纬度坐标数据采集

    最近有个项目需要拿到百度地图中XXX市中所有学校的边界坐标 经过一下午的努力 xff0c 终于成功拿到了坐标 xff0c 对坐标数据还原和验证 特此记录一下具体实现过程和爬取思路 前言 xff1a 什么是POI xff1f Point of
  • Gazebo仿真平台模型搭建与修改

    ROS进阶教程 xff08 一 xff09 Gazebo仿真平台模型搭建与修改 文件讲解Models 文件World文件Launch文件 模型编辑可视化操作配置文件编辑 仿真操作流程完成model建模world文件和launch文件修改 其
  • XShell过期需要采购解决办法

    有天Xshell更新完再打开 xff0c 提示我去采购 xff0c 当然采购得花钱 xff0c 所以下面方法是解决这一问题 1 跳到官网 https www netsarang com download free license html
  • 【SMT32CubeMx安装详解】

    SMT32CubeMx安装详解 文章目录 SMT32CubeMx安装详解 前言一 准备工作二 CubeMax安装三 工程参数配置总结 前言 记录CubeMax软件安装和相关工程配置的简单操作 一 准备工作 在我们进行软件安装之前首先将我们需
  • AirSim无人机仿真平台(windows)

    1 环境 xff1a UE4 26 43 AirSim 43 VS2019 2 安装步骤 xff1a 1 xff09 先下载Epic Games安装启动器 xff0c 然后再安装UE4 26 xff1b 2 xff09 安装VS2019社区
  • ubuntu18在docker下运行kalibr

    一些命令 docker images sudo docker run it kalibr latest sudo docker run it v local path docker path respository bin bash sud
  • 机器人避障规划算法之VFH系列算法研究现状

    机器人路径规划算法可以分为全局路径规划与局部路径规划 xff0c 全局规划算法一般需要地图信息作为先验知识 xff0c 而局部规划算法利用传感器探测环境信息避开障碍物 常用的全局算法算法有可视图法 xff0c 栅格地图法 xff0c 智能算
  • Windows配置ArUco

    windows10 vs2019 opencv3 4 6 注意 xff0c 一定要选择与opencv版本一样的opencv contrib 进行编译 xff0c 否则将会出现错误 xff0c 有很多的工程不能编译通过 xff0c 不能产生相
  • ArUco估计位姿原理

    ArUco使用 PnP OpenCV aruco 校准相机 Camera Calibration Demo 使用opencv的aruco库进行位姿估计 include lt opencv2 core core hpp gt include
  • 传递函数极点与微分方程的解

    如何解微分方程 setting y 61 e rx xff0c 点睛之笔
  • MPC控制

    基于状态空间模型的控制 模型预测控制 xff08 MPC xff09 简介 对基于状态空间模型的控制理解得很到位 在这里我重点讲解一下状态空间 模型 那么什么是状态 xff1f 输出是不是也是状态的一种 xff1f 对的 xff0c 输出也
  • @卡尔曼滤波理解

    Kalman Filter For Dummies 翻译 如何用卡尔曼滤波算法求解电池SOC xff08 基础篇 xff09 转载留存 卡尔曼滤波算法详细推导 这一篇对预备知识的介绍还是很好的 xff0c 过程与原理讲解也很到位 xff0c
  • 全景避障、VIO

    VINS Mono代码分析与总结 完整版 单目与IMU的融合可以有效解决单目尺度不可观测的问题 鱼眼摄像头SLAM xff1a PAN SLAM 全景相机SLAM 原论文 xff1a Panoramic SLAM from a multip
  • CAN总线-ACK应答机制分析

    1 xff1a 应答场定义 应答场长度为 2 个位 xff0c 包含应答间隙 xff08 ACK SLOT xff09 和应答界定符 xff08 ACK DELIMITER xff09 在应答场里 xff0c 发送站发送两个 隐性 位 当接
  • 树莓派4b 引脚图

    树莓派 4B 详细资料
  • 控制~线性系统~的能控性和能观性

    现控笔记 xff08 四 xff09 xff1a 能控性和能观性 能控性 xff1a 是控制作用u t 支配系统的状态向量x t 的能力 xff1b 回答u t 能否使x t 作任意转移的问题 能观性 xff1a 是系统的输出y t 反映系
  • 创建功能包

    创建功能包 xff1a catkin create pkg 在Amos WS src路径下 xff0c 打开控制台输入catkin create pkg my package std msgs rospy roscpp 创建一个名为my p
  • SLAM算法

    一 概述 Simultaneous Localization and Mapping SLAM 原本是Robotics领域用来做机器人定位的 xff0c 最早的SLAM算法其实是没有用视觉camera的 xff08 Robotics领域一般
  • 激光雷达入门

    转载自 xff1a https zhuanlan zhihu com p 33792450 前言 上一次的分享里 xff0c 我介绍了一个重要的感知传感器 摄像机 摄像机作为视觉传感器 xff0c 能为无人车提供丰富的感知信息 但是由于本身

随机推荐

  • 【超详细】韦东山:史上最全嵌入式Linux学习路线图

    我是1999年上的大学 xff0c 物理专业 在大一时 xff0c 我们班里普遍弥漫着对未来的不安 xff0c 不知道学习了物理后出去能做什么 你当下的经历 当下的学习 xff0c 在未来的一天肯定会影响到你 毕业后我们也各自找到了自己的职
  • ArUco码辅助定位——计算机视觉

    使用USB网络摄像头和ROS跟踪ArUco Markers
  • 基于D435i的点云重建

    Task 采用D435i采集深度图和RGB图像 xff0c 进行点云重建和聚类 1 xff09 解析Bag数据 xff1a import os import cv2 import numpy as np import rosbag from
  • vncviewer黑屏问题解决

    最近在重启服务器后 xff0c 用vnc进行远程桌面连接时 xff0c vnc能够连上 xff0c 或有提示错误 xff0c 或无提示错误 xff0c 但显示黑屏 在网上搜索了甚久 xff0c 各种google xff0c 各种baidu
  • Unbuntu 系统及VNC Viewer显示中文

    一行命令搞定 xff1a apt get install ttf wqy zenhei
  • 在嵌入式Linux系统上安装打印机

    简介 xff1a 在Linux环境中安装打印机 xff0c 通常是cups ghostscript等 xff0c 但体积通常很大 xff0c 几十兆 在我应用的环境 xff0c 要求打印模块不大于5M xff0c 在网上搜索的方案是将cup
  • 深度学习环境搭建:win10+GTX1060 + tensorflow1.5+keras+cuda9.0+cudnn7

    2018年 2月8日下午 xff0c 开始搭建环境 我新买了联想Y720笔记本电脑一台 xff0c 希望用它来开展深度学习的探索 根据之前的一点点经验 xff0c 搭建深度学习的环境 本篇博客主要记录的是流程 xff0c 不提供相关数据的下
  • Linux C/C++面试题汇总

    Linux C C 43 43 面试题汇总 前言计算机基础程序的内存空间进程和线程相关 关键字conststaticvolatile C C 43 43 指针 前言 最近面试的比较多 xff0c 看了很多关于面试的内容 xff0c 有些平时
  • NVIDIA TX2--3--NVIDIA Jetson TX2 查看系统版本参数状态及重要指令

    Yolov 1 TX2上用YOLOv3训练自己数据集的流程 VOC2007 TX2 GPU Yolov 2 一文全面了解深度学习性能优化加速引擎 TensorRT Yolov 3 TensorRT中yolov3性能优化加速 xff08 基于
  • freertos之timer浅析

    背景 freertos的定时器与我所见得到其他RTOS不一样 xff0c 我知道的ucosii是在每次tick 43 43 的时候会检查定时器链表 xff0c smc rtos也是这样做的 xff0c rtt没看过源码不清楚 xff0c 而
  • vins-fusion gps融合相关总结

    1 简介 xff1a VINS Fusion在VINS Mono的基础上 xff0c 添加了GPS等可以获取全局观测信息的传感器 xff0c 使得VINS可以利用全局信息消除累计误差 xff0c 进而减小闭环依赖 相比于局部传感器 xff0
  • vins-mono里的坐标系

    vins mono里主要涉及三个坐标系 xff1a word坐标系 xff0c body坐标系即IMU帧坐标系 xff0c cam坐标系即相机帧坐标系 对于单目系统而言 xff0c 初始化时就会确定世界坐标系 首先进行纯视觉初始化 SFM
  • 华三交换机配置telnet远程登录和http、https登录

    1 配置管理IP地址 lt H3C gt system view 进入系统视图 H3C int vlan 1 进入管理VLAN1 H3C Vlan interface1 ip address 1 1 1 1 24 配置默认管理IP地址 H3
  • C——char(字符串)转int

    有时候需要对输入的数字进行计算之类的操作 xff0c 这时候需要将char转int类型 char是一个单独字节 xff0c 可以保存一个本地字符集的内容的类型 一般使用char 的格式来使用 int就是一个范围较小的无符号整数类型 注意 x
  • Linux设备驱动——第三章字符驱动

    当对幸福的憧憬过于急切 xff0c 那痛苦就在人的心灵深处升起 加缪 本章的目的是编写一个完整的字符设备驱动 我们开发一个字符驱动是因为这一类适合大部分简单的硬件设备 字符驱动也比块驱动易于理解 本章的最终目的是编写一个模块化的字符驱动 x
  • FreeRTOS(一)系统时钟和中断

    RTOS系统运行必需要有时钟 xff0c FreeRTOS可以选择SysTick或TIM作为时钟源 本文以再stm32f1上的移植介绍 选择SysTick需要在FreeRTOSConfig h中取消SysTick Handler 函数的映射
  • 对于USB Bulk通信发送0包的理解

    写Device USB驱动的时候 xff0c 当Bulk送信发送的数据长度恰好是wMaxPacketSize的整数倍时 xff0c 是否应该发送0包的问题搞得我焦头烂额 查找了好多资料 xff0c 有的说要加 xff0c 这是USB协议的一
  • upload漏洞专题

    一 upload上传绕过专题 后缀检验绕过 1 黑名单检测绕过 1 上传文件重命名 span class token comment 由于只有后缀是可控的 span 所以常见的后缀为php中 php2 php3 php4 php5 phtm
  • Pony语言学习(七)——表达式(Expressions)语法(单篇向)

    一 字面量 xff08 Literals xff09 xff08 一 xff09 Bool值 xff1a 没啥要说的 xff0c 就是true和false x1f44a xff08 二 xff09 数值 xff08 Numeric Lite
  • Pony语言学习(八):引用能力(Reference Capabilities)

    xff08 如果你有更好的翻译 xff0c 请务必联系我 我们需要和Rust术语做到翻译看齐 xff09 一 总览 xff08 特译 xff1a https tutorial ponylang io reference capabiliti