NeoVim + dein の導入

はじめに

Mac にドキュメントエディタとして neovim を、neovim のプラグインマネージャとして dein をインストールします。

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G4032

1. neovim のインストール

homebrew で一発インストール

$ brew install nvim
$ nvim -version
NVIM v0.4.3
Build type: Release
LuaJIT 2.0.5
Compilation: /usr/local/Homebrew/Library/Homebrew/shims/mac/super/clang -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DNDEBUG -DMIN_LOG_LEVEL=3 -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wmissing-prototypes -Wimplicit-fallthrough -Wvla -fstack-protector-strong -fdiagnostics-color=auto -DINCLUDE_GENERATED_DECLARATIONS -D_GNU_SOURCE -DNVIM_MSGPACK_HAS_FLOAT32 -DNVIM_UNIBI_HAS_VAR_FROM -I/tmp/neovim-20191107-13403-1or2rj3/neovim-0.4.3/build/config -I/tmp/neovim-20191107-13403-1or2rj3/neovim-0.4.3/src -I/usr/local/include -I/tmp/neovim-20191107-13403-1or2rj3/neovim-0.4.3/deps-build/include -I/usr/local/opt/gettext/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -I/tmp/neovim-20191107-13403-1or2rj3/neovim-0.4.3/build/src/nvim/auto -I/tmp/neovim-20191107-13403-1or2rj3/neovim-0.4.3/build/include
Compiled by brew@Mojave.local

Features: +acl +iconv +tui
See ":help feature-compile"

      システム vimrc: "$VIM/sysinit.vim"
       省略時の $VIM: "/usr/local/Cellar/neovim/0.4.3/share/nvim"

Run :checkhealth for more info

2. neovim の設定

  • ~/.vimrc ではなく、~/.config/nvim/init.vim に設定を書きます。
  1. Configuration nvim-configuration

  2. Use $XDG_CONFIG_HOME/nvim/init.vim instead of .vimrc for configuration.

  3. Use $XDG_CONFIG_HOME/nvim instead of .vim to store configuration files.
  4. Use $XDG_DATA_HOME/nvim/shada/main.shada instead of .viminfo for persistent session information. |shada|

XDG_CONFIG_HOME

  • ユーザー個別の設定が書き込まれるディレクトリ (/etc と類似)。
  • デフォルトは $HOME/.config です。
$ mkdir ~/.config/nvim
  • ~/.config/nvim/init.vim の作成
" Configuration
colorscheme desert
filetype plugin indent on
syntax on
syntax enable
set termguicolors
set tabstop=4 softtabstop=4 expandtab shiftwidth=4 smarttab
set list
set listchars=tab:»-,trail:-,eol:,extends:»,precedes:«,nbsp:%
set number
set autoindent
set fenc=utf-8
set noswapfile
set autoread
set hidden
set showcmd
set cursorline
set cursorcolumn
set visualbell
set showmatch
set laststatus=2
set wildmode=list:longest

set ignorecase
set smartcase
set incsearch
set wrapscan

"" FileType
autocmd FileType python setl autoindent
autocmd FileType python setl smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class
autocmd FileType python setl tabstop=8 expandtab shiftwidth=4 softtabstop=4
autocmd FileType r setl tabstop=4 expandtab shiftwidth=2 softtabstop=2
autocmd BufNewFile,BufRead *.gvy setfiletype groovy
autocmd BufNewFile,BufRead *.ts setfiletype typescript
autocmd BufNewFile,BufRead *.tsx,*.jsx setfiletype=typescript.tsx

"" Map Leader
let mapleader = "\<Space>"
let maplocalleader = "\<Space>"

"" Custom Key Mapping
nnoremap ; :
nnoremap : ;
inoremap <silent> jj <ESC>
nnoremap <Leader>o :CtrlP<CR>
nnoremap <Leader>w :w<CR>
vmap <Leader>y "+y
vmap <Leader>d "+d
nmap <Leader>p "+p
nmap <Leader>P "+P
vmap <Leader>p "+p
vmap <Leader>P "+P
nmap <Leader><Leader> V
map <C-n> ;NERDTreeToggle<CR>
nnoremap s <Nop>
nnoremap sj <C-w>j
nnoremap sk <C-w>k
nnoremap sl <C-w>l
nnoremap sh <C-w>h
nnoremap sJ <C-w>J
nnoremap sK <C-w>K
nnoremap sL <C-w>L
nnoremap sH <C-w>H
nnoremap sn gt
nnoremap sp gT
nnoremap sr <C-w>r
nnoremap s= <C-w>=
nnoremap sw <C-w>w
nnoremap so <C-w>_<C-w>|
nnoremap sO <C-w>=
nnoremap sN :<C-u>bn<CR>
nnoremap sP :<C-u>bp<CR>
nnoremap st :<C-u>tabnew<CR>
nnoremap sT :<C-u>Unite tab<CR>
nnoremap ss :<C-u>sp<CR>
nnoremap sv :<C-u>vs<CR>
nnoremap sq :<C-u>q<CR>
nnoremap sQ :<C-u>bd<CR>

