大厂技术坚持周更精选好文|飞书aPaaS

大厂技术坚持周更精选好文|飞书aPaaS

本文来自飞书aPaaS Growth研发团队成员,已获得ELab授权发布。

aPaaS Growth团队专注于用户可感知的、宏观层面的aPaaS应用构建流程,以及租户、应用治理等产品路径。 致力于为aPaaS平台打造流畅的“应用交付”流程和体验,完善与应用建设相关的生态系统,增强应用建设的便利性和可靠性,提高应用的整体性能,从而帮助应用的用户增长。 aPaaS,与基础团队共同推动aPaaS在企业内外的落地和效率提升。

背景 1:定义 SSOT

问:在 SwiftUI 上下文中llvm 游戏引擎支持更多语言,单一事实来源 (SSOT) 的含义是什么?

A:使用SwiftUI,你既可以务实地编写代码,也可以使用设计工具来编辑UI,这也会导致SwiftUI代码被修改。 本质上,您只有源代码,没有单独的设计文件(即 nib 或 Storyboard[1](2016)),这意味着您的 UI 设计和处理 UI 的代码不可能不同步(以前的 nib 文件或故事板就是这种情况)。

背景2:什么是程序和语言? 什么是计算机程序?

计算机程序是编程语言[2]中供计算机[3]执行[执行]((计算“执行”))的序列或指令集。

什么是编译型语言

%E7%B7%A8%E8%AD%AF%E8%AA%9E%E8%A8%80

编译语言(英语:Compiled language)是一类通过编译器实现的编程语言[4][5]。 它不像解释语言[6],解释器逐句执行代码。 相反2d素材,编译器首先将代码[7]编译为机器代码[8],然后执行它。 理论上,任何编程语言都可以编译或直译。 它们之间的区别仅与程序的应用有关。

什么是分析语言

%E7%9B%B4%E8%AD%AF%E8%AA%9E%E8%A8%80

解释性语言(英语:Interpreted language)是编程语言的一种[9]​​。 这种类型的编程语言直接逐句执行代码。 它不需要由编译器[11]编译成机器代码[12],然后像编译语言[10]一样执行。 这种编程语言需要使用解释器[13]。 在执行期间,代码被动态地逐句解释(interpret)为机器代码,或者是已经预编译为机器代码的子程序[14],然后执行。

编程语言应该遵循的数学模型以及编程语言的发展历史

首先,每种语言至少应该具有图灵完备性。 至于什么是图灵完备性,可以参考我之前的分享:证明JS和TS类型编程是图灵完备的[15],简而言之,一种语言只要能实现三种基本功能和三种基本组合,那么它是图灵完备的,绝对可以表达其他图灵完备语言可以表达的逻辑。 注意,这里所说的是纯粹的逻辑,从数学的角度来看。 看来实现一个功能,输入和输出属于同一个域。 如果有新域,则必须在上下文中添加输入。 例如,设备/文件IO需要机器指令的支持。

编程语言都是形式语言(Formal Language[16]),而形式语言的研究早在计算机出现之前就由语言学家提出了。

形式语言的首次使用被认为是 Gottlob Frege[17] 1879 年的 Begriffsschrift[18],意思是“概念写作”,它描述了一种“以算术语言为模型的形式语言,用于纯粹的思考。”([2 ])

需要注意的是,图灵是否完备与语法是否简单并无直接关系。 对于语法非常简单但是图灵完备的语言,可以参考: ,一些我们认为表达力还不错的常用语言其实并不是图灵完备的。 完整的(比如微信的WXML,或者UIDL),原因很简单,就是它们无法实现部分递归函数必须具备的“最小化”操作,即无法实现while循环。

当我们回顾计算机语言的发展过程时,我们会发现计算机语言的语法是一个从简单到复杂的过程。 最初,我们用打孔卡来表示程序()3D动画,程序本质上是一串数字。 后来,机器被发明了。 代码基本上就是数字和一些助记词一一对应,然后指令后面跟着内存地址来表达程序。 后来汇编增加了“过程”的概念,后来有了像Lisp这样的语言,增加了“表达式”的概念。 后来Lisp的方言越来越多,增加了“函数”和“语句”。 概念。 后来,我们有了更正式的现代语言 C,它添加了块和控制流等概念。 后来我们有了Java这样的面向对象语言,它增加了面向对象设计相关的概念(类、接口、封装、多态、继承),现在我们有了ES 2022、Swift、Golang、Rust和还有很多。 语言llvm 游戏引擎支持更多语言,针对不同的领域,它们有不同的语法和特性。

