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

跟着 Lua 5.1 官方参考文档学习 Lua (6)

文章目录

    • 2.11 – Coroutines

2.11 – Coroutines

Lua supports coroutines, also called collaborative multithreading. A coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends its execution by explicitly calling a yield function.

You create a coroutine with a call to coroutine.create. Its sole argument is a function that is the main function of the coroutine. The create function only creates a new coroutine and returns a handle to it (an object of type thread); it does not start the coroutine execution.

When you first call coroutine.resume, passing as its first argument a thread returned by coroutine.create, the coroutine starts its execution, at the first line of its main function. Extra arguments passed to coroutine.resume are passed on to the coroutine main function. After the coroutine starts running, it runs until it terminates or yields.

A coroutine can terminate its execution in two ways: normally, when its main function returns (explicitly or implicitly, after the last instruction); and abnormally, if there is an unprotected error.

In the first case, coroutine.resume returns true, plus any values returned by the coroutine main function. In case of errors, coroutine.resume returns false plus an error message.

A coroutine yields by calling coroutine.yield. When a coroutine yields, the corresponding coroutine.resume returns immediately, even if the yield happens inside nested function calls (that is, not in the main function, but in a function directly or indirectly called by the main function).

In the case of a yield, coroutine.resume also returns true, plus any values passed to coroutine.yield. The next time you resume the same coroutine, it continues its execution from the point where it yielded, with the call to coroutine.yield returning any extra arguments passed to coroutine.resume.

Like coroutine.create, the coroutine.wrap function also creates a coroutine, but instead of returning the coroutine itself, it returns a function that, when called, resumes the coroutine. Any arguments passed to this function go as extra arguments to coroutine.resume. coroutine.wrap returns all the values returned by coroutine.resume, except the first one (the boolean error code). Unlike coroutine.resume, coroutine.wrap does not catch errors; any error is propagated to the caller.

As an example, consider the following code:

     function foo (a)print("foo", a)return coroutine.yield(2*a)endco = coroutine.create(function (a,b)print("co-body", a, b)local r = foo(a+1)print("co-body", r)local r, s = coroutine.yield(a+b, a-b)print("co-body", r, s)return b, "end"end)print("main", coroutine.resume(co, 1, 10))print("main", coroutine.resume(co, "r"))print("main", coroutine.resume(co, "x", "y"))print("main", coroutine.resume(co, "x", "y"))

When you run it, it produces the following output:

     co-body 1       10foo     2main    true    4co-body rmain    true    11      -9co-body x       ymain    true    10      endmain    false   cannot resume dead coroutine

补充:

例子:生产者和消费者

producer = coroutine.create(function ()while true dolocal x = io.read()send(x)endend
)function consumer ()while true dolocal x = receive()io.write(x, "\n")end
endfunction receive ()local status, value = coroutine.resume(producer)return value
endfunction send (x)coroutine.yield(x)
endconsumer()

We can extend this design with filters, which are tasks that sit between the producer and the consumer doing some kind of transformation in the data. A filter is a consumer and a producer at the same time, so it resumes a producer to get new values and yields the transformed values to a consumer.

例子:管道和过滤器

function receive (prod)local status, value = coroutine.resume(prod)return value
endfunction send (x)coroutine.yield(x)
endfunction producer ()return coroutine.create(function ()while true dolocal x = io.read() -- produce new valuesend(x)endend)
endfunction filter (prod)return coroutine.create(function ()for line = 1, math.huge dolocal x = receive(prod) -- get new valuex = string.format("%5d %s", line, x)send(x) -- send it to consumerendend)
endfunction consumer (prod)while true dolocal x = receive(prod)io.write(x, "\n")end
endp = producer()
f = filter(p)
consumer(f)

If you thought about Unix pipes after reading the previous example, you are not alone. After all, coroutines are a kind of (non-preemptive) multithreading. While with pipes each task runs in a separate process, with coroutines each task runs in a separate coroutine. Pipes provide a buffer between the writer (producer) and the reader (consumer) so there is some freedom in their relative
speeds. This is important in the context of pipes, because the cost of switching between processes is high. With coroutines, the cost of switching between tasks is much smaller (roughly the same as a function call), so the writer and the reader can run hand in hand.