3. dein.vim のインストール

$ curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
$ sh ./installer.sh ~/.cache/dein

4. dein.vim の設定

  • インストール後に表示される通り、以下の設定を ~/.config/nvim/init.vim に追記します。
"dein Scripts-----------------------------
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=~/.cache/dein/repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('~/.cache/dein')
  call dein#begin('~/.cache/dein')

  " Let dein manage dein
  " Required:
  call dein#add('~/.cache/dein/repos/github.com/Shougo/dein.vim')

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
"if dein#check_install()
"  call dein#install()
"endif

"End dein Scripts-------------------------
if dein#load_state('~/.cache/dein')
  call dein#begin('~/.cache/dein')

  " Let dein manage dein
  " Required:
  call dein#add('~/.cache/dein/repos/github.com/Shougo/dein.vim')

+ call dein#load_toml('~/.config/nvim/dein.toml')
+ call dein#load_toml('~/.config/nvim/dein_lazy.toml', { 'lazy': 1 })

  " Required:
  call dein#end()
  call dein#save_state()
endif

CSV で Vector プロパティをロードする

環境

Oracle Graph Server Shell 20.1.0
PGX server version: 19.4.0 type: SM
PGX server API version: 3.6.0
PGQL version: 1.2

前提

  • Pgx Server で allow_local_filesystem が true になっており、かつ datasource_dir_whitelist/opt/oracle/oradata ディレクトリが指定されている
$ cat /etc/oracle/graph/pgx.conf
{
  "allow_local_filesystem": true,
  "datasource_dir_whitelist": ["/opt/oracle/oradata"],
...
}
  • Pgx Server が稼働するサーバの /opt/oracle/oradata/opt/oracle/oradata/sample.vertices.csv/opt/oracle/oradata/sample.edges.csv が格納されている。

/opt/oracle/oradata/vector_props.vertices.csv

1,1;2;3,0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;91;92;93;94;95;96;97;98;99,0.0;0.01;0.02;0.03;0.04;0.05;0.06;0.07;0.08;0.09;0.1;0.11;0.12;0.13;0.14;0.15;0.16;0.17;0.18;0.19;0.2;0.21;0.22;0.23;0.24;0.25;0.26;0.27;0.28;0.29;0.3;0.31;0.32;0.33;0.34;0.35;0.36;0.37;0.38;0.39;0.4;0.41;0.42;0.43;0.44;0.45;0.46;0.47;0.48;0.49;0.5;0.51;0.52;0.53;0.54;0.55;0.56;0.57;0.58;0.59;0.6;0.61;0.62;0.63;0.64;0.65;0.66;0.67;0.68;0.69;0.7;0.71;0.72;0.73;0.74;0.75;0.76;0.77;0.78;0.79;0.8;0.81;0.82;0.83;0.84;0.85;0.86;0.87;0.88;0.89;0.9;0.91;0.92;0.93;0.94;0.95;0.96;0.97;0.98;0.99,"hoge0;hoge1;hoge2;hoge3;hoge4;hoge5;hoge6;hoge7;hoge8;hoge9;hoge10;hoge11;hoge12;hoge13;hoge14;hoge15;hoge16;hoge17;hoge18;hoge19;hoge20;hoge21;hoge22;hoge23;hoge24;hoge25;hoge26;hoge27;hoge28;hoge29;hoge30;hoge31;hoge32;hoge33;hoge34;hoge35;hoge36;hoge37;hoge38;hoge39;hoge40;hoge41;hoge42;hoge43;hoge44;hoge45;hoge46;hoge47;hoge48;hoge49;hoge50;hoge51;hoge52;hoge53;hoge54;hoge55;hoge56;hoge57;hoge58;hoge59;hoge60;hoge61;hoge62;hoge63;hoge64;hoge65;hoge66;hoge67;hoge68;hoge69;hoge70;hoge71;hoge72;hoge73;hoge74;hoge75;hoge76;hoge77;hoge78;hoge79;hoge80;hoge81;hoge82;hoge83;hoge84;hoge85;hoge86;hoge87;hoge88;hoge89;hoge90;hoge91;hoge92;hoge93;hoge94;hoge95;hoge96;hoge97;hoge98;hoge99"

/opt/oracle/oradata/vector_props.edges.csv

1,2,1;2;3

CSV ファイルをロードする

var gcb = GraphConfigBuilder.forFileFormat(Format.CSV).
            addVertexUri("/opt/oracle/oradata/vector_props.vertices.csv").
            addEdgeUri("/opt/oracle/oradata/vector_props.edges.csv")

// Vector タイプの PropertyType. 第三引数で次元を指定
gcb.addVertexVectorProperty("vp_vector_int", PropertyType.INTEGER, 3)
gcb.addVertexVectorProperty("vp_vector_long", PropertyType.LONG, 100)
gcb.addVertexVectorProperty("vp_vector_double", PropertyType.DOUBLE, 100)
gcb.addVertexVectorProperty("vp_vector_string", PropertyType.STRING, 100)
gcb.addEdgeVectorProperty("ep_vector_int", PropertyType.INTEGER, 3)

