nim string

string difinition

lib/system.nim

    NimStringDesc {.compilerproc, final.} = object of TGenericSeq
      data: UncheckedArray[char]
    NimString = ptr NimStringDesc

lib/system/sysstr

strings are dynamically resized, have a length field
and are zero-terminated, so they can be casted to C
strings easily
we don’t use refcounts because that’s a behaviour
the programmer may not want

cstring and nim string conversation

var cstr:cstring 
var nimstr = $cstr
cstr = cstr.cstring  
``

##  string and sequence conversation  
``` nim
var s: seq[char] = @['A', 'b', 'C']
var t: string = cast[string](s)
import sequtils
var s = toSeq("abc".items)

proc toString(str: seq[char]): string =
  result = newStringOfCap(len(str))
  for ch in str:
    add(result, ch)

echo toString(s)

optimizing-for-nim-optimizing-string-handling

optimizing-for-nim-optimizing-string-handling

Read More

开源的webview库介绍

zserge/webview 是一个小巧的跨平台webview库。

官方支持go binding,还有其他语言的binding Rust bindings, Python bindings, Nim bindings, Haskell, C# bindings Java bindings

支持双向的JavaScript bindings

使用 Cocoa/WebKit 在 macOS, gtk-webkit2 在 Linux , Edge 在 Windows 10.

需要注意的是,webview目前使用 C++14 作为主要语言,c语言实现的最近版本是
v0.0.1

经过实践发现webview在Macos下使用的API有点过时了,Catalina 下app 初次运行菜单栏无法点击,切换到其他应用再切换回来才可以。另外没有使用pasteBoard API,无法在应用外copy再paste到应用,可以简单的增加菜单栏项目绑定快捷键但官方更希望使用pasteBoard API,目前还没有实现。

Read More

tsc 能否作为bundler以避免项目依赖庞杂的工具链?

最近我在思考“ tsc 能否作为bundler以避免项目依赖庞杂的工具链?”,既然tsc 可以编译成不同的module形式以及不同的ecma语法标准,为何我还需要用rollup来打包库或者其他的bundler工具来打包项目呢?

tsconfig.json 里有 outFile 选项,我能否使用这个选项来bundler出单独的一个js文件呢? 当我尝试bundle 我的commonjs库时获知 outFile can only be used for system/AMD modules.

ts-bundle 搜寻到这个库,发现有人尝试实现同样的想法。

Read More

web技术构建桌面应用框架对比

先从我实际开发过的electron谈起,不可否认electron非常强大,提供的API很完善,文档也很详尽。
但我在开发中注意到electron打包后的应用(unziped)有100多MB,如果加上网页要显示Flash还需要bundle Flash插件,也就更大了。另外Macos下应用可以查看应用内容,源码直接呈现出来,查看相关issue,electron并没有计划提供支持。NWjs据说支持加密源码,我还没有尝试过。

DeskGap
Neutralino

使用electron 和 NWjs 需要安装很多依赖包,和内嵌Chromium,Nodejs,所以打包尺寸才会非常大。
DeskGap 和 Neutralino 则调用各平台的 web engine接口,框架的代码大部分是c++写的。

尝试了下 Neutralino 的开发体验 ,build 完之后,执行 executable,并没有hot reload or live reload.

三个平台的可执行文件在neu create的时候已经存在了。
build直接用的webpack build客户端,可执行文件包含服务端和内置的neutralino.js客户端。

在MacOS平台下缺少copy paste功能,只能在webview内或者单向的从app到平台,从平台copy paste到app则不行。
这点和zserge/webview 是一样的, 至少我从issue和实际运行v0.1.1 c语言版本的情况来说。

Read More

React和Vue的数据传递对比

通过属性传递

Vue

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>

React

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

const element = <Welcome name="Sara" />;

通过事件传递

React

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, {count: initialCount});
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

Vue

Read More

vue-router 和 react-dom-router对比

router对象类型

vue 把 VueRouter作为一个对象,而React 把router作为一个组件。

html5 history api模式和hash模式

vue

vue router实例作为vue instance实例的一个属性,可以配置vue router实例的mode'hash' 或者 'history'

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

react

react-router-domBrowserRouter,HashRouter 分为两个组件。

import {
  Switch,
  Route,
  BrowserRouter
} from "react-router-dom";

使用方式上的不同

Read More

dart flutter中的多线程isolate包的使用

使用多线程的目的是为了避免长时间执行的任务影响UI线程绘制界面,造成界面卡顿,影响用户体验(开发者自身也是第一个用户,所以尤为重要)。
首先引入dart:isolate

import 'dart:isolate';

在需要使用isolate的 async 函数中初始化ReceivePort 即接收端

ReceivePort receivePort = ReceivePort();

注意:本例中不需要调用isolate实例的方法或者isolate.controlPort获取SendPort

var isolate = await Isolate.spawn(runGetDirectorySize, receivePort.sendPort,
        onExit: receivePort.sendPort);

    receivePort.listen((data) {
      _scan(data);
    });

分步拆解:

Isolate.spawn

接受一个void Function(T),在本例中runGetDirectorySize来获取文件目录大小. 这里的T即为receivePort.sendPort
也就是我们调用Isolate.spawn的第二个参数。

同时我们传入一个onExit:receivePort.sendPort可选参数,
runGetDirectorySize执行完毕退出时会给这个receivePort.sendPort发送一个null数据,此时我们可以根据receivePort.listen接收到的data是否为null来判断线程是否执行完毕,比如执行完后更新ui显示目录大小或者为空。

Read More

透过React typescript definition文件看React组件设计

分析时版本:

"react": "^16.13.1",
"@types/react": "^16.9.0",

先从React 实例看起

type ReactInstance = Component<any> | Element;

一个ReactInstance可以是React定义的组件(Component<any>)或者是lib dom定义的Element

// Base component for plain JS classes
// tslint:disable-next-line:no-empty-interface
interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> { }

可以看到Component继承自ComponentLifecycle,也就是我们经常会用到的生命周期接口了。

interface ComponentLifecycle<P, S, SS = any> extends NewLifecycle<P, S, SS>, DeprecatedLifecycle<P, S> {

        componentDidMount?(): void;

        shouldComponentUpdate?(nextProps: Readonly<P>, nextState: Readonly<S>, nextContext: any): boolean;

        componentWillUnmount?(): void;

        componentDidCatch?(error: Error, errorInfo: ErrorInfo): void;
    }

从注释看NewLifecycle<P, S, SS>是为了向下兼容设计的一个生命周期interface

 // This should be "infer SS" but can't use it yet
    interface NewLifecycle<P, S, SS> {
        /**
         * Runs before React applies the result of `render` to the document, and
         * returns an object to be given to componentDidUpdate. Useful for saving
         * things such as scroll position before `render` causes changes to it.
         *
         * Note: the presence of getSnapshotBeforeUpdate prevents any of the deprecated
         * lifecycle events from running.
         */
        getSnapshotBeforeUpdate?(prevProps: Readonly<P>, prevState: Readonly<S>): SS | null;
        /**
         * Called immediately after updating occurs. Not called for the initial render.
         *
         * The snapshot is only present if getSnapshotBeforeUpdate is present and returns non-null.
         */
        componentDidUpdate?(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot?: SS): void;
    }

Read More

React Strict Mode(严格模式)摘要

严格模式
StrictMode 是一个用来突出显示应用程序中潜在问题的工具。与 Fragment 一样,StrictMode 不会渲染任何可见的 UI。它为其后代元素触发额外的检查和警告。

注意:严格模式检查仅在开发模式下运行;它们不会影响生产构建。

你可以为应用程序的任何部分启用严格模式。例如:


import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}

在上述的示例中,不会对 Header 和 Footer 组件运行严格模式检查。但是,ComponentOne 和 ComponentTwo 以及它们的所有后代元素都将进行检查。

StrictMode 目前有助于:

  • 识别不安全的生命周期
  • 关于使用过时字符串 ref API 的警告
  • 关于使用废弃的 findDOMNode 方法的警告
  • 检测意外的副作用
  • 检测过时的 context API
  • 未来的 React 版本将添加更多额外功能。

当启用严格模式时,React 会列出使用了不安全生命周期方法的所有 class 组件,并打印一条包含这些组件信息的警告消息,如下所示:

strict mode unsafe lifecycles warning
此时解决项目中严格模式所识别出来的问题,会使得在未来的 React 版本中使用 concurrent 渲染变得更容易。

Read More

使用Capistrano自动化部署

环境:
Centos 7
Capistrano v3
ruby 2.4.1
rails 5.2.3

Installation

install as Ruby Gem

gem install capistrano

Usage in a Rails project

group :development do
  gem "capistrano", "~> 3.10", require: false
  gem "capistrano-rails", "~> 1.3", require: false
end

bundle install

capistrano-rails

  • Asset Pipeline Support
    cap deploy:migrate
  • Database Migration Support
    cap deploy:compile_assets

    Usage

bundle exec cap install

Read More