补充:Iterators and the Generic for

7.1 Iterators and Closures

An iterator is any construction that allows you to iterate over the elements of a collection. In Lua, we typically represent iterators by functions: each time we call the function, it returns the “next” element from the collection.

Every iterator needs to keep some state between successive calls, so that it knows where it is and how to proceed from there. Closures provide an excellent mechanism for this task. Remember that a closure is a function that accesses one or more local variables from its enclosing environment. These variables keep their values across successive calls to the closure, allowing the closure to remember where it is along a traversal. Of course, to create a new closure we must also create its non-local variables. Therefore, a closure construction typically involves two functions: the closure itself and a factory, the function that creates the closure.

As an example, let us write a simple iterator for a list. Unlike ipairs, this iterator does not return the index of each element, only its value:

function values(t)local i = 0return function()i = i + 1; return t[i]end
end

In this example, values is the factory. Each time we call this factory, it creates a new closure (the iterator itself). This closure keeps its state in its external variables t and i. Each time we call the iterator, it returns a next value from the list t. After the last element the iterator returns nil, which signals the end of the iteration.

We can use this iterator in a while loop:

t = { 10, 20, 30 }
iter = values(t)       -- creates the iterator
while true dolocal element = iter() -- calls the iteratorif element == nil then break endprint(element)
end

However, it is easier to use the generic for. After all, it was designed for this kind of iteration:

t = { 10, 20, 30 }
for element in values(t) doprint(element)
end

The generic for does all the bookkeeping for an iteration loop: it keeps the iterator function internally, so we do not need the iter variable; it calls the iterator on each new iteration; and it stops the loop when the iterator returns nil. (In the next section we will see that the generic for does even more than that.)

例子:Iterator to traverse all words from the input file

function allwords()local line = io.read()                    -- current linelocal pos = 1                             -- current position in the linereturn function()                         -- iterator functionwhile line do                         -- repeat while there are lineslocal s, e = string.find(line, "%w+", pos)if s then                         -- found a word?pos = e + 1                   -- next position is after this wordreturn string.sub(line, s, e) -- return the wordelseline = io.read()              -- word not found; try next linepos = 1                       -- restart from first positionendendreturn nil -- no more lines: end of traversalend
endfor word in allwords() doprint(word)
end

A for statement like

     for var_1, ···, var_n in explist do block end

is equivalent to the code:

     dolocal f, s, var = explistwhile true dolocal var_1, ···, var_n = f(s, var)var = var_1if var == nil then break endblockendend

We call the first variable var_1 in the list the control variable. Its value is never nil during the loop, because when it becomes nil the loop ends.

The first thing the for does is to evaluate the expressions after the in. These expressions should result in the three values kept by the for: the iterator function, the invariant state, and the initial value for the control variable. Like in a multiple assignment, only the last (or the only) element of the list【explist】 can result in more than one value; and the number of values is adjusted to three, extra values being discarded or nils added as needed.

(When we use simple iterators, the factory returns only the iterator function, so the invariant state and the control variable get nil.)

After this initialization step, the for calls the iterator function with two arguments: the invariant state and the control variable. (From the standpoint of the for construct, the invariant state has no meaning at all. The for only passes the state value from the initialization step to the calls to the iterator function.) Then the for assigns the values returned by the iterator function to the variables declared by its variable list. If the first value returned (the one assigned to the control variable) is nil, the loop terminates. Otherwise, the for executes its body and calls the iteration function again, repeating the process.

7.3 Stateless Iterators

As the name implies, a stateless iterator is an iterator that does not keep any state by itself. Therefore, we may use the same stateless iterator in multiple loops, avoiding the cost of creating new closures.

For each iteration, the for loop calls its iterator function with two arguments: the invariant state and the control variable. A stateless iterator generates the next element for the iteration using only these two values.

例子:ipairs 和 pairs 函数

local function iter(a, i)i = i + 1local v = a[i]if v thenreturn i, vend
endfunction ipairs(a)return iter, a, 0
endlocal a = {"a", "b", "c" ,"d"}
for i,v in ipairs(a) doprint(i, v)
end-- The call next(t,k), where k is a key of the table t, returns a next key in the
-- table, in an arbitrary order, plus the value associated with this key as a second
-- return value. The call next(t,nil) returns a first pair. When there are no more
-- pairs, next returns nil.
function pairs(t)return next, t, nil
endlocal t = {a = 1, b = 2, c = 3}
for k,v in pairs(t) doprint(k, v)
end