var g = session.readGraphWithProperties(gcb.build())

// Vector 型のプロパティの値の取り出し方
var vec_v_int_prop = g.getVertex(1).getProperty("vp_vector_int")
// => vec_v_int_prop ==> PgxVect[type=integer,dimension=3]

var vec_v_int = (oracle.pgx.common.util.vector.Vect<Integer>) (vec_v_int_prop)
/*
 * |  Warning:
 * |  unchecked cast
 * |    required: oracle.pgx.common.util.vector.Vect<java.lang.Integer>
 * |    found:    java.lang.Object
 * |  var vec_v_int = (oracle.pgx.common.util.vector.Vect<Integer>) (vec_v_int_prop);
 * |                                                                ^--------------^
 * vec_v_int ==> PgxVect[type=integer,dimension=3]
 */

vec_v_int.toArray()
// $231 ==> Integer[3] { 1, 2, 3 }

// String 型の vector は java.lang.NullPointerException が発生する
g.getVertex(1).getProperty("vp_vector_string")
/*
 *  Exception java.util.concurrent.ExecutionException: java.lang.NullPointerException
 *|        at CompletableFuture.reportGet (CompletableFuture.java:395)
 *|        at CompletableFuture.get (CompletableFuture.java:1999)
 *|        at PgxFuture.get (PgxFuture.java:99)
 *|        at PgxEntity.getProperty (PgxEntity.java:280)
 *|        at (#284:1)
 *|  Caused by: java.lang.NullPointerException
 *|        at PgxEntity.lambda$getPropertyAsync$1 (PgxEntity.java:191)
 *|        at CompletableFuture$UniCompose.tryFire (CompletableFuture.java:1072)
 *|        at CompletableFuture.postComplete (CompletableFuture.java:506)
 *|        at CompletableFuture.complete (CompletableFuture.java:2073)
 *|        at PgxFuture.completeWithResultOrException (PgxFuture.java:55)
 *|        at CompletableFuture.uniWhenComplete (CompletableFuture.java:859)
 *|        at CompletableFuture$UniWhenComplete.tryFire (CompletableFuture.java:837)
 *|        at CompletableFuture.postComplete (CompletableFuture.java:506)
 *|        at CompletableFuture.complete (CompletableFuture.java:2073)
 *|        at PgxRemoteFuture.executeRequest (PgxRemoteFuture.java:107)
 *|        at PgxRemoteFuture.lambda$fetchRemoteResultAsync$3 (PgxRemoteFuture.java:218)
 *|        at ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1128)
 *|        at ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:628)
 *|        at Thread.run (Thread.java:834)
 */

Graph Config Json からロードする方法

  • クライアント側に以下の JSON ファイルを用意する (/tmp/vector_prps_csv.json)
{
    "format": "csv",
    "edge_props": [{
        "type": "integer",
        "name": "ep_vector_int",
        "dimension": 3
    }],
    "error_handling": {},
    "vertex_id_type": "integer",
    "vertex_uris": ["/opt/oracle/oradata/vector_props.vertices.csv"],
    "attributes": {},
    "edge_uris": ["/opt/oracle/oradata/vector_props.edges.csv"],
    "loading": {},
    "vertex_props": [{
        "type": "integer",
        "name": "vp_vector_int",
        "dimension": 3
    }, {
        "type": "long",
        "name": "vp_vector_long",
        "dimension": 100
    }, {
        "type": "double",
        "name": "vp_vector_double",
        "dimension": 100
    }]
}
  • PGX Client を起動して、Graph をロードする
// Graph Config Json ファイルは PGX Client 側に配置されているものを読みにいく
var g = session.readGraphWithProperties("/tmp/vector_props_csv.json")

ローカルにある CSV で Graph をロードする

環境

Oracle Graph Server Shell 20.1.0
PGX server version: 19.4.0 type: SM
PGX server API version: 3.6.0
PGQL version: 1.2

前提

  • Pgx Server で allow_local_filesystem が true になっており、かつ datasource_dir_whitelist/opt/oracle/oradata ディレクトリが指定されている
$ cat /etc/oracle/graph/pgx.conf
{
  "allow_local_filesystem": true,
  "datasource_dir_whitelist": ["/opt/oracle/oradata"],
...
}
  • Pgx Server が稼働するサーバの /opt/oracle/oradata/opt/oracle/oradata/sample.vertices.csv/opt/oracle/oradata/sample.edges.csv が格納されている。

/opt/oracle/oradata/sample.vertices.csv

1,VL,0.1,1,1,true,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.1,"hoge",2,4
2,VL,-2.0,2,100000000000000000,false,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.2,"hage",3,1
3,VL,0.3,-3,-2222222222222222,false,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.3,"hige",4,4
4,VL,4.56789,3,-3333333333333,true,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.4,"huga",1,2

