电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

JS語法也可以有C#的switch表達式

瀏覽:129日期:2022-06-09 15:19:28
目錄
  • 正文
  • 新的約束
  • when 函數寫法
  • 分算等級”測試
    • 測試問題
    • 升級成 TypeScript

正文

于 C/Java 語系的語言,都有 switch 語法。switch 語法用于多分支是一個標準的用法,但這個分支語法的各分支之間存在穿透性,所以需要 break 來切斷邏輯,這也成為 switch 語法中最重要的一個替在缺陷來源。此外,由于 switch 語句中各 case 的代碼是在同一個作用域中,也會對代碼造成一些不便。

C# 8.0 引入了 switch 表達式。C# 的 switch 表達式有著非常豐富的語法元素,可以和模式匹配和解構等語法元素協同工作 —— 這些都不在這里細說,但是對傳統的 switch 語句 進行了一些改進:

  • 通過箭頭 (=>) 標記處理了 case 和語句之間的一對一關系,不需要 break,不再穿透;
  • 作為表達式,可以而且必須返回值;

新的約束

  • switch 表達式一定要詳盡(邏輯一定會走進某一個 case,可以通過棄元模式兜底),否則可能會在運行時引發(fā)異常。

在 C# 8.0 發(fā)布的同年,Java 12 也發(fā)布并引入了 switch 表達式預覽。Java 的 switch 表達式實現比較簡單,就是 switch 語句到 switch 表達式的直接轉換,僅支持等值匹配。直到 2023 年 3 月 Java 20 發(fā)布,switch 表達式才開始支持模式匹配。相比之下,Kotlin 的 when 表達式走在了前面。

在這個問題上 JavaScript 似乎走在了后面,不過在語言提供 switch 表達式之前,我們可以嘗試自己造個輪子。

思路當然是參考策略模式。假設有一個列表,這個列表里的每個元素都包含了兩個因素:第一個用于判斷是否命中,第二個是個函數,得到一個計算結果。然后寫一個循環(huán)遍歷列表的每個元素,一旦某個元素命中,就執(zhí)行元素攜帶的函數獲得結果,中斷循環(huán),返回結果。如果列表的最后一個元素必定命中,那么這個列表就是“詳盡”的。

when 函數寫法

那么這個 when 函數可能會這樣寫(switch 是關鍵字,所以使用 when 來作為函數名):

// JS
function when(value, ...cases) {
    for (const { is, run } of cases) {
if (is(value)) {
    return run(value);
}
    }
    throw new Error("非詳盡");
}

這里我們假設每個情況 (case) 都含有 is 方法用于判斷是否命中,用 run 方法保存命中后需要執(zhí)行的操作。

分算等級”測試

相應地,我們可以經典的“拿分算等級”來進行測試:

// JS
function calcGrade(score) {
    return when(
score,
{ is: v => v >= 0 && v < 80, run: v => `不合格 (${v})` },
{ is: v => v >= 80 && v < 100, run: v => `合格 (${v})` },
{ is: v => v == 100, run: v => `滿分 (${v})` },
{ is: _ => true, run: v => `無效 (${v})` },
    );
}
for (let i = 0; i < 50; i++) {
    const v = 70 + ~~(Math.random() * 35);
    console.log(calcGrade(v));
}

在 calcGrade 實現中 when 的 case 列表最后一項采用了“永真”斷言,所以走到這一項的時候一定會命中,從邏輯上來永遠不會觸發(fā) Error。如果是非“詳盡”的情況列表,就有可能觸發(fā) Error。

測試問題

不過現在從測試代碼中就發(fā)現了兩個問題:

  • is 斷言是采用函數的形式,不能簡單地直接按值匹配;
  • 從調用形式上來說,score 和后面的 case 元素是同級的,形式上區(qū)分不明顯;
  • 每次都要寫 is 和 run,條件多了寫起來也煩。

繼續(xù)改進 ——

