coc.nvim で変数や関数のドキュメント情報をポップアップで表示するショートカット設定
~/.config/nvim/init.vim
" Use K to show documentation in preview window. nnoremap <silent> K :call <SID>show_documentation()<CR> function! s:show_documentation() if (index(['vim','help'], &filetype) >= 0) execute 'h '.expand('<cword>') elseif (coc#rpc#ready()) call CocActionAsync('doHover') else execute '!' . &keywordprg . " " . expand('<cword>') endif endfunction
参考
std::ostringstream を初期化して再利用する方法
- std::ostringstream::str で "" を引数に入れてバッファをクリア
- std::ostringstream::clear で内部状態をクリアリセットする
#include <sstream> int main() { std::ostringstream ss; // ostringstream にバッファを入れる ss << "hoge"; // 1 ss.str(""); // 2 // 引数のデフォルト値はstd::stringstream::goodbit)なので引数省略可 ss.clear(); }
[Oracle Graph Server 20.4] PGQL CREATE 文で発行される SQL と PGQL を表示する方法
String query = String.format( "CREATE PROPERTY GRAPH %s " + " VERTEX TABLES(n1 LABEL hoge PROPERTIES(id, name, rate), n2 LABEL hoge2 PROPERTIES(id, name, rate)) " + " EDGE TABLES(e1 SOURCE KEY(n1_id) REFERENCES n1 DESTINATION KEY (n2_id) REFERENCES n2 LABEL el NO PROPERTIES)", graphName); PgqlPreparedStatement pst = pgqlConn.prepareStatement(query); // Create 文で発行される SQL,PL/SQL PgqlSqlCreateTransImpl createTrans = (PgqlSqlCreateTransImpl) pst.translateStatement(); Object[] createTranslations = createTrans.getCreateTranslation(); Stream.of(createTranslations).filter(s -> s != null).forEach(s -> { switch(s.getClass().getName()){ case "java.lang.String": System.out.println(s); break; case "[Ljava.lang.String;": Stream.of(((String[]) s)).filter(t -> t != null).forEach(System.out::println); break; default: System.out.println(s); } });
{ call opg_apis.create_pg(graph_owner => :1, graph_name => :2, tbs_set => null, options => 'SKIP_INDEX=T') } INSERT /*+ append */ INTO "TEST_USER".TEST_20_4_GRAPHVT$ (VID, VL, K, T, V, VN, VT) SELECT VID, VL, K, T, V, VN, VT FROM ( SELECT VID, VL, K, T, V, VN, VT FROM( WITH T0 AS ( SELECT /*+ materialize */ round(sys_op_combined_hash(n'"N1"' || '|' || TABLE_KEY)/2) AS VID , VL, "ID", "NAME", "RATE" FROM ( SELECT "ID" AS TABLE_KEY , n'HOGE' AS VL, "ID", "NAME", "RATE" FROM "TEST_USER"."N1" ) ) SELECT VID, VL, K, T, to_nchar(VN, 'TM9', 'NLS_Numeric_Characters=''.,''') AS V, VN, VT FROM ( SELECT VID, VL, K, to_number(4) AS T, to_nchar(null) as V, to_number(property_value) as VN, to_timestamp_tz(null) VT FROM T0 UNPIVOT ( property_value FOR K IN ( "ID" AS n'ID' ) ) ) UNION ALL SELECT VID, VL, K, T, V, VN, VT FROM ( SELECT VID, VL, K, to_number(1) AS T, to_nchar(property_value) as V, to_number(null) as VN, to_timestamp_tz(null) VT FROM T0 UNPIVOT ( property_value FOR K IN ( "NAME" AS n'NAME' ) ) ) UNION ALL SELECT VID, VL, K, T, to_nchar(VN, 'TM9', 'NLS_Numeric_Characters=''.,''') AS V, VN, VT FROM ( SELECT VID, VL, K, to_number(4) AS T, to_nchar(null) as V, to_number(property_value) as VN, to_timestamp_tz(null) VT FROM T0 UNPIVOT ( property_value FOR K IN ( "RATE" AS n'RATE' ) ) ) ) ) INSERT /*+ append */ INTO "TEST_USER".TEST_20_4_GRAPHVT$ (VID, VL, K, T, V, VN, VT) SELECT VID, VL, K, T, V, VN, VT FROM ( SELECT VID, VL, K, T, V, VN, VT FROM( WITH T0 AS ( SELECT /*+ materialize */ round(sys_op_combined_hash(n'"N2"' || '|' || TABLE_KEY)/2) AS VID , VL, "ID", "NAME", "RATE" FROM ( SELECT "ID" AS TABLE_KEY , n'HOGE2' AS VL, "ID", "NAME", "RATE" FROM "TEST_USER"."N2" ) ) SELECT VID, VL, K, T, to_nchar(VN, 'TM9', 'NLS_Numeric_Characters=''.,''') AS V, VN, VT FROM ( SELECT VID, VL, K, to_number(4) AS T, to_nchar(null) as V, to_number(property_value) as VN, to_timestamp_tz(null) VT FROM T0 UNPIVOT ( property_value FOR K IN ( "ID" AS n'ID' ) ) ) UNION ALL SELECT VID, VL, K, T, V, VN, VT FROM ( SELECT VID, VL, K, to_number(1) AS T, to_nchar(property_value) as V, to_number(null) as VN, to_timestamp_tz(null) VT FROM T0 UNPIVOT ( property_value FOR K IN ( "NAME" AS n'NAME' ) ) ) UNION ALL SELECT VID, VL, K, T, to_nchar(VN, 'TM9', 'NLS_Numeric_Characters=''.,''') AS V, VN, VT FROM ( SELECT VID, VL, K, to_number(4) AS T, to_nchar(null) as V, to_number(property_value) as VN, to_timestamp_tz(null) VT FROM T0 UNPIVOT ( property_value FOR K IN ( "RATE" AS n'RATE' ) ) ) ) ) INSERT /*+ append */ INTO "TEST_USER".TEST_20_4_GRAPHGE$ (EID, SVID, DVID, EL, K, T, V, VN, VT) SELECT EID, SVID, DVID, EL, K, T, V, VN, VT FROM ( SELECT EID, SVID, DVID, EL, K, T, V, VN, VT FROM( WITH T0 AS ( SELECT /*+ materialize */ round(sys_op_combined_hash(n'"E1"' || '|' || TABLE_KEY)/2) AS EID, SVID, DVID , EL FROM ( SELECT "ID" AS TABLE_KEY, round(sys_op_combined_hash(n'"N1"' || '|' || "N1_ID")/2) AS SVID, round(sys_op_combined_hash(n'"N2"' || '|' || "N2_ID")/2) AS DVID , n'EL' AS EL FROM "TEST_USER"."E1" WHERE "N1_ID" IS NOT NULL AND "N2_ID" IS NOT NULL ) ) SELECT EID, SVID, DVID , EL, to_nchar(null) AS K, to_number(null) AS T, to_nchar(null) AS V, to_number(null) AS VN, to_timestamp_tz(null) AS VT FROM T0 ) ) INSERT /*+ append */ INTO "TEST_USER".TEST_20_4_GRAPHVD$ SELECT VID, VL, CNT FROM (SELECT VID, VL, COUNT(*) AS CNT FROM "TEST_USER".TEST_20_4_GRAPHVT$ GROUP BY VID, VL) INSERT /*+ append */ INTO "TEST_USER".TEST_20_4_GRAPHGT$ SELECT EID, EL, SVID, DVID, sys_op_numtoraw(sys_op_combined_hash(EL)) AS ELH, lengthb(EL) AS ELS, CNT FROM (SELECT EID, EL, SVID, DVID, COUNT(*) AS CNT FROM "TEST_USER".TEST_20_4_GRAPHGE$ GROUP BY EID, SVID, DVID, EL) { call opg_apis.create_pg(graph_owner => :1, graph_name => :2, dop => :3, tbs_set => null, options => 'SKIP_TABLE=T') } { call opg_apis.analyze_pg(graph_name => :1, degree => :2, cascade => DBMS_STATS.AUTO_CASCADE, no_invalidate => DBMS_STATS.AUTO_INVALIDATE, force => false, options => null, graph_owner => :3) }
nbconvert --to html で html コンバートしたノートブックで plotly のグラフが描画されない問題の解決
環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G4032 $ pip list | grep -E "jupyter|plotly" jupyter 1.0.0 jupyter-client 5.2.4 jupyter-console 6.0.0 jupyter-core 4.4.0 jupyterlab 2.1.2 jupyterlab-server 1.1.3 plotly 4.9.0
現象
- 以下のコマンドで nbconvert --to html で html コンバートしたノートブックで plotly のグラフが描画されない
$ jyputer nbconvert --to html hoge.ipynb
- 作成した html を開くと以下のようにグラフが表示されない
- エラーを確認すると以下の通り
Uncaught Error: Script error for: plotly http://requirejs.org/docs/errors.html#scripterror C https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js:8 onScriptError https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js:29
解決策
plotly.graph_objects.Figure.show を実行するときに
fig.show(renderer="jupyterlab")
とrenderer
オプションを付ければよい。jupyter を使っている場合には、
fig.show(renderer="jupyter")
と指定すれば良い。
Connection Pool データソースの設定
前提
手順
1. webapps/<コンテキスト名>/META-INF/context.xml に DataSource Resource の設定を登録する
<!--?xml version="1.0" encoding="UTF-8"?--> <Context> <Resource name="jdbc/oracledb" auth="Container" type="oracle.jdbc.pool.OracleDataSource" factory="oracle.jdbc.pool.OracleDataSourceFactory" maxTotal="100" maxIdle="30" maxWaitMillis="10000" username="GRAPHUSER" password="WELCOME1" alternateUsernameAllowed="true" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:graphuser/WELCOME1@oracle-db:1521/pdb1" defaultAutoCommit="false" /> </Context>
2. webapps/<コンテキスト名>/WEB-INF/web.xml に Connection Pool 用のリソースを参照できるように設定する
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1" metadata-complete="true"> .... <resource-ref> <description>Connection Pool</description> <res-ref-name>jdbc/oracledb</res-ref-name> <res-type>oracle.jdbc.pool.OracleDataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
3. java:comp/env/jdbc/oracledb
のようにデータソースを lookup する
Effective C++ 第三章 その2
項目11: 未定義private関数よりも =delete を優先する
template<class charT, class traits = char_traits<charT>> class basic_ios : public ios_base { public: ... private: basic_ios(const basic_ios &); // not defined basic_ios& operator=(const basic_ios&); // not defined }
template<class charT, class traits = char_traints<charT>> class basic_ios : public ios_base { public: ... basic_ios(const basic_ios& ) = delete; basic_ios& operator=(const basic_ios&) = delete; }
- さらに delete はどんな関数でも適用できる
class Hoge { bool isLucky(int number); bool isLucky(char number)=delete; bool isLucky(bool number)=delete; bool isLucky(double number)=delete; }
- 無向なテンプレートのインスタンス化を防ぐこともできる
template<typename T> void f(T* ptr) template<> void f<char>(char*) = delete; template<> void f<void>(void*) = delete;
- クラス内テンプレート関数に対して、テンプレートの特殊化を用いて無効なインスタンス化を防ぐ場合、C++98 の場合の private にする方法は実現できない。テンプレートの特殊化はクラススコープではなく、名前空間スコープで定義する必要があるため。
- delete の場合名前区間スコープで定義することができる。
項目12: オーバーライドする関数は override と宣言する
- 仮想関数のオーバライドは以下のように行う
class Base { public: virtual void doWork() { }; }; class Derived: public Base { public: virtual void doWork() { // }; }; void _override() { std::unique_ptr<Base> upb = std::make_unique<Derived>(); upb->doWork(); }
- オーバーライドを正しく動作するように宣言するのは難しい。
class Base2 { public: virtual void mf1() const {}; virtual void mf2(int x) {}; virtual void mf3() & {}; void mf4() const {}; }; class Derived2 { public: virtual void mf1() {}; virtual void mf2(unsigned int x) {}; virtual void mf3() && {}; void mf4() const {}; };
- override とすると、コンパイル時にオーバーライドできないことを発見できる
class Base2 { public: virtual void mf1() const {}; virtual void mf2(int x) {}; virtual void mf3() & {}; virtual void mf4() const {}; }; class Derived2 : public Base2 { public: virtual void mf1() const override {}; virtual void mf2(int x) override {}; virtual void mf3() & override {}; virtual void mf4() const override {}; };
- メンバ関数の参照修飾子を用いると、左辺値オブジェクト、右辺値オブジェクト(*this)を区別できる
Effective C++ 第三章 その1
項目7: オブジェクト作成時の {} と ()の違い
- 初期値の設定方法は以下の3つ
- {}
- =
- ()
- ユーザ定義型では、初期化構文によって呼び出される関数が異なる
Widget w1; // デフォルトコンストラクタを呼び出す Widget w2 = w1; // コピーコンストラクタを呼び出す w1 = w2; //コピー演算子=を呼び出す
C+11 から初期化の統一記法が導入された
- {} による初期化
- コンテナの初期要素の指定も可能に
- 非スタティックなメンバ変数のデフォルト値の設定にも利用可能
- コピー不可能なオブジェクト(std::atomic など) では、= による初期化はできない
- 精度が落ちる変換を認めない
- 最も厄介な構文解析の回避
{} による初期化の注意点
std::vector も std::initalizer_list 型の仮引数を持つコンストラクタを実装しているため注意
- テンプレート内のオブジェクト作成に () か {} を使うかは慎重に選択する必要がある
項目8: 0やNULL よりも nullptr を優先する
- nullptr はすべてのポインタ型を表す型 (std::nullptr_t)
- テンプレートが型推論するとき、0 や NULL を誤った型に推論するため、nullptr を選択する
項目9: typedef よりもエイリアス宣言を優先する
- まず、関数型宣言がエイリアス宣言のほうがわかりやすい
typedef void (*FP1) (int, const std::string&); using FP2 = void (*) Iint, const std::string&);
// typdef template<typename T> struct MyAllocList1 { typedef std::list<T, std::allocator<T>> type; }; template<typename T> class Widget2 { private: typename MyAllocList1<T>::type list; }; //型エイリアス template<typename T> using MyAllocList2 = std::list<T, std::allocator<T>>; template<typename T> class Widget3 { private: MyAllocList2<T> list; };
項目10: enum にはスコープを設ける
// C++98 方式で enum を定義した場合、enumの列挙子名はenumを定義したスコープに含まれるため // 以下のように実装するとコンパイルエラーとなる //enum Color { black, white, red }; //auto white = false; //erro! redefinition of 'white' as different kind of symbol
enum class Color { black, white, red }; auto white = false; Color c = Color::white;
void _f() { enum UnScopedColor { _black, _white, _red }; UnScopedColor c_ = _red; // double 型へ型変換される // scoped enum の場合コンパイルエラー // scoped enum でコンパイルを通す場合には、 // std::static_cast<double> で明示的に型変換を行う if (c_ < 14.5) { // pass } }
// enum Hoge; はコンパイルエラー enum class Hoge;
enum class Status: std::uint32_t; enum _Status: std::uint32_t;
using UserInfo = std::tuple<std::string, std::string, std::size_t>; UserInfo uInfo; // フィールド1 が何であるかを使う側が知っている必要がある... auto val = std::get<1>(uInfo); // unscoped enum を使うと...! enum UserInfoFields { uiName, uiEmail, uiReputation }; auto val2 = std::get<uiName>(uInfo); // scoped enum を使用すると冗長になる enum class UserInfoFields2 { uiName, uiEmail, uiReputation }; auto val3 = std::get<static_cast<std::size_t>(UserInfoFields2::uiName)>(uInfo);
- scoped enum で便利に、std::tuple の要素にアクセスするための関数テンプレート
// 任意の列挙子をとり、コンパイル時定数としてその値を返す関数テンプレート template<typename E> constexpr typename std::underlying_type<E>::type toUType(E enumerator) noexcept { return static_cast<typename std::underlying_type<E>::type>(enumerator); } // C++14 template<typename E> constexpr std::underlying_type_t<E> toUType2(E enumerator) { return static_cast<std::underlying_type_t<E>>(enumerator); } // C++14 のさらに改良版 template<typename E> constexpr auto toUType3(E enumerator) { return static_cast<std::underlying_type_t<E>>(enumerator); } auto val4 = std::get<toUType(UserInfoFields::uiName)>(uInfo); auto val5 = std::get<toUType2(UserInfoFields::uiName)>(uInfo); auto val6 = std::get<toUType3(UserInfoFields::uiName)>(uInfo);