/opt/oracle/oradata/sample.edges.csv

1,2,EL,0.1,1,1,true,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.1,"hoge",2,4
2,1,EL,-2.0,2,100000000000000000,false,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.2,"hage",3,1
2,3,EL,0.3,-3,-2222222222222222,false,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.3,"hige",4,4
4,2,EL,4.56789,3,-3333333333333,true,2020-04-20,23:59:59.000000059,2020-04-20T16:46:40.000000300,2020-11-11T01:01:01.000000001+09:00,23:30:30.000000030+09:00,0.4,"huga",1,2

CSV ファイルをロードする

var gcb = GraphConfigBuilder.forFileFormat(Format.CSV).
                addVertexUri("/opt/oracle/oradata/sample.vertices.csv").
                addEdgeUri("/opt/oracle/oradata/sample.edges.csv").
                setVertexIdType(IdType.INTEGER).
                setTimeFormat(Arrays.asList("HH:mm:ss.SSSSSSSSS")).
                setTimeWithTimezoneFormat(Arrays.asList("HH:mm:ss.SSSSSSSSSXXX")).
                setTimestampFormat(Arrays.asList("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS")).
                setTimestampWithTimezoneFormat(Arrays.asList("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX"))

// Vertex Properties
gcb.addVertexProperty("vp_double",    PropertyType.DOUBLE)
gcb.addVertexProperty("vp_integer",   PropertyType.INTEGER)
gcb.addVertexProperty("vp_long",      PropertyType.LONG)
gcb.addVertexProperty("vp_boolean",   PropertyType.BOOLEAN)
gcb.addVertexProperty("vp_local_date",PropertyType.LOCAL_DATE)
gcb.addVertexProperty("vp_time",      PropertyType.TIME)
gcb.addVertexProperty("vp_timestamp", PropertyType.TIMESTAMP)
gcb.addVertexProperty("vp_timestamp_with_timezone", PropertyType.TIMESTAMP_WITH_TIMEZONE)
gcb.addVertexProperty("vp_time_with_timezone", PropertyType.TIME_WITH_TIMEZONE)
gcb.addVertexProperty("vp_float",     PropertyType.FLOAT)
gcb.addVertexProperty("vp_string",    PropertyType.STRING)
gcb.addVertexProperty("vp_vertex",    PropertyType.VERTEX)
gcb.addVertexProperty("vp_edge",      PropertyType.EDGE)

// Edge Properties
gcb.addEdgeProperty("ep_double",    PropertyType.DOUBLE)
gcb.addEdgeProperty("ep_integer",   PropertyType.INTEGER)
gcb.addEdgeProperty("ep_long",      PropertyType.LONG)
gcb.addEdgeProperty("ep_boolean",   PropertyType.BOOLEAN)
gcb.addEdgeProperty("ep_local_date",PropertyType.LOCAL_DATE)
gcb.addEdgeProperty("ep_time",      PropertyType.TIME)
gcb.addEdgeProperty("ep_timestamp", PropertyType.TIMESTAMP)
gcb.addEdgeProperty("ep_timestamp_with_timezone", PropertyType.TIMESTAMP_WITH_TIMEZONE)
gcb.addEdgeProperty("ep_time_with_timezone", PropertyType.TIME_WITH_TIMEZONE)
gcb.addEdgeProperty("ep_float",      PropertyType.FLOAT)
gcb.addEdgeProperty("ep_string",      PropertyType.STRING)
gcb.addEdgeProperty("ep_vertex",      PropertyType.VERTEX)
gcb.addEdgeProperty("ep_edge",      PropertyType.EDGE)

// Label
gcb.setLoadVertexLabels(true)
gcb.setLoadEdgeLabel(true)

var g = session.readGraphWithProperties(gcb.build())