// JS
function when(value) {
    // when 的參數先給 switch 的值
    // 返回一個函數來處理分支匹配 ②
    return function (...cases) {
for (const [is, run] of cases) {
// ^^^^^^^^^ 從對象改為元組(數組)③
    if (value === is || (typeof is == "function" && is(value))) {
//    ^^^^^^ 精確判斷 ①
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 斷言函數判斷
return  run(value);
//    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 可指定行為(函數)
    }
}
throw new Error("非詳盡");
    };
}
function calcGrade(score) {
    return when(score)(
// ^^^^^^^^^^^ 這里返回的是匹配處理的函數
[v => v >= 0 && v < 80, v => `不合格 (${v})`],
[v => v >= 80 && v < 100, v => `合格 (${v})`],
[100, () => "滿分 (100)"],
//       ^^^ 可以指定匹配的值
//    ^^ 計算不需要參數,可以不聲明
[_ => true, v => `無效 (${v})`],
//       ^^^^^^^^^ 兜底的永真斷言
    );
}

為什么兜底斷言必須使用一個函數呢?因為 true 值也有可能是對應一種預想的分支情況。由于這個 when 是通過語義來實現而不是通過語法來實現的,所以這里沒辦法定義一個安全的兜底斷言語法,只有用斷言函數會相對安全。

升級成 TypeScript

至此為止我們已經基本實現了 switch 表達式 (when),把它升級成 TypeScript

// TypeScript
type CaseCondition<T> = T extends Function ? never : ((t: T) => boolean) | T
type Case<T, R> = [CaseCondition<T>, (t: T) => R];
function when<T>(value: T): <R>(...cases: Case<T, R>[]) => R {
    return function<R>(...cases: Case<T, R>[]): R {
for (const [is, run] of cases) {
    if (value === is || (typeof is == "function" && is(value))) {
return run(value);
    }
}
throw new Error("非詳盡");
    };
}
function calcGrade(score: number) {
    return when(score)(
[v => v >= 0 && v < 80, v => `不合格 (${v})`],
[v => v >= 80 && v < 100, v => `合格 (${v})`],
[100, () => "滿分 (100)"],
[_ => true, v => `無效 (${v})`],
    );
}

這段代碼當然可以直接用,但是如果使用 npm 可能會更方便一點:

npm install @jamesfancy/when
// TypeScript
import { when } from "@jamesfancy/when";
function calcGrade(score: number) {
    return when(score)(
[v => v >= 0 && v < 80, v => `不合格 (${v})`],
[v => v >= 80 && v < 100, v => `合格 (${v})`],
[100, () => "滿分 (100)"],
[_ => true, v => `無效 (${v})`],
    );
}

以上就是JS語法也可以有C# 的switch表達式的詳細內容,更多關于JS語法C# switch表達式的資料請關注其它相關文章!

