当前位置: 首页 > news >正文

Kotlin基础——DSL

DSL(领域特定语言)

常见的DSL就是SQL和正则表达式,用于操作数据库和文本字符串,Kotlin DSL通常为嵌套的Lambda表达式或链式方法,如

  • https://github.com/gradle/gradle-script-kotlin 用于构建Gradle脚本
  • https://github.com/JetBrains/Exposed 用于操作数据库
  • https://github.com/Kotlin/kotlinx.html 用于生成HTML

带接收者的Lambda和扩展函数类型

对于普通的生成字符串函数,需要在Lambda中使用it指向StringBuilder实例

fun buildString(builderAction: (StringBuilder) -> Unit): String {val sb = StringBuilder()builderAction(sb)return sb.toString()
}val s = buildString {it.append("Hello ")it.append("World")
}println(s)

转换为带接收者的Lambda可通过this或直接调用方法

fun buildString(builderAction: StringBuilder.() -> Unit): String {val sb = StringBuilder()sb.builderAction()return sb.toString()
}val s = buildString {this.append("Hello ")append("World")
}println(s)

具体做法是使用扩展函数类型取代普通函数类型来声明参数的类型,将函数类型签名中的一个参数移到括号前面,并用一个.分割

(StringBuilder) -> Unit		//一个接收StringBuild参数、无返回值的函数
StringBuilder.() -> Unit	//将(接收者对象)参数往前移

也声明一个扩展函数类型的变量

val appendExcl: StringBuilder.() -> Unit = { this.append("!") }
val sb = StringBuilder("Hi")
sb.appendExcl()
println(sb)

Kotlin标准库中的apply和with就是利用扩展函数类型

public inline fun <T> T.apply(block: T.() -> Unit): T {.....block()			//apply的接收者被当作lambda的接收者return this		//返回接收者
}public inline fun <T, R> with(receiver: T, block: T.() -> R): R {......return receiver.block()		//返回调用Lambda的结果
}

HTML构建器

用于Html的Kotlin DSL叫做HTML构建器,其是类型安全的

open class Tag(val name: String) {private val children = mutableListOf<Tag>()protected fun <T : Tag> doInit(child: T, init: T.() -> Unit) {child.init()children.add(child)}override fun toString() = "<$name>${children.joinToString("")}</$name>"
}fun table(init: TABLE.() -> Unit) = TABLE().apply(init)class TABLE : Tag("table") {fun tr(init: TR.() -> Unit) = doInit(TR(), init)
}class TR : Tag("tr") {fun td(init: TD.() -> Unit) = doInit(TD(), init)
}class TD : Tag("td")fun createTable() =table {tr {td {}}}

调用

println(createTable())<table><tr><td></td></tr></table>

invoke约定

重写invoke()可以让对象像函数一样调用,p(1)会被编译成p.invoke(1)

class Person(val name: String) {operator fun invoke(age: Int) {println("$name,$age")}
}val p = Person("A")
p(1)

Gradle中的DSL

class DependencyHandler {fun compile(coordinate: String) {println("add dependency on $coordinate")}operator fun invoke(body: DependencyHandler.() -> Unit) {body()}
}val dependencies = DependencyHandler()dependencies.compile("com.demo.demo-lib:1.0.0")dependencies {compile("com.demo.demo-lib:1.0.0")
}

中缀调用的DSL

对于下面的DSL

