C++ の std::tuple で動的にループする

たまに C++ を書かないと忘れるので…。

[コード]

#include <tuple>
#include <iostream>
#include <string>

template<typename F, typename T, std::size_t I>
void
apply_impl(F f, T const& t){
    f(std::get<I>(t));
}

template<typename F, typename T, std::size_t ...Indices>
void
apply_impl(F f, T const& t, std::size_t n, std::index_sequence<Indices...>){
    ((void (*[sizeof...(Indices)])(F, T const&)){apply_impl<F, T, Indices>...})[n](f, t);
}


template<typename F, typename ...Args>
void apply(F f, std::tuple<Args...> const& t, std::size_t n){
    apply_impl(f, t, n, std::index_sequence_for<Args...>());
}

template<typename F, typename ...Args>
void for_each(std::tuple<Args...> const& t, F f){
    for(std::size_t i = 0 ; i < sizeof...(Args) ; ++i){
        apply(f, t, i);
    }
}


int
main(){
    using namespace std::literals;
    auto data = std::tuple(1, 3.14, "homu"s);

    auto print = [](auto it){
        std::cout << it << std::endl;
    };
    apply(print, data, 0);
    apply(print, data, 1);
    apply(print, data, 2);

    for_each(data, [](auto it){
        std::cout << it + it << std::endl;
    });

    return 0;
}

[出力]

1
3.14
homu
2
6.28
homuhomu

参考にしたコードはこのあたり
動的に要素にはアクセスしているけど、値を返すことは出来ないので多相ラムダを渡して、それに値を渡すようにしています。
まー、実際 for_each だけなら std::apply とか使ったほうがよさそう。

#include <tuple>
#include <iostream>
#include <string>


template<typename F, typename ...Args>
void for_each(std::tuple<Args...> const& t, F f){
    std::apply([&](auto... args) constexpr{
        (f(args), ...);
    }, t);
}


int
main(){
    using namespace std::literals;
    auto data = std::tuple(1, 3.14, "homu"s);

    for_each(data, [](auto it){
        std::cout << it + it << std::endl;
    });

    return 0;
}
/*
2
6.28
homuhomu
*/

C++ たのしー

Vim script でいい感じにデバッグ出力する

Vim script でデバッグ出力を行いたい場合、以下のようなスクリプトを定義しておくことで『変数名:値』みたいな出力をすることが出来ます。

command! -nargs=*
\   Debug
\   try
\|      echom <q-args> ":" string(<args>)
\|  catch
\|      echom <q-args>
\|  endtry

使い方

let hoge = 42
" 変数名 : 値
" を出力
Debug hoge
" hoge : 42 と出力

" 変数名がない場合はその名前だけ出力
Debug foo
" foo と出力

とても便利。

第8回 学生エンジニア限定LT大会!!! でエモい話をしてきた

前回に懲りずに学生に混ざってLTしてきました。

9年間ブログを書き続けて得たもの

https://osyo-manga.github.io/slide-gakusei_LT-08-9years-blog/#/

内容は『アウトプットすることで自分にもプラスになるんやで』みたいな事を話してきました。
まあ、アウトプットすることは大事なんですけど、自分にも役に立つのでいいですよねー。
皆さん、どんどんアウトプットしていきましょう。

本日のハイライト

懇親会で LT をしているあいだにピザと寿司が全部食べれられてしまっていた。
ゆるさん。
今度参加したときは2倍食べてやる!!!

表参道.rb #31 で LINE でお天気bot をつくった話をしてきた

LT してきました。
今回もご飯がとても美味しすぎた…。

LINE でお天気bot をつくった話

https://osyo-manga.github.io/slide-omotesandorb-31-otenki-bot/index.html#/

と、いうことで今回は珍しく生産性のある話をしてきました。
年末に LINE でお天気 bot を作ったので、それで利用した API や Ruboty の紹介なんかをしてきました。
Ruboty のプラグインとして LINE のアダプタお天気 bot のハンドラをつくったので API キーさえ用意してもらえればすぐに使える(はず…。
何か問題があれば Issues まで教えてください。


そんな感じで今回で5回目のLTをしてきましたー。
運営の方々、発表を聞いてくださった皆様、ありがとうございました。
今回はちょっと参加人数が少なくていつもとは違う趣向でしたが、これぐらいの人数のほうがみんなで色々と意見をいいながら話せるのでこれはこれでよかったかな?と思いました。
みんなでワイワイいいながらコードを見るのは楽しいですね!
そろそろ話すのにも慣れていきたい。

Ruby で (a ==1 && a== 2 && a==3) の結果を真にする

と、いうのが JavaScript 界隈で流行っているので Ruby でもやってみた

== メソッドを定義する

多分一番簡単なやり方。 比較演算子そのものの結果を変えます。

a = Object.new
def a.== other
    true
end

p a == 1 && a == 2 && a == 3
# => true

a メソッドを定義する

Ruby ではメソッド呼び出しの際に () を省略する事が出来るので a() というメソッド呼び出しを a とだけで呼び出すことが出来ます。

def a
    @a = (@a || 0) + 1
end

p a == 1 && a == 2 && a == 3
# => true

こっちは Ruby らしいですね。

おまけ:== ではなくて === を使う

主題からは外れますが Ruby では === 演算子は特別な呼び出しなので == の変わりに === を使うといろいろな手段が使えます。

Proc#=== を使う

Proc#===Proc#call と同じなのでブロックの中身をそのまま返します。

a = proc { true }

# a.call 1 と同じ
p a === 1 && a === 2 && a === 3
# => true

Method#=== を使う

Method#===Proc#=== と同様に #call を呼び出します。

a = [1, 2, 3].method(:include?)

# [1, 2, 3].include? 1 を呼び出しているのと同じ
p a === 1 && a === 2 && a === 3
# => true

Range#=== を使う

Range#===Range#include? を呼び出します。

a = (1..3)

# (1..3).include? 1 を呼び出しているのと同じ
p a === 1 && a === 2 && a === 3
# => true

Set#=== を使う

Range と同様に Set#===Set#include? を呼び出します。

require "set"

a = Set[1, 2, 3]

# Set[1, 2, 3].include? 1 を呼び出しているのと同じ
p a === 1 && a === 2 && a === 3
# => true

Ruby たのしい

Ubuntu で Dropbox の同期が出来なかったときの対処方法

最近 Ubuntu を入れ直したんですが、その時に Dropbox の同期がうまくいかなかったので覚書。
Linux 版の Dropbox アプリの場合、デフォルトの設定では『1 万件以上のフォルダを監視すること』が出来ないため、以下のようなコマンドを端末から実行して回避する必要がある。

# 10 万件までのフォルダを監視するように指示する
$ echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf; sudo sysctl -p

参照

Ruby の Hash のキーを Symbol に変更する

Ruby の Hash のキーを Symbol に変更したい場合、Ruby 2.5 で追加された Hash#transform_keys を使うとよさそう。

hash = { "name" => "homu", "age" => 14 }.transform_keys(&:to_sym)
# => {:name=>"homu", :age=>14}

こういうのをやりたいことは稀によくあるのでメソッド1つで出来るのはよさそう。
ただ、#transform_keys って名前がちょっと長いので transform_keys(&:to_sym) を呼び出すヘルパメソッドが欲しくなる。
ちなみに Hash#transform_keys! だと自身を破壊的に変更します。