標簽: JavaScript
主站蜘蛛池模板: 一体化隔油提升设备-餐饮油水分离器-餐厨垃圾处理设备-隔油池-盐城金球环保产业发展有限公司 | 南京交通事故律师-专打交通事故的南京律师 | 缝纫客| 济南玻璃安装_济南玻璃门_济南感应门_济南玻璃隔断_济南玻璃门维修_济南镜片安装_济南肯德基门_济南高隔间-济南凯轩鹏宇玻璃有限公司 | 水篦子|雨篦子|镀锌格栅雨水篦子|不锈钢排水篦子|地下车库水箅子—安平县云航丝网制品厂 | 泰国专线_泰国物流专线_广州到泰国物流公司-泰廊曼国际 | 机床主轴维修|刀塔维修|C轴维修-常州翔高精密机械有限公司 | 磁力抛光机_磁力研磨机_磁力去毛刺机_精密五金零件抛光设备厂家-冠古科技 | 中高频感应加热设备|高频淬火设备|超音频感应加热电源|不锈钢管光亮退火机|真空管烤消设备 - 郑州蓝硕工业炉设备有限公司 | 单电机制砂机,BHS制砂机,制沙机设备,制砂机价格-正升制砂机厂家 单级/双级旋片式真空泵厂家,2xz旋片真空泵-浙江台州求精真空泵有限公司 | 高考志愿规划师_高考规划师_高考培训师_高报师_升学规划师_高考志愿规划师培训认证机构「向阳生涯」 | 东莞ERP软件_广州云ERP_中山ERP_台湾工厂erp系统-广东顺景软件科技有限公司 | 花纹铝板,合金铝卷板,阴极铝板-济南恒诚铝业有限公司 | 伶俐嫂培训学校_月嫂培训班在哪里报名学费是多少_月嫂免费政府培训中心推荐 | 淄博不锈钢,淄博不锈钢管,淄博不锈钢板-山东振远合金科技有限公司 | 仿古建筑设计-仿古建筑施工-仿古建筑公司-汉匠古建筑设计院 | 培训中心-海南香蕉蛋糕加盟店技术翰香原中心官网总部 | 一体化预制泵站-一体化提升泵站-一体化泵站厂家-山东康威环保 | 针焰试验仪,灼热丝试验仪,漏电起痕试验仪,水平垂直燃烧试验仪 - 苏州亚诺天下仪器有限公司 | 扬尘在线监测系统_工地噪声扬尘检测仪_扬尘监测系统_贝塔射线扬尘监测设备「风途物联网科技」 | 驾驶式洗地机/扫地机_全自动洗地机_工业洗地机_荣事达工厂官网 | 全自动烧卖机厂家_饺子机_烧麦机价格_小笼汤包机_宁波江北阜欣食品机械有限公司 | 高压绝缘垫-红色配电房绝缘垫-绿色高压绝缘地毯-上海苏海电气 | 法兰螺母 - 不锈钢螺母制造厂家 - 万千紧固件--螺母街 | 恒温恒湿试验箱厂家-高低温试验箱维修价格_东莞环仪仪器_东莞环仪仪器 | 【灵硕展览集团】展台展会设计_展览会展台搭建_展览展示设计一站式服务公司 | 发电机组|柴油发电机组-批发,上柴,玉柴,潍柴,康明斯柴油发电机厂家直销 | 超声波电磁流量计-液位计-孔板流量计-料位计-江苏信仪自动化仪表有限公司 | 下水道疏通_管道疏通_马桶疏通_附近疏通电话- 立刻通 | 彼得逊采泥器-定深式采泥器-电动土壤采样器-土壤样品风干机-常州索奥仪器制造有限公司 | 钢格板|镀锌钢格板|热镀锌钢格板|格栅板|钢格板|钢格栅板|热浸锌钢格板|平台钢格板|镀锌钢格栅板|热镀锌钢格栅板|平台钢格栅板|不锈钢钢格栅板 - 专业钢格板厂家 | 南溪在线-南溪招聘找工作、找房子、找对象,南溪综合生活信息门户! | 高扬程排污泵_隔膜泵_磁力泵_节能自吸离心水泵厂家-【上海博洋】 | 土壤检测仪器_行星式球磨仪_土壤团粒分析仪厂家_山东莱恩德智能科技有限公司 | 北京康百特科技有限公司-分子蒸馏-短程分子蒸馏设备-实验室分子蒸馏设备 | 广州展览制作|展台制作工厂|展览设计制作|展览展示制作|搭建制作公司 | 干式变压器厂_干式变压器厂家_scb11/scb13/scb10/scb14/scb18干式变压器生产厂家-山东科锐变压器有限公司 | 电脑刺绣_绣花厂家_绣花章仔_织唛厂家-[源欣刺绣]潮牌刺绣打版定制绣花加工厂家 | 冷却塔风机厂家_静音冷却塔风机_冷却塔电机维修更换维修-广东特菱节能空调设备有限公司 | 艺术生文化课培训|艺术生文化课辅导冲刺-济南启迪学校 | 半自动预灌装机,卡式瓶灌装机,注射器灌装机,给药器灌装机,大输液灌装机,西林瓶灌装机-长沙一星制药机械有限公司 |