Pebble Coding

ソフトウェアエンジニアによるIT技術、数学の備忘録

swift5.7(Xcode14)で気になる機能

SE-0345 if let shorthand for shadowing an existing optional variable

swift-evolution/proposals/0345-if-let-shorthand.md at main · apple/swift-evolution · GitHub

同じ変数名でunwrapする際に簡略化して書けるようになりました。
これ助かる。

Xcode13未満

let longVariableName: Int? = 3
guard let longVariableName = longVariableName else {
    ...
}

Xcode14以上

let longVariableName: Int? = 3
guard let longVariableName else {
    ...
}

std::filesystemの便利さ

std::filesystem::pathは便利である。
文字コード変換機能が内蔵されており,macOS,windowsどちらも意図どおり動作する。
以下検証コードと実行結果である。 

    std::filesystem::path path1 = "あ";
    const unsigned char* a = (const unsigned char*)path1.string().c_str();
    printf("a: %02x %02x %02x %02x\n", *a, *(a+1), *(a+2), *(a+3));
    const wchar_t* b = path1.wstring().c_str();
    printf("b: %02x %02x %02x %02x\n", *b, *(b+1), *(b+2), *(b+3));
    
    std::filesystem::path path2 = L"あ";
    const unsigned char* c = (const unsigned char*)path2.string().c_str();
    
    printf("c: %02x %02x %02x %02x\n", *c, *(c+1), *(c+2), *(c+3));
    const wchar_t* d = path2.wstring().c_str();
    printf("d: %02x %02x %02x %02x\n", *d, *(d+1), *(d+2), *(d+3));
[Xcode15]
a: 00e3 0081 0082 0000
b: 3042 0000 0000 0000
c: 00e3 0081 0082 0000
d: 3042 0000 0000 0000
[Visual Studio 2022]
a: 0082 00a0 0000 0000
b: 3042 0000 0000 0000
c: 0082 00a0 0000 0000
d: 3042 0000 0000 0000

macOSはシステムのデフォルトがUTF8,日本語版WindowsはCP932となっているのがわかる。

swift5.9(Xcode15)で気になる機能

Swift.org - Swift 5.9 Released

SE-0366: consume operator to end the lifetime of a variable binding.
C++の std::move と同じものが導入されました。

swift-evolution/proposals/0366-move-function.md at main · apple/swift-evolution · GitHub

SE-0380: if and switch expressions

switchのreturn書くのが面倒だったのが改善されました。
2項演算子の可読性が悪いのも改善できます。

swift-evolution/proposals/0380-if-switch-expressions.md at main · apple/swift-evolution · GitHub

SE-0390: Noncopyable structs and enums

C++の std::unique_ptr と同じものが導入されました。

swift-evolution/proposals/0390-noncopyable-structs-and-enums.md at main · apple/swift-evolution · GitHub

githubに登録した公開鍵がどれか確認する方法

githubに登録したSSHの公開鍵はアカウントの設定のところに情報がリストされますが、 作成時に使ったメールアドレスと SHA256:D60Uldj(以下略) 追加日時などしか表示されません。
一方自分が持つ公開鍵にはSHA256:のような情報はありません。
メールアドレスを何度も使い回している場合はこの公開鍵がどれなのか区別がつかないのですが、確認する方法がわかりました。

このSHA256:D60Uldj...のものは公開鍵のフィンガープリントと呼ばれ、単純に公開鍵のSHA256ハッシュを取ったもののようです。手元に公開鍵ファイルがあればssh-keygenコマンドで簡単にフィンガープリントが計算できるようです。
$ ssh-keygen -l -f xxx.pub
256 SHA256:D60Ulfj... hoge@fuga... (ED25519)

github上に表示されているフィンガープリントと一致しました。

std::string_viewはstd::stringに比べてどのくらい速いのか

std::string_viewは文字列の所有権を保持しません。
所有権を保持しない文字列であればcharポインタを使った方が効率はいいです。
std::string_viewには文字列比較機能などがありますが所有権を持たせたくなった時に、
std::stringに変更した時の修正量が少なくて済むというメリットがあります。
内部的にはメンバ変数としてcharポインタとsize_tを持っているだけのようです。
もう一つのstd::stringとの大きな違いとしてはstd::string_viewはnullptrを受け取ることができます。
このときはcharポインタにはnullptrが入り、size_tには0が入ります。
判定には、size(), length(), empty(), data()などが利用できるようです。
std::string_viewはstd::stringに比べてどのくらい速いのか調べてみました。

#include <chrono>
#include <stdio.h>
#include <vector>
#include <string>
#include <string_view>

int main(int argc, const char * argv[]) {
    
    const auto bufsize = 16;
        
    std::vector<std::string> original;
    original.reserve(1000 * 1000);
    
    for (int i = 0; i < 10000; ++i) {
        char buf[bufsize];
        snprintf(buf, sizeof(buf), "%d", i);
        original.push_back(buf);
    }
    
    {
        std::vector<std::string_view> v;
        v.reserve(1000 * 1000);
        
        const auto begin = std::chrono::system_clock::now();
        for (int i = 0; i < 10000; ++i) {
            v.push_back(std::string(original[i]));
        }
        
        const auto end = std::chrono::system_clock::now();
        const auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count();
        printf("%lld\n", duration);
    }
    
    {
        std::vector<std::string_view> v;
        v.reserve(1000 * 1000);
        
        const auto begin = std::chrono::system_clock::now();
        for (int i = 0; i < 10000; ++i) {
            v.push_back(std::string_view(original[i]));
        }
        
        const auto end = std::chrono::system_clock::now();
        const auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count();
        printf("%lld\n", duration);
    }
        
    return 0;
}

34000
21000

1.6倍ほど速いという結果になりました。