回顾整个过程,是一个从简单到复杂、从易学到难学、表达力从弱到强、从不实用到实用、从易解析到难解析的过程。 过程。

以下纯属个人观点:一种语言很难面面俱到。 每种语言通常都有其适用的场景,常常面临类似于三维悖论的场景[19](当然,可以引入更多维度,形成四五六七八十九悖论)。 关于...),例如:

引擎游戏_引擎对于游戏的作用_llvm 游戏引擎支持更多语言

图片.png

比如Javascript这样的分析型语言,语法比较简单,表现力比较强(支持面向对象编程、async wait语法、function as First Citizen……),但是它们的性能会比较弱,因为你无法控制锁。 ,如果没有锁,需要引入eventloop,造成性能消耗; 如果没有内存控制,就需要引入GC,造成性能消耗。

另一个例子是 Rust 中内存所有权的引入。 语言的学习复杂度骤然增加,但在性能场景中也能在性能和表现力方面做得更好。

背景 3:简单的分析语言实现

话虽如此,在正式介绍 XCode + SwiftUI 之前,我需要先介绍一下一种语言是如何解析的。 我们以最简单的语言之一Lisp为例,用最简单的自循环解析器来讲解。

图片.png

假设我们有一个简单的 Lisp 程序:

// 语义为:(60 * 9 / 5) + 32
(+ (* (/ 9 5) 60) 32)

那么解析器程序的第一步会执行tokenize程序,结果是:

[
  "(",
  "+",
  "(",
  "*",
  "(",
  "/",
  "9",
  "5",
  ")",
  "60",
  ")",
  "32",
  ")"
]

第二步是执行解析并将 token 列表转换为 AST:

[
  "+",
  [
    "*",
    [
      "/",
      9,
      5
    ],
    60
  ],
  32
]

第三步是解析 AST。 解析过程本质上是一个深度递归的自下而上的评估过程。 例如,上述AST的评估过程如下:

// 输入
[
  "+", // <- 第一层指针,发现子属性是数组,先求数组的值
  [
    "*", // <- 第二层指针,发现子属性是数组,先求数组的值
    [
      "/", // <- 第二层指针,没有子属性是数组了,不需要递归了,在这里求第一次值
      9,
      5
    ],
    60
  ],
  32
]

// 第一遍求值
[
  "+",
  [
    "*",
    1.8,
    60
  ],
  32
]

// 第二遍求值
[
  "+",
  108,
  32
]

// 第三遍求值
140

完整的Demo请参考:

function interp(x, env) {
    env = env || g;
    if (typeof x === "string") { // symbol
        return env.find(x)[x];
    }
    else if (!Array.isArray(x)) { // constant literal
        return x;
    }
    else if (x[0] === "quote") { // (quote exp)
        let exp = x[1];
        return exp;
    }
    else if (x[0] === "if") { // (if test conseq alt)
        let test = x[1], conseq = x[2], alt = x[3];
        let exp = interp(test, env) ? conseq : alt;
        return interp(exp, env);
    }
    else if (x[0] === "define") { // (define symbol exp)
        let symbol = x[1], exp = x[2];
        env[symbol] = interp(exp, env);
    }
    else if (x[0] === "set!") { // (set! symbol exp)
        let symbol = x[1], exp = x[2];
        return (env.find(symbol)[symbol] = interp(exp, env));
    }
    else if (x[0] === "eval") { // custom shenanigans
        let exp = interp(x[1], env);
        return interp(exp, env);
    }
    else if (x[0] === "lambda") { // (lambda (symbol...) body)
        let parms = x[1], body = x[2];
        return makeProc(parms, body, env);
    }
    else {
        let proc = interp(x[0], env);
        let args = x.slice(1).map(exp => interp(exp, env));
        if (typeof proc !== "function") {
            throw new Error("Expected function, got " + (proc || "").toString());
        }
        return proc.apply(proc, args);
    }
}

同时,如果我们稍微添加一个包装器,我们就可以得到这个程序的调用堆栈。

let stack = [];
function wrap(func) {
  return function(...args) {
    stack.push(args[0]);
    let resp = func(...args);
    stack.pop();
    return resp;
  };
}
interp = wrap(interp);

好像到这里,你知道什么是stackoverflow异常吗? 本质上,我们的程序在 AST 上进行递归,并在递归过程中不断将内容压入堆栈。 如果程序写得不好,堆栈空间就会溢出。

怎么样,这段代码是不是感觉很熟悉? 如果我们打开kunlun-fe的parseComponentMeta.ts文件,你会发现它也是一个自循环解析器:

