From bce8cf8b87662b11deaa2cfdfe68ed6d8f7e1554 Mon Sep 17 00:00:00 2001
From: i-shm
open System |
编译器认为存在两个相同的 CopyTo 重载无法区分。但查阅文档发现,Vector<T> 的 CopyTo 方法实际上只有一个匹配的重载(接受 Span<T>),这似乎矛盾。
这是因为 F# 编译器处理泛型方法重载的方式:
+Vector<T> 可能实现了多个接口,导致编译器看到两个签名相同的 CopyTo 方法(例如通过不同接口继承)。仅我所知的一种解决方案是通过添加扩展方法显式指引编译器:
+type Vector<'T> with |
这种方法通过创建具体的类型路径,帮助编译器绕过复杂的重载解析逻辑。
+学艺不精,不知道这是不是语言设计的差异,可能 F# 倾向于要求更明确的类型信息以避免意外行为?或许当泛型类型继承多个接口时,有没有可能出现在具体类型中不易察觉的隐式重载冲突?
+在FDA监管的药物研发、临床试验和上市流程中,当一个已上市药物(通常指创新药,通过新药申请NDA获得批准)出现一种更低廉的制药方式,但其活性成分的分子式保持完全相同时,这种情况本质上涉及仿制药(generic drug)的开发或工艺优化申请,而非从零开始的全新药物研发。简单来说,不需要重新进行完整的临床试验(即I-III期的大规模人体试验),但必须通过简化的监管路径证明新制药方式生产的药物与原药在质量、安全性和疗效上等效。
+首先,理解核心前提:分子式完全相同意味着活性成分(active pharmaceutical ingredient, API)是相同的化学实体,例如从专利保护的原研药转向无专利保护的仿制药生产。这不同于生物制品(如单克隆抗体)的生物类似药,后者可能需要更多比较性临床试验。FDA将此类药物归类为“仿制药”,其审批路径是缩减新药申请(Abbreviated New Drug Application, ANDA),而非完整的NDA。ANDA的目的是避免重复证明已知的安全性和有效性数据,这些数据已在原药的NDA中确立[1]。
+FDA的《仿制药用户费用法案》(GDUFA)和相关指南明确规定,对于相同分子式的药物,新制药方式(如改进的合成路线、晶型优化或更高效的提取工艺)只需证明“生物等效性”(bioequivalence),而非全面临床试验。生物等效性研究通常包括:1)体外溶出测试(in vitro dissolution),评估药物在模拟生理条件下的释放速率;2)人体药代动力学研究(pharmacokinetic studies),在健康志愿者中比较新药与原药的吸收、分布、代谢和排泄曲线(如AUC和Cmax参数的90%置信区间在80%-125%内)。这些研究规模小,通常只需24-36名受试者,持续数周,而非数年[2]。如果新工艺导致杂质谱或稳定性变化,FDA可能要求额外的数据,如加速稳定性测试或毒性评估,但仍无需重复疗效试验,除非有证据显示潜在差异(如新杂质超过许可阈值)[3]。
+在实际操作中,这一路径大大降低了成本和时间:ANDA审批平均需10-15个月,费用远低于NDA的数亿美元和数年周期。新制药方式的低廉性往往源于规模化生产或工艺创新,但FDA要求申请者提交化学、制造和控制(CMC)信息,证明新工艺符合良好生产规范(cGMP)。例如,阿司匹林或扑热息痛等经典药物,其多种仿制药版本均通过此路径上市,而无需重新验证其止痛或抗炎疗效[4]。然而,如果新方式涉及重大变更(如从化学合成转为生物合成,尽管分子式相同),FDA可能视其为“混合型”申请,需要桥接研究来确认等效性。
+如果生物等效性未能证明(例如,新工艺导致生物利用度差异>20%),申请将被拒,或需额外桥接试验,这可能增加延误和成本。不过上市后监测(post-marketing surveillance)仍适用,包括不良事件报告(FAERS系统),以捕捉任何罕见差异。
+U.S. Food and Drug Administration. (2023). Frequently Asked Questions about Generic Drugs. Retrieved from https://www.fda.gov/drugs/generic-drugs/frequently-asked-questions-about-generic-drugs ↩︎
+U.S. Food and Drug Administration. (2019). Bioequivalence Studies with Pharmacokinetic Endpoints for Drugs Submitted Under an ANDA. Guidance for Industry. Retrieved from https://www.fda.gov/regulatory-information/search-fda-guidance-documents/bioequivalence-studies-pharmacokinetic-endpoints-drugs-submitted-under-abbreviated-new-drug ↩︎
+U.S. Food and Drug Administration. (2020). Changes to an Approved NDA or ANDA. Guidance for Industry. Retrieved from https://www.fda.gov/regulatory-information/search-fda-guidance-documents/changes-approved-nda-or-anda ↩︎
+U.S. Food and Drug Administration. (2023). Approved Drug Products with Therapeutic Equivalence Evaluations (Orange Book). Retrieved from https://www.fda.gov/drugs/drug-approvals-and-databases/approved-drug-products-therapeutic-equivalence-evaluations-orange-book ↩︎
+open System |
编译器认为存在两个相同的 CopyTo 重载无法区分。但查阅文档发现,Vector<T> 的 CopyTo 方法实际上只有一个匹配的重载(接受 Span<T>),这似乎矛盾。
这是因为 F# 编译器处理泛型方法重载的方式:
-Vector<T> 可能实现了多个接口,导致编译器看到两个签名相同的 CopyTo 方法(例如通过不同接口继承)。仅我所知的一种解决方案是通过添加扩展方法显式指引编译器:
-type Vector<'T> with |
这种方法通过创建具体的类型路径,帮助编译器绕过复杂的重载解析逻辑。
-学艺不精,不知道这是不是语言设计的差异,可能 F# 倾向于要求更明确的类型信息以避免意外行为?或许当泛型类型继承多个接口时,有没有可能出现在具体类型中不易察觉的隐式重载冲突?
-在FDA监管的药物研发、临床试验和上市流程中,当一个已上市药物(通常指创新药,通过新药申请NDA获得批准)出现一种更低廉的制药方式,但其活性成分的分子式保持完全相同时,这种情况本质上涉及仿制药(generic drug)的开发或工艺优化申请,而非从零开始的全新药物研发。简单来说,不需要重新进行完整的临床试验(即I-III期的大规模人体试验),但必须通过简化的监管路径证明新制药方式生产的药物与原药在质量、安全性和疗效上等效。
-首先,理解核心前提:分子式完全相同意味着活性成分(active pharmaceutical ingredient, API)是相同的化学实体,例如从专利保护的原研药转向无专利保护的仿制药生产。这不同于生物制品(如单克隆抗体)的生物类似药,后者可能需要更多比较性临床试验。FDA将此类药物归类为“仿制药”,其审批路径是缩减新药申请(Abbreviated New Drug Application, ANDA),而非完整的NDA。ANDA的目的是避免重复证明已知的安全性和有效性数据,这些数据已在原药的NDA中确立[1]。
-FDA的《仿制药用户费用法案》(GDUFA)和相关指南明确规定,对于相同分子式的药物,新制药方式(如改进的合成路线、晶型优化或更高效的提取工艺)只需证明“生物等效性”(bioequivalence),而非全面临床试验。生物等效性研究通常包括:1)体外溶出测试(in vitro dissolution),评估药物在模拟生理条件下的释放速率;2)人体药代动力学研究(pharmacokinetic studies),在健康志愿者中比较新药与原药的吸收、分布、代谢和排泄曲线(如AUC和Cmax参数的90%置信区间在80%-125%内)。这些研究规模小,通常只需24-36名受试者,持续数周,而非数年[2]。如果新工艺导致杂质谱或稳定性变化,FDA可能要求额外的数据,如加速稳定性测试或毒性评估,但仍无需重复疗效试验,除非有证据显示潜在差异(如新杂质超过许可阈值)[3]。
-在实际操作中,这一路径大大降低了成本和时间:ANDA审批平均需10-15个月,费用远低于NDA的数亿美元和数年周期。新制药方式的低廉性往往源于规模化生产或工艺创新,但FDA要求申请者提交化学、制造和控制(CMC)信息,证明新工艺符合良好生产规范(cGMP)。例如,阿司匹林或扑热息痛等经典药物,其多种仿制药版本均通过此路径上市,而无需重新验证其止痛或抗炎疗效[4]。然而,如果新方式涉及重大变更(如从化学合成转为生物合成,尽管分子式相同),FDA可能视其为“混合型”申请,需要桥接研究来确认等效性。
-如果生物等效性未能证明(例如,新工艺导致生物利用度差异>20%),申请将被拒,或需额外桥接试验,这可能增加延误和成本。不过上市后监测(post-marketing surveillance)仍适用,包括不良事件报告(FAERS系统),以捕捉任何罕见差异。
-U.S. Food and Drug Administration. (2023). Frequently Asked Questions about Generic Drugs. Retrieved from https://www.fda.gov/drugs/generic-drugs/frequently-asked-questions-about-generic-drugs ↩︎
-U.S. Food and Drug Administration. (2019). Bioequivalence Studies with Pharmacokinetic Endpoints for Drugs Submitted Under an ANDA. Guidance for Industry. Retrieved from https://www.fda.gov/regulatory-information/search-fda-guidance-documents/bioequivalence-studies-pharmacokinetic-endpoints-drugs-submitted-under-abbreviated-new-drug ↩︎
-U.S. Food and Drug Administration. (2020). Changes to an Approved NDA or ANDA. Guidance for Industry. Retrieved from https://www.fda.gov/regulatory-information/search-fda-guidance-documents/changes-approved-nda-or-anda ↩︎
-U.S. Food and Drug Administration. (2023). Approved Drug Products with Therapeutic Equivalence Evaluations (Orange Book). Retrieved from https://www.fda.gov/drugs/drug-approvals-and-databases/approved-drug-products-therapeutic-equivalence-evaluations-orange-book ↩︎
-G⁺ 细菌的细胞壁外层主要由 厚度约 20–80 nm 的肽聚糖(peptidoglycan) 组成,这层结构密集且富含交联的糖肽链,能够在脱色步骤中形成物理屏障,阻止酒精/丙酮的渗透,从而保留结晶紫‑碘复合物。
+与 G⁻ 细菌不同,G⁺ 细菌没有外膜(outer membrane)和脂多糖(LPS)层。外膜的缺失使得脱色剂难以进入细胞内部,进一步加强了紫色的保留。
+某些 G⁺ 细菌在细胞壁上表达的酶(如酸性磷酸酶)可与染料形成更为稳定的复合物,进一步提升染色的持久性。
+在呼吸道痰涂片中出现 “有荚膜的双球菌(capsulated diplococci)”,最典型的病原体是 肺炎链球菌(Streptococcus pneumoniae)。它是一种 革兰氏阳性(G⁺)、α‑hemolytic、嗜血清素 的双球菌,表面包裹有厚厚的多糖荚膜,正是该荚膜赋予它在显微镜下呈现明显的荧光或“胶状”外观。
+在痰涂片或血培养的显微镜检查中,观察到 G⁺ 双球菌提示肺炎链球菌感染的可能性较大,帮助临床医生在培养结果出来前就能启动经验性抗生素治疗(如 β‑lactam 类药物)。
+肺炎链球菌的荚膜多型性(> 90 种血清型)是疫苗设计的核心依据,同时也影响抗体介导的吞噬作用。了解其 G⁺ 特性有助于解释为何某些血清型(如 3 型)在免疫逃逸方面更具优势。
+]]>G⁺ 细菌的细胞壁外层主要由 厚度约 20–80 nm 的肽聚糖(peptidoglycan) 组成,这层结构密集且富含交联的糖肽链,能够在脱色步骤中形成物理屏障,阻止酒精/丙酮的渗透,从而保留结晶紫‑碘复合物。
-与 G⁻ 细菌不同,G⁺ 细菌没有外膜(outer membrane)和脂多糖(LPS)层。外膜的缺失使得脱色剂难以进入细胞内部,进一步加强了紫色的保留。
-某些 G⁺ 细菌在细胞壁上表达的酶(如酸性磷酸酶)可与染料形成更为稳定的复合物,进一步提升染色的持久性。
-在呼吸道痰涂片中出现 “有荚膜的双球菌(capsulated diplococci)”,最典型的病原体是 肺炎链球菌(Streptococcus pneumoniae)。它是一种 革兰氏阳性(G⁺)、α‑hemolytic、嗜血清素 的双球菌,表面包裹有厚厚的多糖荚膜,正是该荚膜赋予它在显微镜下呈现明显的荧光或“胶状”外观。
-在痰涂片或血培养的显微镜检查中,观察到 G⁺ 双球菌提示肺炎链球菌感染的可能性较大,帮助临床医生在培养结果出来前就能启动经验性抗生素治疗(如 β‑lactam 类药物)。
-肺炎链球菌的荚膜多型性(> 90 种血清型)是疫苗设计的核心依据,同时也影响抗体介导的吞噬作用。了解其 G⁺ 特性有助于解释为何某些血清型(如 3 型)在免疫逃逸方面更具优势。
-]]>正确顺序:
location = /api/auth/me { |
这里的顺序很重要。Nginx 匹配规则是:精确匹配 = 优先,然后是前缀匹配 ^~,然后是正则匹配,最后是普通前缀匹配。^~ 表示一旦匹配成功就不再检查正则。
let int_pow base exponent = |
其中 int_math_int_pow() 由 C 实现:
external int_math_int_pow : int -> int -> int = "Base_int_math_int_pow_stub" [@@noalloc] |
其实现在 src/int_math_stubs.c 中:
-static int64_t int_pow(int64_t base, int64_t exponent) { |
这是一个四分快速幂的实现,它是二分快速幂的一种变种。二分快速幂将指数分为两部分,然后递归地计算每一部分的结果。
-而四分快速幂将指数分为四部分,然后递归地计算每一部分的结果。
-这里通过将指数右移2位(相当于除以4)和使用位与操作来实现,进一步减少了乘法次数。
主要步骤:
---mul[1]是基数和mul[3]的乘积,mul[2]是mul[1]的平方,mul[3]是mul[2]和基数的乘积
-
--这样做的目的是为了选择正确的乘数,因为指数被分解为4的倍数
-
这个实现的优点是它可以在对数时间内计算出幂运算,而且每次循环只需要4次乘法。这比标准的二分快速幂算法需要的乘法次数更少。
]]>zbg (short for Zero Bullshit Git) is a CLI tool for using git efficiently.let int_pow base exponent = |
其中 int_math_int_pow() 由 C 实现:
external int_math_int_pow : int -> int -> int = "Base_int_math_int_pow_stub" [@@noalloc] |
其实现在 src/int_math_stubs.c 中:
+static int64_t int_pow(int64_t base, int64_t exponent) { |
这是一个四分快速幂的实现,它是二分快速幂的一种变种。二分快速幂将指数分为两部分,然后递归地计算每一部分的结果。
+而四分快速幂将指数分为四部分,然后递归地计算每一部分的结果。
+这里通过将指数右移2位(相当于除以4)和使用位与操作来实现,进一步减少了乘法次数。
主要步骤:
+++mul[1]是基数和mul[3]的乘积,mul[2]是mul[1]的平方,mul[3]是mul[2]和基数的乘积
+
++这样做的目的是为了选择正确的乘数,因为指数被分解为4的倍数
+
这个实现的优点是它可以在对数时间内计算出幂运算,而且每次循环只需要4次乘法。这比标准的二分快速幂算法需要的乘法次数更少。
]]>Ten years prior to presentation, he underwent surgical decompression for syringomyelia.
+A magnetic resonance imaging (MRI) scan of his cervical and thoracic spine performed 2 years prior to presentation revealed a recurrent syrinx extending from Cl C1 to T11, which was not resected because it did not cause symptoms at that time.
+On physical examination, he had mild tenderness to palpation and reduced range of motion of the left shoulder with abduction and flexion limited to 120° (normal range of motion, 180°).
+The left scapular muscles were atrophic, and pain and temperature sensation were reduced in his proximal left arm, and dorsal aspect of his left shoulder.
+His complete blood cell count, serum glucose levels, C-reactive protein levels, and erythrocyte sedimentation rate were normal.
+Results of tests for rheumatoid factor and antinuclear antibody were negative.
+Left shoulder radiograph showed complete absence of the left humeral head and a well-demarcated smooth osseous margin of the proximal humerus with associated soft tissue swelling and periarticular calcification.
+A chest radiograph taken 2 years prior revealed a normal left shoulder joint. The patient was hospitalized for further evaluation and treatment.
+这里提到了一种罕见的进展性疾病, 叫Charcot肩, 是一种神经性关节病变,特点是关节迅速被破坏和相关软组织肿胀。患者通常表现为肩部逐渐增大的肿胀,可能伴有疼痛或无痛,肩部无力和活动范围减少。
+大约80%的Charcot肩患者有脊髓空洞症, 表现为脊髓中的液体充满腔体
Ten years prior to presentation, he underwent surgical decompression for syringomyelia.
-A magnetic resonance imaging (MRI) scan of his cervical and thoracic spine performed 2 years prior to presentation revealed a recurrent syrinx extending from Cl C1 to T11, which was not resected because it did not cause symptoms at that time.
-On physical examination, he had mild tenderness to palpation and reduced range of motion of the left shoulder with abduction and flexion limited to 120° (normal range of motion, 180°).
-The left scapular muscles were atrophic, and pain and temperature sensation were reduced in his proximal left arm, and dorsal aspect of his left shoulder.
-His complete blood cell count, serum glucose levels, C-reactive protein levels, and erythrocyte sedimentation rate were normal.
-Results of tests for rheumatoid factor and antinuclear antibody were negative.
-Left shoulder radiograph showed complete absence of the left humeral head and a well-demarcated smooth osseous margin of the proximal humerus with associated soft tissue swelling and periarticular calcification.
-A chest radiograph taken 2 years prior revealed a normal left shoulder joint. The patient was hospitalized for further evaluation and treatment.
-这里提到了一种罕见的进展性疾病, 叫Charcot肩, 是一种神经性关节病变,特点是关节迅速被破坏和相关软组织肿胀。患者通常表现为肩部逐渐增大的肿胀,可能伴有疼痛或无痛,肩部无力和活动范围减少。
-大约80%的Charcot肩患者有脊髓空洞症, 表现为脊髓中的液体充满腔体
--注意:Rust 虚表及其结构属于 Rust 语言的内部实现细节,不保证稳定性。本文所介绍的虚表布局仅反映本文创作时最新的 Rust 虚表结构[1],在将来 Rust 虚表结构可能会发生变化。一个 Rust 程序的正确性不应该以任何方式依赖于 Rust 虚表的结构。
-
Rust 程序中的所有虚表均以一个固定结构的 header 开头。Header 中按顺序包含三个usize 大小的字段:drop_in_place ,size 和 align 。在 header 之后是一系列的 usize 大小字段,其数量以及含义在每个虚表中可能都不同。
-+---------------+ |
虚表 header 中的drop_in_place 是一个函数指针,其指向的函数能够原地 drop 当前胖指针所引用的对象。size 和 align 两个域分别给出对象的大小和内存对齐,这两个域共同构成一个 std::alloc::Layout 结构,可用于释放当前胖指针所引用的对象所占据的内存。虚表 header 的存在使得 trait object 总是能被销毁和释放。例如当销毁一个 Box<dyn Trait> 时,Box::<dyn Trait>::drop 会首先调用虚表中的 drop_in_place 函数原地销毁 Box 所引用的对象,然后再调用 dealloc 函数并传递虚表中的 size 和 align 释放堆空间。
... |
编译错误:
+error: lifetime may not live long enough |
这是因为 handlers 里面的闭包捕获了一个引用,并且尝试返回一个包含该引用的值导致的。
细说就是:闭包内部使用了 self.clone() 来获取一个新的实例,然后在异步块中返回一个 JSON 对象,这个 JSON 对象依赖于 self.tree() 的结果。因为闭包捕获了 self 的引用,所以它必须保证 self 在闭包执行完毕后仍然有效。
解决这个问题的思路是:确保闭包中的所有引用都在闭包执行完毕之前就不再被使用。
+就是说,要将闭包的作用域限制在一个更短的生命周期内,或者使用其他方式来避免闭包捕获长期存在的引用:
|
++注意:Rust 虚表及其结构属于 Rust 语言的内部实现细节,不保证稳定性。本文所介绍的虚表布局仅反映本文创作时最新的 Rust 虚表结构[1],在将来 Rust 虚表结构可能会发生变化。一个 Rust 程序的正确性不应该以任何方式依赖于 Rust 虚表的结构。
+
Rust 程序中的所有虚表均以一个固定结构的 header 开头。Header 中按顺序包含三个usize 大小的字段:drop_in_place ,size 和 align 。在 header 之后是一系列的 usize 大小字段,其数量以及含义在每个虚表中可能都不同。
++---------------+ |
虚表 header 中的drop_in_place 是一个函数指针,其指向的函数能够原地 drop 当前胖指针所引用的对象。size 和 align 两个域分别给出对象的大小和内存对齐,这两个域共同构成一个 std::alloc::Layout 结构,可用于释放当前胖指针所引用的对象所占据的内存。虚表 header 的存在使得 trait object 总是能被销毁和释放。例如当销毁一个 Box<dyn Trait> 时,Box::<dyn Trait>::drop 会首先调用虚表中的 drop_in_place 函数原地销毁 Box 所引用的对象,然后再调用 dealloc 函数并传递虚表中的 size 和 align 释放堆空间。
在虚表 header 之后是一系列的字段。在最普遍的情况下,每个字段代表一个指向 trait 所定义的函数的指针。例如,对于下列 object safe 的 trait:
pub trait Trait { |
如果类型T 实现了 Trait,那么为 T 生成的 Trait 虚表的结构为:
@@ -2320,22 +2336,6 @@ A relation table (also sometimes called a JOIN, link or pi... |
编译错误:
-error: lifetime may not live long enough |
这是因为 handlers 里面的闭包捕获了一个引用,并且尝试返回一个包含该引用的值导致的。
细说就是:闭包内部使用了 self.clone() 来获取一个新的实例,然后在异步块中返回一个 JSON 对象,这个 JSON 对象依赖于 self.tree() 的结果。因为闭包捕获了 self 的引用,所以它必须保证 self 在闭包执行完毕后仍然有效。
解决这个问题的思路是:确保闭包中的所有引用都在闭包执行完毕之前就不再被使用。
-就是说,要将闭包的作用域限制在一个更短的生命周期内,或者使用其他方式来避免闭包捕获长期存在的引用:
|
我使用 Pop!_OS,此发行版使用 EFI 启动,故而可以在 /boot/efi/loader/loader.conf 中加上:
options quiet splash amdgpu.dcdebugmask=0x10 amdgpu.sg_display=0 |
对于其他使用 EFI 或 GRUB 启动的发行版也可以添加类似的参数尝试尝试。
+]]> +class-validator 和 class-transformer 这两个库提供了以声明式的方式对 DTO 进行验证和转换。然而在处理布尔值时,如果在全局验证管道或仅仅是在局部同时开启了 enableImplicitConversion,可能会引入一个极其隐蔽且违反直觉的 Bug:前端传过来的布尔值恒为 true。
+假设正在开发一个电子商务平台的 API,需要实现一个产品列表的筛选功能。希望能够根据产品是否有库存 (hasStock)、是否为特色产品 (isFeatured) 等布尔条件进行筛选。
前端发出的请求 URL 可能如下所示: /products?filter[hasStock]=true&filter[isFeatured]=false
在 NestJS 后端,首先会在 main.ts 中配置一个全局的 ValidationPipe,以自动处理 DTO 的验证和转换。为了方便,通常会启用 enableImplicitConversion,期望它能自动将 URL 查询参数中的字符串(如 "123", "true")转换为 DTO 中定义的类型(number, boolean):
// main.ts |
接着,定义一个 ProductFilterDto 来接收这些筛选条件。
一个看似正确的 DTO 定义:
+// product-filter.dto.ts |
在控制器中使用这个 DTO:
+// products.controller.ts |
当请求 .../products?filter[isFeatured]=false 到达时,本来期望在 find 方法中得到的 filter.isFeatured 的值是布尔类型的 false。然而,控制台输出的结果却令人意外:{ isFeatured: true }
这个问题的根源在于 class-transformer 内部的转换执行顺序,以及 JavaScript 中 Boolean 函数的类型转换行为。
所有通过 URL 查询参数传递的值,其本质都是字符串。当 NestJS 接收到请求时,filter.isFeatured 的原始值是字符串 "false"。
ValidationPipe 启动 class-transformer 的转换流程。由于在全局管道中设置了 enableImplicitConversion: true,转换器会首先检查 DTO 属性的 TypeScript 类型。
class-transformer 看到 ProductFilterDto 中的 isFeatured 属性被声明为 boolean 类型。"false" 转换为布尔值。这个转换等同于执行 Boolean("false")。在 JavaScript 中,任何非空字符串(包括 "false")通过 Boolean() 构造函数转换后都会得到 true。true 值被作为该属性的转换结果。此时,即使尝试添加一个自定义的 @Transform 装饰器来手动处理这个问题,也为时已晚。
例如,定义一个 booleanTransformer:
// boolean-transformer.ts |
然后更新 dto:
+// product-filter.dto.ts (错误的尝试) |
流程会变成这样:
+Boolean("false") -> true。@Transform 装饰器执行:此时传递给 booleanTransformer 的 value 已经是上一步错误转换后的布尔值 true,而不是原始的字符串 "false"。转换函数无从下手。最终结果依然是 true。
any 绕过隐式转换要解决这个问题,核心在于阻止 class-transformer 进行那次错误的、优先的隐式转换,从而确保自定义 @Transform 函数能接收到最原始的字符串值。
最直接且侵入性最小的方法,是将 DTO 中相关属性的 TypeScript 类型从 boolean 改为 any。
修正后的 DTO 定义:
+// product-filter.dto.ts (正确的实现) |
这个改动虽然看起来放弃了 TypeScript 的类型检查,但在这个特定的场景下,它非常安全且有效。原因如下:
+class-transformer 看到属性类型是 any 时,它不知道该隐式转换成什么目标类型,因此会“跳过”这个属性的隐式转换步骤。@Transform 接管:如此一来,原始的字符串值("true" 或 "false")就能原封不动地传递给 robustBooleanTransformer 函数。该函数现在可以正确地将字符串转换为期望的布尔值。@IsBoolean 守门:在自定义转换完成后,@IsBoolean() 装饰器会进行最后的验证,确保存入 DTO 的最终值必须是 true 或 false。这保证了在业务逻辑中,该属性的类型是绝对安全的。好用,爱用。
]]>class-validator 和 class-transformer 这两个库提供了以声明式的方式对 DTO 进行验证和转换。然而在处理布尔值时,如果在全局验证管道或仅仅是在局部同时开启了 enableImplicitConversion,可能会引入一个极其隐蔽且违反直觉的 Bug:前端传过来的布尔值恒为 true。
-假设正在开发一个电子商务平台的 API,需要实现一个产品列表的筛选功能。希望能够根据产品是否有库存 (hasStock)、是否为特色产品 (isFeatured) 等布尔条件进行筛选。
前端发出的请求 URL 可能如下所示: /products?filter[hasStock]=true&filter[isFeatured]=false
在 NestJS 后端,首先会在 main.ts 中配置一个全局的 ValidationPipe,以自动处理 DTO 的验证和转换。为了方便,通常会启用 enableImplicitConversion,期望它能自动将 URL 查询参数中的字符串(如 "123", "true")转换为 DTO 中定义的类型(number, boolean):
// main.ts |
接着,定义一个 ProductFilterDto 来接收这些筛选条件。
一个看似正确的 DTO 定义:
-// product-filter.dto.ts |
在控制器中使用这个 DTO:
-// products.controller.ts |
当请求 .../products?filter[isFeatured]=false 到达时,本来期望在 find 方法中得到的 filter.isFeatured 的值是布尔类型的 false。然而,控制台输出的结果却令人意外:{ isFeatured: true }
这个问题的根源在于 class-transformer 内部的转换执行顺序,以及 JavaScript 中 Boolean 函数的类型转换行为。
所有通过 URL 查询参数传递的值,其本质都是字符串。当 NestJS 接收到请求时,filter.isFeatured 的原始值是字符串 "false"。
ValidationPipe 启动 class-transformer 的转换流程。由于在全局管道中设置了 enableImplicitConversion: true,转换器会首先检查 DTO 属性的 TypeScript 类型。
class-transformer 看到 ProductFilterDto 中的 isFeatured 属性被声明为 boolean 类型。"false" 转换为布尔值。这个转换等同于执行 Boolean("false")。在 JavaScript 中,任何非空字符串(包括 "false")通过 Boolean() 构造函数转换后都会得到 true。true 值被作为该属性的转换结果。此时,即使尝试添加一个自定义的 @Transform 装饰器来手动处理这个问题,也为时已晚。
例如,定义一个 booleanTransformer:
// boolean-transformer.ts |
然后更新 dto:
-// product-filter.dto.ts (错误的尝试) |
流程会变成这样:
-Boolean("false") -> true。@Transform 装饰器执行:此时传递给 booleanTransformer 的 value 已经是上一步错误转换后的布尔值 true,而不是原始的字符串 "false"。转换函数无从下手。最终结果依然是 true。
any 绕过隐式转换要解决这个问题,核心在于阻止 class-transformer 进行那次错误的、优先的隐式转换,从而确保自定义 @Transform 函数能接收到最原始的字符串值。
最直接且侵入性最小的方法,是将 DTO 中相关属性的 TypeScript 类型从 boolean 改为 any。
修正后的 DTO 定义:
-// product-filter.dto.ts (正确的实现) |
这个改动虽然看起来放弃了 TypeScript 的类型检查,但在这个特定的场景下,它非常安全且有效。原因如下:
-class-transformer 看到属性类型是 any 时,它不知道该隐式转换成什么目标类型,因此会“跳过”这个属性的隐式转换步骤。@Transform 接管:如此一来,原始的字符串值("true" 或 "false")就能原封不动地传递给 robustBooleanTransformer 函数。该函数现在可以正确地将字符串转换为期望的布尔值。@IsBoolean 守门:在自定义转换完成后,@IsBoolean() 装饰器会进行最后的验证,确保存入 DTO 的最终值必须是 true 或 false。这保证了在业务逻辑中,该属性的类型是绝对安全的。好用,爱用。
]]>.m2/settings.xml. You can however set the :proxy config either in shadow-cljs.edn directly or ~/.shadow-cljs/config.edn.
-
-shadow-cljs.edn:
-{:source-paths ["src/main" |
.m2/settings.xml. You can however set the :proxy config either in shadow-cljs.edn directly or ~/.shadow-cljs/config.edn.
+
+shadow-cljs.edn:
+{:source-paths ["src/main" |
时光对谁都不温柔,愿意对我温柔的,只有身边陪我一起迎接时光洗礼的人。
+宇宙中也不会有什么声音, 视觉上再震撼的毁灭也只是发生在沉默之中。
+一切重新沉寂下来。
+]]>时光对谁都不温柔,愿意对我温柔的,只有身边陪我一起迎接时光洗礼的人。
-宇宙中也不会有什么声音, 视觉上再震撼的毁灭也只是发生在沉默之中。
-一切重新沉寂下来。
-]]>那在这之前呢?
在这之前我刚吃完一碗辣椒炒肉,
香
+]]> +衣服买大了,他们走路好急,地铁上只有老人没看手机,天怎么黑那么快是我起晚了吗,那个蹦蹦跳跳的女孩耳机里在听什么歌,我还在原地吗,我要再等等吗。
+家就像厚酒之后突然明晰的想象,时间不语,只是沉默,我沉默地走进时间,看着我和你的年龄相差越来越小。
+这雨天,世界都温柔的可以掐出水来。
]]>虽然我早已不强求世界上有这么一个人,
但我会一直等待,甚至期待你的到来。
我叫韩暮秋,幸会。
-]]> -衣服买大了,他们走路好急,地铁上只有老人没看手机,天怎么黑那么快是我起晚了吗,那个蹦蹦跳跳的女孩耳机里在听什么歌,我还在原地吗,我要再等等吗。
-家就像厚酒之后突然明晰的想象,时间不语,只是沉默,我沉默地走进时间,看着我和你的年龄相差越来越小。
-这雨天,世界都温柔的可以掐出水来。
]]>时间会带走了一个人,也带走了他的呼吸,他的声音,他掌心的温度。但似乎又留下了些什么
+光的颗粒在空气里浮动,在记忆里游走,她闭上眼睛,光从睫毛上滑过,像许多个早晨,像许多个傍晚,像她们再次相遇的无数个灿然的瞬间。她在其中走走停停,像一粒微尘,又像一颗星。
]]>时间会带走了一个人,也带走了他的呼吸,他的声音,他掌心的温度。但似乎又留下了些什么
-光的颗粒在空气里浮动,在记忆里游走,她闭上眼睛,光从睫毛上滑过,像许多个早晨,像许多个傍晚,像她们再次相遇的无数个灿然的瞬间。她在其中走走停停,像一粒微尘,又像一颗星。
+早上七点。
太阳完全绽放的光芒照亮了这个欣欣向荣的世界,有山、有海,有自由。
+]]> +世界很大,大到容纳下云海山川与深海,一定要去看看所有的色彩。世界也很小,小到只能让我一个人存在,原地转一圈,就足以填补了人生所有的空白。
我的家人太早回归了群星,而我还贪恋着人间烟火。
息止安所。
+]]> +“拍了啊,倒数,三、二、一……茄子!”
咔擦,画面定格,幸福定格,大家终于从苦难里彻底毕业了。
-]]> -房颤,即心房颤动,是一种常见的持续性心律失常。正常情况下,心房先有规律地收缩,把血液推入心室;房颤时,心房电活动变得快速、紊乱,心房不再进行有效的整体收缩,心室则以不规则节律搏动。
-患者可能感到心悸、胸闷、乏力、活动耐量下降,也可能完全没有症状。无症状并不等于没有风险。房颤对脑卒中的影响,主要来自血流淤滞和血栓形成,而不是来自心跳“乱”本身。
+患者可能感到心悸、胸闷、乏力和活动耐量下降,也可能完全没有症状。无症状不能排除血栓风险。房颤导致卒中的主要环节是血流淤滞和血栓形成,心跳不规则本身并不是栓塞的直接原因。
房颤与年龄增长、高血压、心力衰竭、冠心病、瓣膜疾病、糖尿病、肥胖、睡眠呼吸暂停和甲状腺功能异常等因素有关。它还可能形成一个持续恶化的循环:房颤引起心房电和结构重塑,重塑又使房颤更容易持续。[1][2]
房颤相关血栓形成,通常可以从三个方面理解:血流淤滞、心房组织改变和凝血倾向增强。这三个方面对应经典的血栓形成机制,即 Virchow 三要素。
@@ -6148,41 +6148,41 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的房颤患者的血栓并不一定形成在心室,也不一定发生在全身静脉。典型的房颤相关血栓来自左心房,尤其是左心耳。血栓形成后,如果受到心房压力变化、心律恢复或血流剪切力影响,就可能脱落。
长期房颤可能导致心房扩大、纤维化和局部内皮功能异常。心房内膜受到机械牵张和炎症信号影响后,抗凝和抗血小板的保护性状态可能减弱,促凝状态增强。
-房颤与炎症、氧化应激、纤维化和内皮功能障碍之间存在相互作用。现有研究支持“房颤不是单纯电活动异常”的观点:它同时涉及心房结构、代谢、炎症和凝血网络。[1:1][3]
+房颤与炎症、氧化应激、纤维化和内皮功能障碍之间存在相互作用。现有研究表明,房颤同时涉及心房结构、代谢、炎症和凝血网络。[1:1][3]
房颤患者可能出现血小板活化、凝血酶生成增加和纤维蛋白形成增强。高血压、心力衰竭、糖尿病、慢性肾病和高龄等因素,又会进一步提高凝血和血管损伤风险。
因此,房颤相关血栓不是由单一因素造成的。即使患者某一次心电图没有记录到房颤,也不能据此认为血栓风险已经消失。房颤可能具有阵发性,血栓风险还受到基础疾病、既往卒中史和心房结构等因素影响。
左心房内形成的血栓如果脱落,会进入左心室,再被泵入主动脉。血栓沿动脉进入脑循环后,可能堵塞颈内动脉、大脑中动脉或其他脑动脉分支,造成局部脑组织缺血和坏死。
-这类卒中属于心源性栓塞。与某些小动脉粥样硬化性卒中相比,房颤相关卒中往往具有栓子较大、血管阻塞位置较近端、神经功能损害较重等特点,也更容易出现较大的梗死范围。
+这类卒中属于心源性栓塞。与某些小动脉粥样硬化性卒中相比,房颤相关卒中的栓子往往较大,阻塞部位可能更近端,神经功能损害也可能更重,因此梗死范围可能更大。
经典的 Framingham 研究把房颤确定为卒中的独立危险因素。后续指南和综述也持续把卒中预防放在房颤管理的核心位置。[4][5]
血栓也可能进入其他器官,引起外周动脉栓塞、肠系膜缺血、肾梗死或脾梗死。不过,临床上最受关注的后果仍然是缺血性卒中和短暂性脑缺血发作。
不能只根据“有没有房颤”判断是否需要抗凝。房颤患者的血栓栓塞风险存在很大差异。
+是否需要抗凝,取决于患者的整体血栓栓塞风险。不同房颤患者的风险并不相同。
临床通常会使用风险评分工具估计卒中风险。常见因素包括心力衰竭、高血压、年龄、糖尿病、既往卒中或短暂性脑缺血发作、血管疾病以及女性性别等。2023 年美国指南和 2024 年欧洲指南都强调,抗凝决策应以经过验证的卒中风险评估为基础,同时结合患者偏好、出血风险和临床情境。[6][7]
风险评分的作用是帮助估计总体风险,不是替代临床判断。它也不能回答所有问题。例如,肾功能变化、近期出血、肿瘤、贫血、合并用药和高龄,都可能改变抗凝治疗的实际获益与风险。
-出血风险评估同样重要,但“出血风险高”并不自动等于“不能抗凝”。更合理的做法是寻找可纠正因素,例如控制血压、减少不必要的抗血小板药物、避免非甾体抗炎药、处理贫血和改善肾功能监测。
+出血风险升高时,应先寻找可纠正因素,例如控制血压、减少不必要的抗血小板药物、避免非甾体抗炎药、处理贫血和加强肾功能监测,再综合判断抗凝获益与出血风险。
抗凝药的作用是抑制凝血级联,减少纤维蛋白血栓形成。它并不是把已经形成的血栓“瞬间溶解”,而是降低新血栓形成和原有血栓扩大的概率。
+抗凝药通过抑制凝血级联,减少纤维蛋白血栓形成。它主要降低新血栓形成和原有血栓扩大的概率,不能替代针对急性血栓的溶栓或取栓治疗。
目前,房颤卒中预防常用口服抗凝药包括直接口服抗凝药和华法林。直接口服抗凝药包括直接凝血酶抑制剂以及直接凝血因子 Xa 抑制剂。它们起效较快,通常不需要像华法林那样频繁调整国际标准化比值,但仍需要根据肾功能、年龄、体重、合并用药和适应证选择剂量。
多项随机试验的个体患者数据分析显示,直接口服抗凝药总体上适合用于非瓣膜性房颤的卒中预防,且不同年龄和性别亚组的主要疗效方向相对一致。系统综述和网络荟萃分析也支持口服抗凝药预防房颤相关卒中,但不同药物在胃肠道出血、颅内出血和其他出血结局上并不完全相同。[8][9]
-这并不意味着直接口服抗凝药对所有房颤患者都优于华法林。机械心脏瓣膜患者、部分中重度二尖瓣狭窄患者,以及某些严重肾功能异常患者,需要按照具体指南和专科医生意见选择方案。药物种类不能只凭“新药”或“方便”来决定。
+直接口服抗凝药并不适用于所有房颤患者。机械心脏瓣膜患者、部分中重度二尖瓣狭窄患者,以及某些严重肾功能异常患者,需要按照具体指南和专科医生意见选择方案。药物种类应依据适应证、肾功能、合并用药和出血风险确定。
阿司匹林等抗血小板药主要影响血小板功能,而房颤相关血栓形成往往以凝血和纤维蛋白网络为重要特征。对于需要抗凝的房颤患者,单用抗血小板药通常不能等效替代口服抗凝药。
如果患者同时存在冠状动脉疾病、冠脉支架或急性冠脉综合征,医生可能在特定阶段联合使用抗凝药和抗血小板药。但联合治疗会增加出血风险,疗程和药物组合需要严格限定,不能自行长期叠加。
通常不能仅因为心律恢复正常,就立即停用抗凝药。
房颤患者的卒中风险不仅由当天是否出现房颤决定,还与既往房颤负荷、心房结构、年龄和伴随疾病有关。部分患者会出现无症状复发,普通门诊心电图也可能无法捕捉阵发性房颤。
-因此,抗凝治疗一般根据长期血栓栓塞风险决定,而不是只根据是否成功复律、消融或暂时没有症状决定。2024 年欧洲指南将房颤管理放在 AF-CARE 框架中,强调合并危险因素管理、避免卒中和血栓栓塞、减少症状以及动态评估治疗效果。[7:1]
-房颤的完整管理需要同时处理四个问题:评估并降低卒中和血栓栓塞风险;控制心率或恢复并维持窦律,以改善症状和心脏功能;管理高血压、肥胖、睡眠呼吸暂停、糖尿病、心力衰竭和饮酒等危险因素;持续监测药物安全性、肾功能、出血表现和房颤复发。
-节律控制可能改善症状,也可能在部分患者中改善长期结局,但它不能自动替代卒中风险评估。消融治疗也不等于血栓风险永久消失。治疗目标应从“消灭一次房颤”转向长期降低房颤负荷、卒中风险和心血管并发症。
+抗凝治疗通常依据长期血栓栓塞风险决定。复律、消融或症状暂时消失,并不能单独决定停药。2024 年欧洲指南将房颤管理放在 AF-CARE 框架中,强调危险因素管理、卒中和血栓栓塞预防、症状控制以及治疗效果的动态评估。[7:1]
+房颤管理包括四项工作。医生需要评估卒中和血栓栓塞风险,控制心率或恢复并维持窦律,处理高血压、肥胖、睡眠呼吸暂停、糖尿病、心力衰竭和饮酒等危险因素,并监测药物安全性、肾功能、出血表现和房颤复发。
+节律控制可以改善症状,并可能改善部分患者的长期结局,但仍需持续评估卒中风险。消融治疗后也要根据长期风险决定抗凝方案。治疗目标是降低房颤负荷、卒中风险和心血管并发症。
如果房颤患者突然出现单侧肢体无力或麻木、口角歪斜、说话含糊、理解困难、视物异常、行走不稳或突发剧烈头痛,应立即按照卒中急救流程就医。症状即使自行缓解,也可能是短暂性脑缺血发作,不能等待观察。
正在服用抗凝药的患者,如果出现持续性呕血、黑便、血尿、无法止住的鼻出血、严重头痛、意识变化或跌倒撞击头部,也需要尽快就医。不要因为担心出血而自行停药,也不要因为漏服一次而擅自加倍补服。
房颤与血栓栓塞的关系,可以归纳为一条连续的病理链:心房失去有效收缩,血流在左心耳等部位淤滞;心房结构、内皮和凝血状态发生改变;血栓形成并可能脱落;栓子进入脑循环后造成缺血性卒中。
-真正有价值的房颤管理,不是只关注心电图上的节律,也不是只关注心率数字,而是同时回答三个问题:患者的血栓风险有多高,抗凝的获益是否超过出血风险,以及如何降低房颤本身和相关基础疾病的负荷。对个体患者而言,具体药物、剂量和停药时机必须由医生结合病史、肾功能、年龄、合并用药和出血情况决定。
+房颤增加血栓栓塞风险的过程可以概括为:心房失去有效收缩,血流在左心耳等部位淤滞;心房结构、内皮和凝血状态发生改变;血栓形成并可能脱落;栓子进入脑循环后造成缺血性卒中。
+房颤管理需要回答三个问题:患者的血栓风险有多高,抗凝获益是否超过出血风险,以及怎样降低房颤和相关基础疾病的负荷。具体药物、剂量和停药时机,应由医生结合病史、肾功能、年龄、合并用药和出血情况决定。