7.4 Iterators with Complex State

Frequently, an iterator needs to keep more state than fits into a single invariant state and a control variable. The simplest solution is to use closures. An alternative solution is to pack all it needs into a table and use this table as the invariant state for the iteration. Using a table, an iterator can keep as much data as it needs along the loop. Moreover, it can change this data as it goes.
Although the state is always the same table (and therefore invariant), the table contents change along the loop. Because such iterators have all their data in the state, they typically ignore the second argument provided by the generic for (the iterator variable).

As an example of this technique, we will rewrite the iterator allwords, which traverses all the words from the current input file. This time, we will keep its state using a table with two fields: line and pos.

例子:重写 allwords 迭代器

local iterator -- to be defined later
function allwords()local state = { line = io.read(), pos = 1 }return iterator, state
endfunction iterator(state)while state.line do -- repeat while there are lines-- search for next wordlocal s, e = string.find(state.line, "%w+", state.pos)if s then -- found a word?-- update next position (after this word)state.pos = e + 1return string.sub(state.line, s, e)else               -- word not foundstate.line = io.read() -- try next line...state.pos = 1  -- ... from first positionendendreturn nil -- no more lines: end loop
endfor word in allwords() doprint(word)
end

Whenever possible, you should try to write stateless iterators, those that keep all their state in the for variables. With them, you do not create new objects when you start a loop. If you cannot fit your iteration into this model, then you should try closures. Besides being more elegant, typically a closure is more efficient than an iterator using tables is: first, it is cheaper to create a closure than a table; second, access to non-local variables is faster than access to table fields. Later we will see yet another way to write iterators, with coroutines. This is the most powerful solution, but a little more expensive.


补充:9.3 Coroutines as Iterators

We can see loop iterators as a particular example of the producer–consumer pattern: an iterator produces items to be consumed by the loop body. Therefore, it seems appropriate to use coroutines to write iterators. Indeed, coroutines provide a powerful tool for this task. Again, the key feature is their ability to turn upside-down the relationship between caller and callee. With this feature, we can write iterators without worrying about how to keep state between successive
calls to the iterator.

To illustrate this kind of use, let us write an iterator to traverse all permutations of a given array.

例子:生成排列

function printResult (a)for i = 1, #a doio.write(a[i], " ")endio.write("\n")
endfunction permgen (a, n)n = n or #a -- default for ’n’ is size of ’a’if n <= 1 then -- nothing to change?printResult(a)elsefor i=1,n do-- put i-th element as the last onea[n], a[i] = a[i], a[n]-- generate all permutations of the other elementspermgen(a, n - 1)-- restore i-th elementa[n], a[i] = a[i], a[n]endend
endpermgen ({1,2,3,4})

改写成协程的版本:

function printResult (a)for i = 1, #a doio.write(a[i], " ")endio.write("\n")
endfunction permgen (a, n)n = n or #a -- default for ’n’ is size of ’a’if n <= 1 then -- nothing to change?coroutine.yield(a)elsefor i=1,n do-- put i-th element as the last onea[n], a[i] = a[i], a[n]-- generate all permutations of the other elementspermgen(a, n - 1)-- restore i-th elementa[n], a[i] = a[i], a[n]endend
endfunction permutations (a)local co = coroutine.create(function () permgen(a) end)return function () -- iteratorlocal code, res = coroutine.resume(co)return resend
endfor p in permutations{"a", "b", "c"} doprintResult(p)
end

The permutations function uses a common pattern in Lua, which packs a call to resume with its corresponding coroutine inside a function. This pattern is so common that Lua provides a special function for it: coroutine.wrap. Like create, wrap creates a new coroutine. Unlike create, wrap does not return the coroutine itself; instead, it returns a function that, when called, resumes the
coroutine. Unlike the original resume, that function does not return an error code as its first result; instead, it raises the error in case of error. Using wrap, we can write permutations as follows:

function permutations(a)return coroutine.wrap(function() permgen(a) end)
end