export function parseComponentMeta(
  meta: ComponentMeta,
  components: Components = {},
  ...
): JSX.Element {
  const { name, type, children, events, selectors: selectorMeta } = meta;
  ...
  const { props = {} } = meta;
  const { key: propKey } = props;
  if (propKey === undefined) {
    // props = { ...props, key: name };
    props.key = name;
  }

  props.__component_name__ = name;

  let normalizedChildren = null;
  if (typeof children === 'string') {
normalizedChildren = children;
  } else if (Array.isArray(children) && children.length > 0) {
normalizedChildren = children. map ( ( childMeta ) =>
 parseComponentMeta (
childMeta,
components,
connect,
stateKey,
payload,
componentCache,
selectors,
decorator,
),
);
  }

  if (isHostComponent(type)) {
    return createElement(type, props, normalizedChildren);
  }

  let ComponentType = deepGet(components, type) as React.ComponentType;
  if (ComponentType === undefined) {
    window.console.error(type' is not found in components:', components);
    ComponentType = NotFound;
  }
  if (events !== undefined && connect === undefined) {
    throw new DangerousCustomErrorWithoutSensitiveMessage({
      label: 'page-meta-engine',
      message: '"connect" is required when "events" passed.',
    });
  }
  if (selectorMeta !== undefined && connect === undefined) {
    throw new DangerousCustomErrorWithoutSensitiveMessage({
      label: 'page-meta-engine',
      message: '"connect" is required when "selectors" passed.',
    });
  }
  if (isInBlacklistOfConnect(type) || connect === undefined) {
    return createElement(ComponentType, props, normalizedChildren);
  }
  
  // 做了一些 redux wrapping 相关的东西
  return ...
}

换个角度思考,昆仑的UI Meta或者后续的UIDL直接定义了一套AST,然后实现了一个自循环的解析器。

延伸思考:

如果我现在需要使用UI Meta或者UIDL来实现一个无限加载列表组件,可以实现吗? 如果你扩展 UI Meta 而不实现自定义 React 组件,你会引入什么样的 Meta 属性? 这些属性的原子操作是什么? 你如何解析它?

如果我想在UI Meta中添加条件渲染功能,应该如何实现?

如果我们实现一个JS解析器会不会很困难? 事实上,这并不是很难。 如果不考虑效率,我们只需要1000行代码就可以实现ES5的AST的eval,从而实现ES5的语义。

我们的 ES AST 比 Lisp 细节丰富得多,也更容易理解。 例如,对于同一个表达式,ES表达式是这样的:

#/要点/c40c85b756de9a4e10fb5bfe668fa000/ff2ab3d89b593035af82b97cddf72a68910dcab9

{
  "type""File",
  },
  "errors": [],
  "program": {
    "type""Program",
    },
    "sourceType""module",
    "interpreter": null,
    "body": [
      {
        "type""ExpressionStatement",
        },
        "expression": {
          "type""BinaryExpression",
          },
          "left": {
            "type""BinaryExpression",
            },
            "left": {
              "type""BinaryExpression",
              },
              "left": {
                "type""NumericLiteral",
                },
                "extra": {
                  "rawValue": 60,
                  "raw""60"
                },
                "value": 60
              },
              "operator""*",
              "right": {
                "type""NumericLiteral",
                },
                "extra": {
                  "rawValue": 9,
                  "raw""9"
                },
                "value": 9
              }
            },
            "operator""/",
            "right": {
              "type""NumericLiteral",
              },
              "extra": {
                "rawValue": 5,
                "raw""5"
              },
              "value": 5
            },
            "extra": {
              "parenthesized"true,
              "parenStart": 0
            }
          },
          "operator""+",
          "right": {
            "type""NumericLiteral",
            },
            "extra": {
              "rawValue": 32,
              "raw""32"
            },
            "value": 32
          }
        }
      }
    ],
    "directives": []
  },
  "comments": []
}

XCode + SwiftUI 界面设计经验

llvm 游戏引擎支持更多语言_引擎对于游戏的作用_引擎游戏

文章来源:http://mp.weixin.qq.com/s?src=11×tamp=1700439108&ver=4907&signature=uy1b*mJj9wfS64bsjcf0ZzOGobM3Euofs6Kbpip8p6k8HvKK-Fr90PSOROPpXHwiFE41q5Tfii9bZv*nDsOGBOOb3etx3BAPuAz0i5i6JRanPXW9-Y0veIUDvUsbGn8j&new=1