Graph Config Json からロードする方法

  • クライアント側に以下の JSON ファイルを用意する (/tmp/sample_csv.json)
{
    "attributes": {},
    "error_handling": {},
    "timestamp_with_timezone_format": ["yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX"],
    "vertex_props": [{
        "type": "double",
        "dimension": 0,
        "name": "vp_double"
    }, {
        "type": "integer",
        "dimension": 0,
        "name": "vp_integer"
    }, {
        "type": "long",
        "dimension": 0,
        "name": "vp_long"
    }, {
        "type": "boolean",
        "dimension": 0,
        "name": "vp_boolean"
    }, {
        "type": "local_date",
        "dimension": 0,
        "name": "vp_local_date"
    }, {
        "type": "time",
        "dimension": 0,
        "name": "vp_time"
    }, {
        "type": "timestamp",
        "dimension": 0,
        "name": "vp_timestamp"
    }, {
        "type": "timestamp_with_timezone",
        "dimension": 0,
        "name": "vp_timestamp_with_timezone"
    }, {
        "type": "time_with_timezone",
        "dimension": 0,
        "name": "vp_time_with_timezone"
    }, {
        "type": "float",
        "dimension": 0,
        "name": "vp_float"
    }, {
        "type": "string",
        "dimension": 0,
        "name": "vp_string"
    }, {
        "type": "vertex",
        "dimension": 0,
        "name": "vp_vertex"
    }, {
        "type": "edge",
        "dimension": 0,
        "name": "vp_edge"
    }],
    "format": "csv",
    "timestamp_format": ["yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS"],
    "time_format": ["HH:mm:ss.SSSSSSSSS"],
    "vertex_id_type": "integer",
    "loading": {
        "load_vertex_labels": true,
        "load_edge_label": true
    },
    "vertex_uris": ["/opt/oracle/oradata/sample.vertices.csv"],
    "edge_props": [{
        "type": "double",
        "dimension": 0,
        "name": "ep_double"
    }, {
        "type": "integer",
        "dimension": 0,
        "name": "ep_integer"
    }, {
        "type": "long",
        "dimension": 0,
        "name": "ep_long"
    }, {
        "type": "boolean",
        "dimension": 0,
        "name": "ep_boolean"
    }, {
        "type": "local_date",
        "dimension": 0,
        "name": "ep_local_date"
    }, {
        "type": "time",
        "dimension": 0,
        "name": "ep_time"
    }, {
        "type": "timestamp",
        "dimension": 0,
        "name": "ep_timestamp"
    }, {
        "type": "timestamp_with_timezone",
        "dimension": 0,
        "name": "ep_timestamp_with_timezone"
    }, {
        "type": "time_with_timezone",
        "dimension": 0,
        "name": "ep_time_with_timezone"
    }, {
        "type": "float",
        "dimension": 0,
        "name": "ep_float"
    }, {
        "type": "string",
        "dimension": 0,
        "name": "ep_string"
    }, {
        "type": "vertex",
        "dimension": 0,
        "name": "ep_vertex"
    }, {
        "type": "edge",
        "dimension": 0,
        "name": "ep_edge"
    }],
    "edge_uris": ["/opt/oracle/oradata/sample.edges.csv"],
    "time_with_timezone_format": ["HH:mm:ss.SSSSSSSSSXXX"]
}
  • PGX Client を起動して、Graph をロードする
// Graph Config Json ファイルは PGX Client 側に配置されているものを読みにいく
var g = session.readGraphWithProperties("/tmp/sample_csv.json")

Vector プロパティをセットする方法

環境

Oracle Graph Server Shell 20.1.0
PGX server version: 19.4.0 type: SM
PGX server API version: 3.6.0
PGQL version: 1.2

準備

  • Graph の作成
var g = session.<Integer>newGraphBuilder(IdType.INTEGER).addVertex(1).build()

Vector プロパティの設定方法

// Vector Integer プロパティの作成
g.createVertexVectorProperty(PropertyType.INTEGER, 3 /* dimension */, "vp_vec_int")

// Vector Integer プロパティのセット
g.getVertex(1).setProperty("vp_vec_int", new oracle.pgx.api.PgxVect<Integer>(new Integer[]{1,2,3}))
// Vector Long プロパティの作成
g.createVertexVectorProperty(PropertyType.LONG, 3 /* dimension */, "vp_vec_long")

// Vector Long プロパティのセット
g.getVertex(1).setProperty("vp_vec_long", new oracle.pgx.api.PgxVect<Long>(new Long[]{1L,2L,3L}))
// Vector Float プロパティの作成
g.createVertexVectorProperty(PropertyType.FLOAT, 3 /* dimension */, "vp_vec_float")

// Vector Float プロパティのセット
g.getVertex(1).setProperty("vp_vec_float", new oracle.pgx.api.PgxVect<Float>(new Float[]{0.1f,0.2f,0.3f}))
// Vector Double プロパティの作成
g.createVertexVectorProperty(PropertyType.DOUBLE, 3 /* dimension */, "vp_vec_double")

// Vector Double プロパティのセット
g.getVertex(1).setProperty("vp_vec_double", new oracle.pgx.api.PgxVect<Double>(new Double[]{0.1d,0.2d,0.3d}))
  • Vector String プロパティのセットはできない
// Vector String プロパティの作成
g.createVertexVectorProperty(PropertyType.STRING, 3 /* dimension */, "vp_vec_string")