Usually, coroutine.wrap is simpler to use than coroutine.create. It gives us exactly what we need from a coroutine: a function to resume it. However, it is also less flexible. There is no way to check the status of a coroutine created with wrap. Moreover, we cannot check for runtime errors.

例子:使用协程下载多个文件

local socket = require "socket"function receive(connection)connection:settimeout(0) -- do not blocklocal s, status, partial = connection:receive(2 ^ 10)if status == "timeout" thencoroutine.yield(connection)endreturn s or partial, status
endfunction download(host, file)local c = assert(socket.connect(host, 80))local count = 0 -- counts number of bytes readc:send("GET " .. file .. " HTTP/1.0\r\n\r\n")while true dolocal s, status, partial = receive(c)count = count + #(s or partial)if status == "closed" then break endendc:close()print(file, count)
endthreads = {} -- list of all live threads
function get(host, file)-- create coroutinelocal co = coroutine.create(function()download(host, file)end)-- insert it in the listtable.insert(threads, co)
endfunction dispatch()local i = 1local connections = {}while true doif threads[i] == nil then -- no more threads?if threads[1] == nil then break endi = 1                 -- restart the loopconnections = {}endlocal status, res = coroutine.resume(threads[i])if not res then -- thread finished its task?table.remove(threads, i)else            -- time outi = i + 1connections[#connections + 1] = resif #connections == #threads then -- all threads blocked?-- wait for any of these connections to change statussocket.select(connections)endendend
endhost = "www.w3.org"
get(host, "/TR/html401/html40.txt")
get(host, "/TR/2002/REC-xhtml1-20020801/xhtml1.pdf")
get(host, "/TR/REC-html32.html")
get(host, "/TR/2000/REC-DOM-Level-2-Core-20001113/DOM2-Core.txt")dispatch()

需要安装 luasocket 库

luarocks install luasocket

相关文章:

跟着 Lua 5.1 官方参考文档学习 Lua (6)

文章目录 2.11 – Coroutines 2.11 – Coroutines Lua supports coroutines, also called collaborative multithreading. A coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends i…...

Spring Cloud — Hystrix 服务隔离、请求缓存及合并

Hystrix 的核心是提供服务容错保护&#xff0c;防止任何单一依赖耗尽整个容器的全部用户线程。使用舱壁隔离模式&#xff0c;对资源或失败单元进行隔离&#xff0c;避免一个服务的失效导致整个系统垮掉&#xff08;雪崩效应&#xff09;。 1 Hystrix监控 Hystrix 提供了对服务…...

加油站(力扣134)

既然每一个加油站都有对应的加油量和耗油量&#xff0c;我们不妨计算一下每个加油站的汽油净增量。如果每个加油站净增量之和不为负数&#xff0c;则说明一定可以找到唯一的起始点。那我们该如何找到这个起始点呢&#xff1f;我们设置最开始的起点为第0个加油站&#xff0c;接着…...

科普:你的笔记本电脑中有三个IP:127.0.0.1、无线网 IP 和局域网 IP;两个域名:localhost和host.docker.internal

三个IP 你的笔记本电脑中有三个IP&#xff1a;127.0.0.1、无线网 IP 和局域网 IP。 在不同的场景下&#xff0c;需要选用不同的 IP 地址&#xff0c;如下为各自的特点及适用场景&#xff1a; 127.0.0.1&#xff08;回环地址&#xff09; 特点 127.0.0.1 是一个特殊的 IP 地…...

Golang 相关的github 开源项目

1. pan-light url: http://github.com/peterq/pan-lightstar: 12.1kfork: 2.5kwatch: 284 用Golang和Qt5编写的不限速版百度网盘。相比之前版本的百度网盘客户端&#xff0c;当前版本拥有更友好、便捷的图形界面&#xff0c;体量更轻&#xff0c;便于使用&#xff0c;只需下载…...

数据结构《图》

数据结构《图论》 图的性质 一、无向图&#xff08;Undirected Graph&#xff09; 定义 由一组顶点&#xff08;Vertex&#xff09;和一组无向边&#xff08;Edge&#xff09;构成。 每条无向边用一条无方向的线段连接两个顶点&#xff0c;记为 ( (u, v) )&#xff0c;其中…...

WPF实现打印机控制及打印

在WPF中实现打印机控制和打印功能&#xff0c;通常需要使用System.Printing命名空间中的类来管理打印机和打印任务。以下是一个简单的示例&#xff0c;展示如何在WPF应用程序中实现打印功能。 1. 添加必要的引用 首先&#xff0c;确保在项目中引用了System.Printing命名空间。…...

springboot系列十四: 注入Servlet, Filter, Listener + 内置Tomcat配置和切换 + 数据库操作

文章目录 注入Servlet, Filter, Listener官方文档基本介绍使用注解方式注入使用RegistrationBean方法注入DispatcherServlet详解 内置Tomcat配置和切换基本介绍内置Tomcat配置通过application.yml完成配置通过类配置 切换Undertow 数据库操作 JdbcHikariDataSource需求分析应用…...

DeepSeek 助力 Vue 开发:打造丝滑的二维码生成(QR Code)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

从传统到轻量级5G:网络架构演变与优化路径

轻量级5G​​​​ 随着5G技术的不断发展&#xff0c;通信网络架构正经历着前所未有的变革。传统的5G核心网架构虽然在性能和容量方面表现出色&#xff0c;但在灵活性、部署效率以及成本控制方面却面临一些挑战。为了应对日益复杂的通信需求&#xff0c;轻量级5G核心网成为了一种…...

独立开发者如何寻找产品设计灵感

作为独立开发者&#xff0c;面对激烈的市场竞争和不断变化的用户需求&#xff0c;寻找优秀的产品设计灵感是至关重要的一步。以下是一篇关于独立开发者如何寻找产品设计灵感的教程&#xff0c;希望能为你提供一些有益的指导。 一、观察日常生活 1.1 关注身边的小问题 在日常生…...

技术解析 | 适用于TeamCity的Unreal Engine支持插件,提升游戏构建效率

龙智是JetBrains授权合作伙伴、Perforce授权合作伙伴&#xff0c;为您提供TeamCity、Perforce Helix Core等热门的游戏开发工具及一站式服务 TeamCity 是游戏开发的热门选择&#xff0c;大家选择它的原因包括支持 Perforce、可以进行本地安装&#xff0c;并提供了多种配置选项。…...

uniapp h5端和app端 使用 turn.js

前提:添加页后,添加页与当前页会重叠在一起,不知道为什么,没有找到解决办法 1.h5端 <template><view class"container"><view id"flipbook"><view class"page page1">Page 1</view><view class"page pag…...

智慧校园系统在学生学习与生活中的应用

随着科技的快速发展&#xff0c;智慧校园系统逐渐成为现代教育不可或缺的一部分。它整合了先进的信息技术、物联网技术以及人工智能等&#xff0c;旨在构建一个全面、智能、个性化的学习与生活环境。对于学生而言&#xff0c;这一系统不仅能够极大地提高学习效率&#xff0c;还…...

umi: valtio的使用

一、基本用法 import { proxy, useSnapshot } from umijs/max;// 1、定义数据 const state proxy({ count: 33 });export default () > {// 2、使用数据const snap useSnapshot(state);function increaseCount() {state.count 1;}return (<><h1>{snap.count}…...

什么是矩阵账号?如何高效运营tiktok矩阵账号

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌​‌‌​‌‌‌‍‌​‌​‌​​​‍‌​​‌​‌‌​‍‌​​​​‌‌​‍‌​‌​​‌‌‌‍‌​​‌‌​‌​‍‌​‌​​‌‌‌‍‌​‌‌‌​​‌‍‌‌​​‌‌‌​‍‌‌​​‌‌​​‍‌…...

C语言.h头文件的写法

头文件的内容 #ifndef __SEQUENCE_LIST_H // 定义以防止递归包含 #define __SEQUENCE_LIST_H // (1)、其它头文件 #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <stdbool.h> // (2)、宏定义(函数、变量、常量) // (3)、…...

【Day44 LeetCode】图论问题 Ⅱ

一、图论问题 Ⅱ 1、岛屿的最大面积 这题和上一篇博客求岛屿数量如出一辙&#xff0c;都是要找出所有岛屿&#xff0c;深度优先搜索代码如下&#xff1a; # include<iostream> # include<vector>using namespace std;int dfs(vector<vector<int>> …...

设计模式教程:责任链模式(Chain of Responsibility Pattern)

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种常用的设计模式&#xff0c;它属于行为型模式&#xff0c;主要解决的是多个对象处理一个请求时&#xff0c;如何解耦请求的发送者和接收者&#xff0c;以及如何将请求的处理职责分配给不同的对象。 1…...

java网络编程

计算机网络基础 网络编程的目的就是直接或间接地通过网络协议与其他计算机进行通信。 在 Java 语言中包含网络编程所需要的各种类&#xff0c;编程人员只需要创建这些类的对象&#xff0c;调用相应的方法&#xff0c;就可以进行网络应用程序的编写。 要进行网络程序的编写&am…...

计算机网络面试知识点总结

目录 1. 计算机网络的基本知识点2. OSI 七层模型3. TCP/IP 四层模型4. TCP 和 UDP4.1 TCP 协议4.2 TCP 流量控制4.3 TCP 拥塞控制4.4 TCP 三次握手4.5 TCP 四次挥手4.6 TCP 粘包问题4.7 TCP Socket交互流程4.8 UDP 协议以及和 TCP 协议的不同 5. HTTP协议5.1 HTTP 请求方法以及…...

ubuntu22.4搭建单节点es8.1

下载对应的包 elasticsearch-8.1.1-linux-x86_64.tar.gz 创建es租户 groupadd elasticsearc useradd elasticsearch -g elasticsearch -p elasticsearch chmod uw /etc/sudoers chmod -R elasticsearch:elasticsearch elasticsearch 修改配置文件 vim /etc/sysctl.conf vm…...

卷积与动态特征选择:重塑YOLOv8的多尺度目标检测能力

文章目录 1. YOLOv8的网络结构概述2. 添加注意力机制2.1 为什么添加注意力机制&#xff1f;2.2 如何将注意力机制集成到YOLOv8中&#xff1f;2.3 效果分析 3. C2f模块的集成3.1 C2f模块简介3.2 如何在YOLOv8中集成C2f模块&#xff1f;3.3 效果分析 4. 卷积操作的优化4.1 卷积操…...

【Altium Designer】差分对等长设置以及绕线

在Altium Designer 17中设置差分对的等差规则及绕等长操作&#xff0c;需结合规则配置与交互式布线工具完成。以下是详细操作步骤&#xff1a; 目录 一、差分对等差规则设置 1. 原理图端差分对定义 2. PCB端差分规则配置 二、差分对等长绕线操作 1. 差分对布线 2. 交互式…...

BFS 和 DFS(深度优先搜索、广度优先搜索)

深度优先搜索&#xff08;DFS&#xff09;和广度优先搜索&#xff08;BFS&#xff09;是两种常用的图遍历算法&#xff0c;用于解决图相关的问题。它们在搜索问题中具有广泛的应用&#xff0c;如路径搜索、连通性检测等。 以下是具体区别&#xff1a; &#xff08;图片引自&am…...

汽车免拆诊断案例 | 2013 款奔驰 S300L 车起步时车身明显抖动

故障现象  一辆2013款奔驰S300L车&#xff0c;搭载272 946发动机&#xff0c;累计行驶里程约为15万km。车主反映&#xff0c;将挡位置于D挡&#xff0c;稍微释放一点制动踏板&#xff0c;车辆蠕动时车身明显抖动&#xff0c;类似气缸失火时的抖动&#xff0c;又类似手动变速器…...

基于UnrealEngine(UE5)的太空探索

视频部分可参见&#xff1a;https://www.bilibili.com/video/BV1JWA8eSEVg/ 中国 天宫号 空间站 人造卫星可视化 星链卫星可视化 小行星分布及运动轨迹可视化 月球基地 可视化 八大行星轨道 太阳系宜居带可视化 阿波罗8号拍摄的地球升起 谷神星模型及轨迹可视化 星座可视化 十…...

HTML Application(hta)入门教程

简介 HTA是HTML Application的缩写&#xff0c;又称为HTML应用程序。 hta是一个可执行文件&#xff0c;双击可以直接运行 hta与html非常相似&#xff0c;可直接将文件后缀改为.hta来获得HTA格式的文件。 支持VBS和JavaScript html的权限被限制在网页浏览器内&#xff0c;只有操…...

IOS UITextField 无法隐藏键盘问题

设置UITextField 键盘按钮返回键为“完成”&#xff0c;即return key 设置done .m代码设置代理 //设置代理协议 UITextFieldDelegate&#xff0c; self.mobileTextField.delegate self; ///点击完成键隐藏键盘 - (BOOL)textFieldShouldReturn:(UITextField *)textField{//取…...

ES6箭头函数:基础与进阶指南

目录 引言 一、基础篇&#xff1a;核心语法与特性 1.1 语法革新 1.2 this绑定机制 二、进阶篇&#xff1a;深度特性解析 2.1 闭包中的this继承 2.2 限制与注意事项 三、实践指南&#xff1a;应用场景与陷阱规避 3.1 推荐使用场景 3.2 应避免的场景 四、性能考量 结语…...

AI赋能编程:PyCharm与DeepSeek的智能开发革命

在这个智能化的时代&#xff0c;人工智能技术正在深刻地改变着我们的工作方式&#xff0c;尤其是在编程领域。无论是初学者还是资深开发者&#xff0c;都希望借助更高效的工具和智能助手来提升生产力、优化代码质量。今天&#xff0c;我们将聚焦于两个强大的工具&#xff1a;Py…...

在Spring Boot中如何使用Freemaker模板引擎

在 Spring Boot 中使用 FreeMarker 模板引擎可以帮助你创建动态的 Web 页面。以下是详细的步骤和示例代码,介绍如何在 Spring Boot 项目里集成和使用 FreeMarker。 1. 添加依赖 如果你使用的是 Maven 项目,需要在 pom.xml 文件中添加 FreeMarker 相关依赖。Spring Boot 提供…...

【论文精读】VLM-AD:通过视觉-语言模型监督实现端到端自动驾驶

论文地址&#xff1a; VLM-AD: End-to-End Autonomous Driving through Vision-Language Model Supervision 摘要 人类驾驶员依赖常识推理来应对复杂多变的真实世界驾驶场景。现有的端到端&#xff08;E2E&#xff09;自动驾驶&#xff08;AD&#xff09;模型通常被优化以模仿…...

【HarmonyOS Next】鸿蒙应用进程和线程详解

【HarmonyOS Next】鸿蒙应用进程和线程详解 一、前言 进程的定义&#xff1a; 进程是系统进行资源分配的基本单位&#xff0c;是操作系统结构的基础。 在鸿蒙系统中&#xff0c;一个应用下会有三类进程&#xff1a; (1) 主进程&#xff0c; (2) ExtensionAbility进程&#xff…...

基于深度学习的信号滤波:创新技术与应用挑战

一、引言 1.1 研究背景 随着科技的不断发展&#xff0c;信号处理领域面临着越来越复杂的挑战。在众多信号处理技术中&#xff0c;基于深度学习的信号滤波技术逐渐崭露头角&#xff0c;成为研究的热点。 基于深度学习的信号滤波在信号处理领域具有至关重要的地位。如今&#…...

从【人工智能】到【计算机视觉】,【深度学习】引领的未来科技创新与变革

前几天偶然发现了一个超棒的人工智能学习网站&#xff0c;内容通俗易懂&#xff0c;讲解风趣幽默&#xff0c;简直让人欲罢不能。忍不住分享给大家&#xff0c;点击这里立刻跳转&#xff0c;开启你的AI学习之旅吧&#xff01; 前言 – 人工智能教程https://www.captainbed.cn/l…...

什么是方法

System.out.println(),那么它是什么呢&#xff1f; Java方法是语句的集合&#xff0c;它们在一起执行一个功能。 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建&#xff0c;在其他地方被使用 这段Java代码出现错误的原因在于&#xff0c;在…...

Python strip() 方法详解:用途、应用场景及示例解析(中英双语)

Python strip() 方法详解&#xff1a;用途、应用场景及示例解析 在 Python 处理字符串时&#xff0c;经常会遇到字符串前后存在多余的空格或特殊字符的问题。strip() 方法就是 Python 提供的一个强大工具&#xff0c;专门用于去除字符串两端的指定字符。本文将详细介绍 strip(…...

合并区间(56)

56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:vector<vector<int>> merge(vector<vector<int>>& intervals) {if (intervals.size() 1) {return intervals;}//现根据每一项的第一个值&#…...

如何保存爬虫获取商品评论的数据?

保存爬取的评论数据是爬虫项目中的一个重要环节。根据需求&#xff0c;你可以选择将数据保存为本地文件&#xff08;如CSV、JSON、TXT&#xff09;&#xff0c;或者存储到数据库&#xff08;如MySQL、MongoDB等&#xff09;。以下是几种常见的数据保存方式及其示例代码。 1. 保…...

使用docker配置PostgreSQL

配置docker阿里云镜像仓库 国内使用docker hub拉取镜像比较慢&#xff0c;所以首先配置个人的镜像仓库。 阿里云的个人镜像仓库是免费的&#xff0c;对个人来说足够用。 具体操作参考阿里云官方链接 。 关于个人镜像仓库的使用参考链接。 配置完个人镜像仓库后将公网配置到doc…...

阿里云虚机的远程桌面登录提示帐户被锁定了

提示由于安全原因&#xff0c;帐户被锁定。 阿里云虚机ECS的远程桌面登录提示帐户被锁定了&#xff0c;只能登录阿里云处理 阿里云-计算&#xff0c;为了无法计算的价值 需选择通过VNC连接 然后计算机管理&#xff0c;解除帐户锁定即可。...

SAP on Microsoft Azure Architecture and Administration (Ravi Kashyap)

SAP on Microsoft Azure Architecture and Administration (Ravi Kashyap)...

抽象类、接口、枚举

一、抽象类 1.1 简介 作为父类&#xff0c;里面的方法逻辑不能满足任何一个子类的需求&#xff0c;提供的逻辑根本就用不上&#xff0c;那么就不添加方法体了&#xff0c;此时这个方法需要 使用关键字abstract来修饰&#xff0c;表示为抽象方法&#xff0c;而抽象方法所在的类…...

GO系列-IO 文件操作

os io 判断文件是否存在 func fileExist(filePath string) (bool, error) {_, err : os.Stat(filePath)if err nil {return true, nil}if os.IsNotExist(err) {return false, nil}return false, &CheckFileExistError{filePath} } 读取文件内容 func readFileContext(…...

【前端】使用WebStorm创建第一个项目

文章目录 前言一、步骤1、启动2、创建项目3、配置Node.js4、运行项目 二、Node.js介绍 前言 根据前面文章中记录的步骤&#xff0c;已经安装好了WebStorm开发软件&#xff0c;接下来我们就用这个IDE开发软件创建第一个项目。 一、步骤 1、启动 启动软件。 2、创建项目 新建…...

自定义类型:结构体,枚举,联合

结构体 结构体的基本声明 基础知识&#xff1a;结构是一些值的集合&#xff0c;这些值称为成员变量&#xff0c;结构的每个成员可以是不同类型的变量。 //学生 struct Stu {//学生的相关信息char name[20];int age; }s1,s2; //s1,s2是直接创建的结构体变量&#xff08;全局变…...

柠檬水找零(力扣860)

这道题的贪心很简单&#xff0c;就是体现在对于20元的找零上。根据题意&#xff0c;20元有两种找零方式&#xff1a;1.找一张5元和一张10元&#xff1b;2.找3张5元。但是5元比较万能&#xff0c;因为无论是10还是20都需要用5元来找零&#xff0c;所以我们优先考虑第一种找零方式…...

sprintf和sscanf的用法和区别

sprintf和sscanf是C语言中常用的字符串处理函数&#xff0c;它们各自有不同的用途和用法。 1、sprintf的用法 sprintf函数主要用于将数据格式化为字符串并存储在指定的缓冲区中。其函数原型为&#xff1a; int sprintf(char *str, const char *format, ...); str&#xff1a…...

deepseek自动化代码生成

使用流程 效果第一步&#xff1a;注册生成各种大模型的API第二步&#xff1a;注册成功后生成API第三步&#xff1a;下载vscode在vscode中下载agent&#xff0c;这里推荐使用cline 第四步&#xff1a;安装完成后&#xff0c;设置模型信息第一步选择API provider&#xff1a; Ope…...