infix fun <T> T.should(matcher: Matcher<T>) = matcher.test(this)interface Matcher<T> {fun test(value: T)
}class startWith(val prefix: String) : Matcher<String> {override fun test(value: String) {if (!value.startsWith(prefix)) {throw AssertionError("$value does not start with $prefix")}}

可使用中缀调用

"kotlin" should startWith("kot")"kotlin".should(startWith("kot"))

还可利用包装类进一步简化,利用obetject对象选择不同类型的should()重载方法

object start
infix fun String.should(x: start): StartWrapper = StartWrapper(this)
class StartWrapper(val value: String) {infix fun with(prefix: String) =if (!value.startsWith(prefix))throw AssertionError("$value does not start with $prefix")elseprintln("success")
}
"kotlin" should start with ("kot")"kotlin".should(start).with("kot")

基本数据类型上定义扩展

val Int.days: Periodget() = Period.ofDays(this)val Period.ago: LocalDateget() = LocalDate.now() - thisval Period.fromNow: LocalDateget() = LocalDate.now() + this

通过扩展函数实现获取一天前和一天后的日期

println(1.days.ago)
println(1.days.fromNow)

相关文章:

Kotlin基础——DSL

DSL&#xff08;领域特定语言&#xff09; 常见的DSL就是SQL和正则表达式&#xff0c;用于操作数据库和文本字符串&#xff0c;Kotlin DSL通常为嵌套的Lambda表达式或链式方法&#xff0c;如 https://github.com/gradle/gradle-script-kotlin 用于构建Gradle脚本https://gith…...

《Docker 简易速速上手小册》第4章 Docker 容器管理(2024 最新版)

文章目录 4.1 容器生命周期管理4.1.1 重点基础知识4.1.2 重点案例&#xff1a;启动并管理 Python Flask 应用容器4.1.3 拓展案例 1&#xff1a;调试运行中的容器4.1.4 拓展案例 2&#xff1a;优雅地停止和清理容器 4.2 容器数据管理与持久化4.2.1 重点基础知识4.2.2 重点案例&a…...

【人脸朝向识别与分类预测】基于PNN神经网络

课题名称&#xff1a;基于PNN神经网络的人脸朝向识别分类 版本日期&#xff1a;2024-02-20 运行方式&#xff1a;直接运行PNN0503.m文件 代码获取方式&#xff1a;私信博主或 QQ:491052175 模型描述&#xff1a; 采集到一组人脸朝向不同角度时的图像&#xff0c;图像来自不…...

【Python笔记-设计模式】组合模式

一、说明 组合模式是一种结构型设计模式&#xff0c; 你可以使用它将对象组合成树状结构&#xff0c; 并且能像使用独立对象一样使用它们。 (一) 解决问题 处理树形结构&#xff1a;可以很好地处理树形结构的数据&#xff0c;使得用户可以统一对待单个对象和对象组合。统一接…...

51单片机学习(5)-----蜂鸣器的介绍与使用

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 目录 一. 蜂鸣器的介绍 1.蜂鸣器介绍 2.压电式蜂鸣器 &#xff08;无源…...

-bash: /root/.ssh/authorized_keys: Read-only file system

问题背景 由于跳板机不支持 ssh-copy-id 命令&#xff0c;为了配置免密登录&#xff0c;考虑在服务器上手动使用 cat 命令写入跳板机公钥 cat <<EOL >> ~/.ssh/authorized_keys [Your public key] EOL但却出现了以下错误 -bash: /root/.ssh/authorized_keys: Re…...

3,设备无关位图显示

建立了一个类Dib Dib.h #pragma once #include “afx.h” class CDib :public CObject { public: CDib(); ~CDib(); char* GetFileName(); BOOL IsValid(); DWORD GetSize(); UINT GetWidth(); UINT GetHeight(); UINT GetNumberOfColors(); RGBQUAD* GetRGB(); BYTE* GetDat…...

转前端了!!

大家好&#xff0c;我是冰河~~ 没错&#xff0c;为了更好的设计和开发分布式IM即时通讯系统&#xff0c;也为了让大家能够直观的体验到分布式IM即时通讯系统的功能&#xff0c;冰河开始转战前端了。也就是说&#xff0c;整个项目从需求立项到产品设计&#xff0c;从架构设计到…...

RESTful API如何使用它构建 web 应用程序。

链接&#xff1a;华为机考原题 RESTful API(Representational State Transfer)是一种基于网络的软件架构风格&#xff0c;用于设计和访问网络资源。它是一种轻量级、灵活、可扩展的架构&#xff0c;常用于构建Web应用程序和服务。 使用RESTful API构建Web应用程序的步骤如下&…...

现在学Oracle是49年入国军么?

今天周末&#xff0c;不聊技术&#xff0c;聊聊大家说的最多的一个话题 先说明一下&#xff0c;防止挨喷&#x1f606; 本人并不是职业dba&#xff0c;对数据库就是爱好&#xff0c;偶尔兼职&#xff0c;以下仅个人观点分析&#xff0c;如有不同观点请轻喷&#xff0c;哈哈&…...

【回溯】组合问题||

给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 示例 1: 输入: candidates [10,1,2,7,6,…...

【c语言】字符函数和字符串函数(下)

前言 书接上回 【c语言】字符函数和字符串函数(上) 上一篇讲解的strcpy、strcat、strcmp函数的字符串长度是不受限制的 而本篇strncpy、strncat、strcnmp函数的字符串长度是受限制的 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;…...

基于Java的艺培管理解决方案

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…...

Python算法题集_实现 Trie [前缀树]

Python算法题集_实现 Trie [前缀树] 题208&#xff1a;实现 Trie (前缀树)1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【定义数据类默认字典】2) 改进版一【初始化字典无额外类】3) 改进版二【字典保存结尾信息无额外类】 4. 最优算法5. 相关…...

pytorch简单新型模型测试参数

import torch from torch.nn import Conv2d,MaxPool2d,Sequential,Flatten,Linear import torchvision import torch.optim.optimizer from torch.utils.data import DataLoader,dataset from torch import nn import torch.optim.optimizer# 建模 model nn.Linear(2,1)#损失 …...

Unity中URP下实现水体(水面高光)

文章目录 前言一、实现高光反射原理1、原理&#xff1a;2、公式&#xff1a; 二、实现1、定义 _SpecularColor 作为高光反射的颜色2、定义 _SpecularIntensity 作为反射系数&#xff0c;控制高光反射的强度3、定义 _Smoothness 作为高光指数&#xff0c;用于模型高光范围4、模拟…...

26.HarmonyOS App(JAVA)列表对话框

列表对话框的单选模式&#xff1a; //单选模式 // listDialog.setSingleSelectItems(new String[]{"第1个选项","第2个选项"},1);//单选 // listDialog.setOnSingleSelectListener(new IDialog.ClickedListener() { // Override …...

五种主流数据库:常用字符函数

SQL 字符函数用于字符数据的处理&#xff0c;例如字符串的拼接、大小写转换、子串的查找和替换等。 本文比较五种主流数据库常用数值函数的实现和差异&#xff0c;包括 MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLite。 字符函数函数功能MySQLOracleSQL ServerPostgreSQ…...

软考笔记--企业资源规划和实施

企业资源是指企业业务活动和战略运营的事物&#xff0c;包括人、财和物&#xff0c;也包括信息资源&#xff0c;同时也包括企业的内部和外部资源。企业资源可以归纳为物流&#xff0c;资金流和信息流。企业资源规划&#xff08;ERP&#xff09;是只建立在信息技术基础上&#x…...

React歌词滚动效果(跟随音乐播放时间滚动)

首先给audio绑定更新时间事件 const updateTime e > {console.log(e.target.currentTime)setCurrentTime(e.target.currentTime);};<audiosrc{currentSong.url}ref{audio}onCanPlay{ready}onEnded{end}onTimeUpdate{updateTime}></audio>当歌曲播放时间改变的时…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...