// Vector String プロパティのセット -> エラー発生
g.getVertex(1).setProperty("vp_vec_string", new oracle.pgx.api.PgxVect<String>(new String[]{"str1", "str2", "str3}))

|  Exception java.lang.IllegalArgumentException: type string is not a valid vector property type
|        at PgxVect.<init> (PgxVect.java:49)
|        at (#23:1)

Vector プロパティの参照方法

((oracle.pgx.common.util.vector.Vect<Integer>)g.getVertex(1).getProperty("vp_vec_int")).toArray()
|  Warning:
|  unchecked cast
|    required: oracle.pgx.common.util.vector.Vect<java.lang.Integer>
|    found:    java.lang.Object
|  ((oracle.pgx.common.util.vector.Vect<Integer>)g.getVertex(1).getProperty("vp_vec_int")).toArray()
|                                                ^--------------------------------------^
$28 ==> Integer[3] { 1, 2, 3 }
((oracle.pgx.common.util.vector.Vect<Long>)g.getVertex(1).getProperty("vp_vec_long")).toArray()
|  Warning:
|  unchecked cast
|    required: oracle.pgx.common.util.vector.Vect<java.lang.Long>
|    found:    java.lang.Object
|  ((oracle.pgx.common.util.vector.Vect<Long>)g.getVertex(1).getProperty("vp_vec_long")).toArray()
|                                             ^---------------------------------------^
$29 ==> Long[3] { 1, 2, 3 }
((oracle.pgx.common.util.vector.Vect<Double>)g.getVertex(1).getProperty("vp_vec_double")).toArray()
|  Warning:
|  unchecked cast
|    required: oracle.pgx.common.util.vector.Vect<java.lang.Double>
|    found:    java.lang.Object
|  ((oracle.pgx.common.util.vector.Vect<Double>)g.getVertex(1).getProperty("vp_vec_double")).toArray()
|                                               ^-----------------------------------------^
$30 ==> Double[3] { 0.1, 0.2, 0.3 }
((oracle.pgx.common.util.vector.Vect<Float>)g.getVertex(1).getProperty("vp_vec_float")).toArray()
|  Warning:
|  unchecked cast
|    required: oracle.pgx.common.util.vector.Vect<java.lang.Float>
|    found:    java.lang.Object
|  ((oracle.pgx.common.util.vector.Vect<Float>)g.getVertex(1).getProperty("vp_vec_float")).toArray()
|                                              ^----------------------------------------^
$31 ==> Float[3] { 0.1, 0.2, 0.3 }

実践 Rust 入門 第4章プリミティブ型

Rust における型

  • すべての値の型はコンパイル時に決定される
    • これは安全性、効率性という利点がある
      • 安全性: エラーの早期発見、所有権システムとの連携による型安全かつデータ競合のないプログラム開発の促進
      • 効率性: メモリの細かい制御、コンパイラによる最適化の恩恵

型の分類

  • 定義による分類

    • プリミティブ型
    • ユーザ定義型
  • 構成による分類

    • スカラ型
    • 複合型

スカラ型

  • ユニット
  • 真理値
  • 固定精度の整数
  • 固定精度の浮動小数
  • 文字
  • 参照
  • 生ポインタ
  • 関数ポイント
let n = 40;
let c = 'R';

ユニット

  • 値を返さない関数の戻り値はユニット型
  • ユニット型は意味のある情報を持たないため、サイズは0
    • キーバリューのペアを格納するデータ構造でキーのみデータを保持したい場合には、バリューにユニットを格納すると無駄にメモリを消費しない
assert_eq!(std::mem::size_of::<()>(), 0);

真偽値

  • true と false を持つ
    let b1 = true;
    let b2 = !b1;
    let n1 = 1;
    let n2 = 2;

    let b3 = n1 >= n2;
    let b4 = n1 < n2;
    let b5 = b3 && b4;
    let b6 = b3 || b4;

固定精度の整数

  • ビット幅指定の整数型
    • 符号なし (uxx)
    • 符号あり (ixx)
let n1: i32 = 32;
  • アドレス幅の整数型
    • usize
    • isize
let n2: usize = 32;
  • 整数リテラル
    • デフォルト10進数
    • プレフィクスで他の基数に基づく数を表される
      • 0x: 16進数
      • 0o: 8進数
      • 0b: 2進数
let h1 = 0xff;
let o1 = 0o744;
let b1 = 0b1010_0110_1110_1001;
let n1 = 10u8;
let n2 = b'A';
assert_eq!(n2, 65u8);
  • 代表的な整数演算

    • よくある算術演算、ビット演算、複合代入演算、比較演算は利用可能 
    • Cで使えるけど Rust で使用できないものは以下の2つ
  • 整数型のメソッドや定数

    • 整数型のメソッド
    • pow(), abs(), rotate_left(), from_str(), to_string(), checked_add()
    • 定数
    • 最大値 MAX 等
  • 整数演算の桁あふれ

  • リリースモードでは桁あふれは検出できない
    • 以下の方法で対応するメソッドを使用することを検討する
      • 検査付き演算
      • 飽和演算
      • ラッピング演算
      • 桁あふれ演算
fn overflow_calc() {
    let n1 = 200u8;
    let n2 = 3u8;

    assert_eq!(n1.checked_mul(n2), None);
    assert_eq!(n1.saturating_mul(n2), std::u8::MAX);
    assert_eq!(n1.wrapping_mul(n2), 88);
    assert_eq!(n1.overflowing_mul(n2), (88, true));
}

固定精度の浮動小数

  • ビット数に応じてf32, f64の2つの型が用意されている
  • サフィックスで型を指定可能
  • 指数部も指定可能
    let f1 = 10.0;
    let f2 = 1_234.897f64;
    let f3 = 576.6E77;

文字

  • 1つのUnicodeのスカラ値
  • シングルクォートで囲む
  • 1文字を表すのにたとえ英数字であっても4バイトを消費する
  • 複数のコードポイントが組み合わされた文字例えば'が'などは char リテラルとして使用することはできない(コンパイルエラー)
    let c1 = 'A';
    let c2 = 'B';

    assert!(c1 <= c2);
    assert!(c1.is_uppercase());

    let c3 = '0';
    assert!(c3.is_digit(10));

    let c4 = '\t';
    let c5 = '\'';
    let c6 = '\\';
    let c7 = '\x7F';

    let c8 = '漢';
    let c9 = '\u{5b57}';
    let c10 = '\u{1f600}';
    println!("{}", c10);

参照

  • メモリ安全ポインタ
    • データが格納されている場所を指す
    • usize と同じビット幅の整数で表される
    fn f1(mut n: u32){
        n = 1;
        println!("{}", n);
    }

    fn f2(n_ptr: &mut u32){
        println!("f2: n_ptr {:p}", n_ptr);
        *n_ptr = 2;
        println!("{}", n_ptr);
    }

    let mut f_n1 = 0;
    f1(f_n1);
    println!("{}", f_n1);
    f2(&mut f_n1);
    println!("{}", f_n1);

生ポインタ

  • メモリ安全ではないポインタ
  • dereference するときに unsafe ブロック内に処理を記述する必要性がある
    let mut c1 = 'A';
    let c1_ptr: *mut char = &mut c1;

    assert_eq!(unsafe{*c1_ptr}, 'A');

    unsafe {
        *c1_ptr = 'B';
    }

関数ポインタ

  • 関数を指すポインタ
  fn double(n: i32) -> i32 {
      n + n
  }

  fn abs(n: i32) -> i32 {
      if n >= 0 { n } else { -n } 
  }

  let f1: fn(i32) -> i32 = double;
  let f2: fn(i32) -> i32 = abs;

  assert_eq!(std::mem::size_of_val(&f1), std::mem::size_of::<usize>());

  let mut f3 = double;
  assert_eq!(std::mem::size_of_val(&f3), 0);

Rust 環境構築 + Hello, World + Cargo 基本

安全性、並列性、速度の3つにフォーカスしたシステムプログラミング言語である Rust に興味を持ったので、 まずは環境構築から始めてみます。

Rust 環境構築

  • Rust コンパイラは様々なプラットフォームをサポートしていますが、サポートのレベルが3つに分けられています。

    • 第1級: ビルドでき、かつ動作を保証する
    • 第2級: ビルドを保証する
    • 第3級: テストやビルドは保証していない
  • この中で 64-bit OSX (10.7+, Lion+) は第1級サポートに位置付けられています。

Mac OS での Rust 環境構築

  • 筆者の環境は以下の通りです。
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14
BuildVersion:   18A391
  • 環境構築は以下のワンコマンドですみます。
$ curl https://sh.rustup.rs -sSf | sh

info: downloading installer

Welcome to Rust!

This will download and install the official compiler for the Rust programming
language, and its package manager, Cargo.

It will add the cargo, rustc, rustup and other commands to Cargo's bin
directory, located at:

  /Users/htamakos/.cargo/bin

This path will then be added to your PATH environment variable by modifying the
profile files located at:

  /Users/htamakos/.profile
  /Users/htamakos/.zprofile

You can uninstall at any time with rustup self uninstall and these changes will
be reverted.

Current installation options:

   default host triple: x86_64-apple-darwin
     default toolchain: stable
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1

info: syncing channel updates for 'stable-x86_64-apple-darwin'
info: latest update on 2019-01-17, rust version 1.32.0 (9fda7c223 2019-01-16)
info: downloading component 'rustc'
64.5 MiB /  64.5 MiB (100 %)   4.5 MiB/s ETA:   0 s
info: downloading component 'rust-std'
 49.2 MiB /  49.2 MiB (100 %)   6.1 MiB/s ETA:   0 s
info: downloading component 'cargo'
info: downloading component 'rust-docs'
  8.5 MiB /   8.5 MiB (100 %)   7.6 MiB/s ETA:   0 s
info: installing component 'rustc'
info: installing component 'rust-std'
info: installing component 'cargo'
info: installing component 'rust-docs'
info: default toolchain set to 'stable'

  stable installed - rustc 1.32.0 (9fda7c223 2019-01-16)


Rust is installed now. Great!

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done automatically.

To configure your current shell run source $HOME/.cargo/env
  • この後 $HOME/.cargo/bin を PATHに追加するか source $HOME/.cargo/env で rust 関連のコマンドが実行できます。2019/2時点で最新の安定バージョンは 1.32.0のようです。
$ source $HOME/.cargo/env
$ rustc --version                                                                                                                                             
rustc 1.32.0 (9fda7c223 2019-01-16)

Hello, Rust!

  • 何はともあれ Rust で Hello, World してみます。関数定義を fn で、標準出力をprintln関数で実行する、行末コロンがある、等の特徴がわかります。
fn main(){
  println!("Hello, World");
}
$ rustc main.rs
$ ls -lah
total 560
drwxr-xr-x  4 htamakos  staff   128B  2 15 00:35 .
drwxr-xr-x  3 htamakos  staff    96B  2 15 00:25 ..
-rwxr-xr-x  1 htamakos  staff   274K  2 15 00:35 main
-rw-r--r--  1 htamakos  staff    41B  2 15 00:34 main.rs

$ ./main
Hello, World

できた!

Hello, World 解説

  • C言語に近いシンタックス

    • {} で関数ブロックを記述
    • 行末にコロンが必須
    • main 関数は特別扱いで、すべての rust プログラムのエントリーポイントになる
  • println! はRustのマクロ呼び出し

    • println は関数で、それに対して!をつけるとマクロ呼び出しになるらしい

Cargo Introduction

  • Rust のビルドシステム兼パッケージマネージャーが Cargoです。
  • 上記のインストール手順を踏むと勝手にインストールされています。
$ cargo --version
cargo 1.32.0 (8610973aa 2019-01-02)
  • cargo でプロジェクトを作成するには以下のようなコマンドを実行します。
$ cargo new hello_rust --bin
  • するとnewの後に指定した名前のディレクトリが作成され、その下に、Cargo.tomlファイルと src/main.rs が作成されます。ついでにgitリポジトリの初期化も行ってくれるようです。
$ ls -lah hello_rust
total 16
drwxr-xr-x  6 htamakos  staff   192B  2 15 00:48 .
drwxr-xr-x  5 htamakos  staff   160B  2 15 00:48 ..
drwxr-xr-x  9 htamakos  staff   288B  2 15 00:51 .git
-rw-r--r--  1 htamakos  staff    19B  2 15 00:48 .gitignore
-rw-r--r--  1 htamakos  staff   125B  2 15 00:48 Cargo.toml
drwxr-xr-x  3 htamakos  staff    96B  2 15 00:48 src
  • Cargo.toml の中身は以下のようになっています。TOMLファイル形式が設定ファイルのフォーマットとして採用されているようです。
$ cat Cargo.toml
[package]
name = "hello_rust"
version = "0.1.0"
authors = ["htamakos <xxxxxx@gmail.com>"]
edition = "2018"

[dependencies]
  • Cargo で build する
$ cargo build
   Compiling hello_rust v0.1.0 (/Users/htamakos/project/learning_rust/01_hello_world/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 3.18s
  • cargo でビルドしたプログラムを実行する
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target/debug/hello_rust`
Hello, world!
$ cargo check
    Checking hello_rust v0.1.0 (/Users/htamakos/project/learning_rust/01_hello_world/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.18s
  • cargo でリリースビルドを作成する
$ cargo build --release

# target ディレクトリ以下にreleaseディレクトリが作成され、そこに実行バイナリ等が作成されます。
$ ls -lah target/release
total 552
drwxr-xr-x@ 11 htamakos  staff   352B  2 15 00:59 .
drwxr-xr-x   5 htamakos  staff   160B  2 15 00:59 ..
-rw-r--r--   1 htamakos  staff     0B  2 15 00:59 .cargo-lock
drwxr-xr-x   3 htamakos  staff    96B  2 15 00:59 .fingerprint
drwxr-xr-x   2 htamakos  staff    64B  2 15 00:59 build
drwxr-xr-x   4 htamakos  staff   128B  2 15 00:59 deps
drwxr-xr-x   2 htamakos  staff    64B  2 15 00:59 examples
-rwxr-xr-x   2 htamakos  staff   270K  2 15 00:59 hello_rust
-rw-r--r--   1 htamakos  staff   172B  2 15 00:59 hello_rust.d
drwxr-xr-x   2 htamakos  staff    64B  2 15 00:59 incremental
drwxr-xr-x   2 htamakos  staff    64B  2 15 00:59 native

自動整形ツール rustfmt のインストール

  • Rust のツールチェインには、自動フォーマットツールである rustfmt があります。これは以下のコマンドでインストールできます。
$ rustup component add rustfmt
info: downloading component 'rustfmt'
  1.6 MiB /   1.6 MiB (100 %)   1.3 MiB/s ETA:   0 s
info: installing component 'rustfmt'
  • 使い方は以下の通り
# 以下のようにインデントがおかしい.rsファイルに対して、
$ cat main.rs                                                                                                                                    
fn main() {

println!("Hello, World");
}

# rustfmt をかけると...
$ rustfmt main.rs

# 自動的にフォーマットされます。
$ cat main.rs
fn main() {
    println!("Hello, World");
}

参考: https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/getting-started.htmlhttps://doc.rust-jp.rs/book/second-edition/ch01-01-installation.html