読者です 読者をやめる 読者になる 読者になる

オンラインでSICP読書女子会をはじめて1年経ったので経過報告(o ・ω・)ノ

Lisp初心者のくーむです。

なんとなくLispアドベントカレンダーに登録してしまいました。 こちらLisp Advent Calendar 201621日目の記事になります。

今回は地道に1年続いているSICP読書会の様子についてちょっとだけご紹介しようと思います。

オンラインSICP読書女子会について

去年12月に、Ladies++という女性向けのC++コミュニティを立ち上げました。
コミュニティの活動の一環として、何をやろうかと考えていた時、
(気にはなるけどあの厚くて練習問題が多く1人ではなかなか続けられない)SICP読みたいねー、という話になりSICP読書会をはじめました。(C++関係ない・・・)

2016年1月からはじめ、だいたい2週に1度程度開催しており、
1年経った現在、2.3節をやっています。

SICPとは(一応)

コンピュータとデータ構造の基礎がつまったあの本です。

計算機プログラムの構造と解釈 第2版

計算機プログラムの構造と解釈 第2版

github.com

英語版や、非公式日本語訳版などが無料で提供されています。 ふつうの技術書というよりも、大量にある問題を解いていく問題集というかんじです。 基本的にSchemeで書かれています。(Python版(英語)も存在します)

開催の様子についての紹介

どういった形式で開催するのか

まず読書会を始める前に、こちらに悩みました。
イベントサイトやブログなどでSICP読書会を開催している様子を探ってみたところ、
参加者の中で当番制で問題を解いてくる人をまわし、
その人が問題の解説をしていくというパターンが多いように思いました。

第一回目は私達もそのようにしてみたのですが、 解いてきていない人たちが次の回でついていけない場合があり、 基本的に
「全員が解いてきて、ソースコードをどこかに上げ、みんなで他の人の解答について議論し合う」
という形になりました。

また、私が場所を確保することができないという問題があったため、 開催場所はコミュニティのSlackの#sicpチャンネルになってます。

基本的には毎週水曜日21:30~22:30で開催しています。

何問ずつやるのか

はじめは毎週5問ずつやっていました。 しかし、2章になってから重い問題も多く、今は3~5問という感じになっています。
だいたい予習にかかる時間が2~3時間程度です。

何人でやっているのか

最初は3~5名ほどいたのですが、 今現在はだいたいいつも2人で開催しています(੭ु˙꒳​˙)੭ु⁾⁾ <- (with @hioさん)

こじんまりですが自分のペースで進められるのがよいところです。

今からでも是非みんな参加して!と言ってはいるのですが、 SICPは頭からやってくことに意味があるなぁと感じる構成になっているため、 微妙な節から始めると、「SICPって怖い、むずかしい」という気持ちを産んでしまいそうな気がします。

もし興味が有る方がいれば、2.4節もしくは3章がはじまるタイミングで参加していただくのが良いかもしれません。

これまでの解答

参加者の解答をみて自分の解答を修正したり、別解として紹介したりしつつまとめている私の記事一覧です。

※途中で名前やまとめ方がかわったり、ちょっと抜けが合ったりする・・・!

どんなかんじに喋っているのか(おまけ)

2章にて、シンボルの使い道がわからない〜という話をしてたときの様子

しんぼるどんなときに使うんですか?

> 例えばハッシュのキーとか。

ほえー?

> 文字列だと、メモリ列をずずずーっとみて一致調べないとだけど、
  シンボルは内部的には基本ただの整数値になってる

シンボルだとすぐ飛べる?
つまりdefine的な?


> そんなかんじー

'aがなにであるかは
とくに定義はどこにもしないんですよね?
かってに好きな値を割り当ててくれて
かぶらないようになる?

> そう〜
  'a と 'b はかならず別の値になるようにしてくれるし、
  'a と 'a なら、別のモジュールで使ってても同じ値になってくれる
  
  ちなみに Perl は、文字列に対して内部でハッシュ値を計算して持ってたりする。
  ハッシュキーにするときとか。
  
文字列をハッシュキーにするときに
その文字列を一旦ハッシュ化して、どこかにペアをつくっておいて、そのハッシュでアクセスする?

> そうそう。

ほえー! おもしろい!!

こんな感じでワイワイ雑談を交えながら問題の答え合わせをしています(o ・ω・)ノ

なんで女子会なの?

Ladies++の活動の一環だからということで、特に理由はありません。

さいごに

SICP読書会は様々なところで開催されており、 自分たちも開催したい、という方も多いかと思いましたので、 まだ2章半ばではありますが、1年つづいた例として、開催の仕方や様子を紹介してみました。*1

本自体を読んでいる感想としては、 ここで何度も私が紹介している、世界で闘うプログラミング力を鍛える150問でやったような基礎的な内容を、 もっとじっくりきっちり理解していける感じです。

最近やっている2章はmapやfilter等関数型らしい(?)話題になってきていて、 普段関数型言語を書かない私としてはとてもおもしろいです。 難しい部分も多いですが、人と一緒にやるとがんばれますねヽ(=´▽`=)ノ

やっとschemeにも慣れてきた(括弧の対応が無意識にとれるようになってきた)ところなので、 ぜひschemeで何かちょっと作ってみたいな・・・という気持ちがあります( ・ω・)

まだまだSICPは序盤ですので、 どこまで解いていけるかわかりませんが、来年も頑張っていきたいですヽ(=´▽`=)ノ

次回開催

ladiespp.connpass.com

さて明日は @y2q_actionmanさんで「cffi関連?(タイトル未定?)」ですっ

*1:結局のところは 「開催方法云々よりも、一緒に読んでくれる人を見つけることが大事なのでは・・・・」 という気がしなくもない

ElasticSearch(2.3.5)とKibana4でユーザの統計データを表示してみる

久々に Python mini Hack-a-thonに参加させていただいたので、 なにやろうかな〜と考えた結果、ElasticSearchに触れてみることにした。 今回は簡単なデータをちょっと表示する所までしかできていない。

目的

とあるWebサービスにログインしているお客様の情報を毎日取得し、
日毎のユーザの変化をみたい

例えば・・・

全てのユーザさんの中から、10代のユーザで最終ログインが1日以内のユーザ数の遷移

なんてリクエストなんかに応えたい。

サンプルデータはこんな感じ。

{
    "data": [
        {
            "status": {
                "date": 20160806,   // 今日の日にち
                "age": 10,          // 何十代か
                "last_login": 1,    // 最後にログインしたのは何日以内か
            },
            "data": {
                "account": 10,      // status に該当する人が何人いるか
            }
        },
        ...............
      ]
}

ここに書くと長くなるので、サンプルデータはこちら:elastic_sample.json

まずは導入

https://www.elastic.co/downloads/elasticsearch から ElasticSearchをDL。 最新っぽい2.3.5をDLした

適当な場所に置いて、

cd lasticsearch-2.3.5
./bin/elasticsearch

で、ElasticSearchを起動すると、9200番portに立ち上がる: localhost:9200

localhost:9200/_nodes/stats/process から、立ち上がったノードの状態とか見れる。

※ノード: ElasticSearch のインスタンスのこと。 この辺りを参考に: Elasticsearch クラスタ概説

※このへんに書いてます Setup | Elasticsearch Reference [2.3] | Elastic

データを入れてみる

ElasticSearchでは、

http://localhost:9200/{index}/{type}/{id}

jsonをポストすると、 Index > Type のなかにidのデータをつっこめる。 Index, Typeはデータベースのテーブルを分けるみたいな感じに使えばいいと思うのだけど、 どうやって分けるのがいいのか難しい。

今回は以下のようにした。

  • Index = サービス名
  • Type = "daily_data"

id名は、 後から更新する際に一意にとれる必要があるので、 {date}_{age}_{last_login} というようにデータのキーとなるStatusの値を全部joinしたものにした。

jsonをポストするプログラムを書いてみた in Python2.7 使ったテストデータ:elastic_sample.json

import json
import urllib2

index_ = "service_name"
type_ = "daily_data"
id_format_ = "{date}_{age}_{last_login}"
url_ = "http://localhost:9200/{index}/{type}/{id}"

with open('data/elastic_sample.json', 'r') as f:
    data = json.load(f)

    for d in data['data']:
        status = d['status']
        date = str(d['status']['date'])
        d['@timestamp'] = date[:4] + "-" + date[4:6] + "-" + date[6:]

        id_ = id_format_.format(date=status['date'],
                                age=status['age'],
                                last_login=status['last_login'])


        post_data = json.dumps(d)
        url = url_.format(index=index_,
                          type=type_,
                          id=id_)
        print id_, url, post_data

        req = urllib2.Request(url,
                              post_data,
                              {'Content-Type': 'application/json'})

        f = urllib2.urlopen(req)
        response = f.read()
        print response
        f.close()

こんな感じにレスポンスが帰ってきた。 Response

20160806_10_3 http://localhost:9200/service_name/daily_data/20160806_10_3 {"status": {"date": 20160806, "age": 10, "last_login": 3}, "@timestamp": "2016-08-06", "data": {"account": 10}}
{"_index":"service_name","_type":"daily_data","_id":"20160806_10_3","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}
20160806_20_3 http://localhost:9200/service_name/daily_data/20160806_20_3 {"status": {"date": 20160806, "age": 20, "last_login": 3}, "@timestamp": "2016-08-06", "data": {"account": 20}}
{"_index":"service_name","_type":"daily_data","_id":"20160806_20_3","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}
20160806_10_1 http://localhost:9200/service_name/daily_data/20160806_10_1 {"status": {"date": 20160806, "age": 10, "last_login": 1}, "@timestamp": "2016-08-06", "data": {"account": 30}}
{"_index":"service_name","_type":"daily_data","_id":"20160806_10_1","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}
20160806_20_1 http://localhost:9200/service_name/daily_data/20160806_20_1 {"status": {"date": 20160806, "age": 20, "last_login": 1}, "@timestamp": "2016-08-06", "data": {"account": 40}}
{"_index":"service_name","_type":"daily_data","_id":"20160806_20_1","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}
20160807_10_3 http://localhost:9200/service_name/daily_data/20160807_10_3 {"status": {"date": 20160807, "age": 10, "last_login": 3}, "@timestamp": "2016-08-07", "data": {"account": 11}}
{"_index":"service_name","_type":"daily_data","_id":"20160807_10_3","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}
20160807_20_3 http://localhost:9200/service_name/daily_data/20160807_20_3 {"status": {"date": 20160807, "age": 20, "last_login": 3}, "@timestamp": "2016-08-07", "data": {"account": 25}}
{"_index":"service_name","_type":"daily_data","_id":"20160807_20_3","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}
20160807_10_1 http://localhost:9200/service_name/daily_data/20160807_10_1 {"status": {"date": 20160807, "age": 10, "last_login": 1}, "@timestamp": "2016-08-07", "data": {"account": 31}}
{"_index":"service_name","_type":"daily_data","_id":"20160807_10_1","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}
20160807_20_1 http://localhost:9200/service_name/daily_data/20160807_20_1 {"status": {"date": 20160807, "age": 20, "last_login": 1}, "@timestamp": "2016-08-07", "data": {"account": 41}}
{"_index":"service_name","_type":"daily_data","_id":"20160807_20_1","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}

実際に以下にアクセスしてもデータを見られる。 localhost:9200/service_name/daily_data/20160806_10_3

postしたデータの型を確認する

アクセスすると、データがどういった型で持たれているかがわかる。 localhost:9200/service_name/daily_data/_mapping 今回みたいにmappingを特に設定せずにいきなりpostすると、 勝手に判定してmappingしてくれる。

mapping結果はこんなかんじy

{
  "service_name": {
    "mappings": {
      "daily_data": {
        "properties": {
          "@timestamp": {
            "type": "date",
            "format": "strict_date_optional_time||epoch_millis"
          },
          "data": {
            "properties": {
              "account": {
                "type": "long"
              }
            }
          },
          "status": {
            "properties": {
              "age": {
                "type": "long"
              },
              "date": {
                "type": "long"
              },
              "last_login": {
                "type": "long"
              }
            }
          }
        }
      }
    }
  }
}

http://localhost:9200/service_name/_search?q=*にアクセスすると、データが全部見える。

データを消す

データ消したい時は、こんな感じにして消す。

curl -XDELETE http://localhost:9200/service_name/daily_data/20160806_10_3

データをKibanaに入れてみる

Kibanaのダウンロード

Download Kibana Free • Get Started Now | Elastic

適当なパスに置いて、以下を叩く。

cd kibana-4.5.4-darwin-x64
./bin/kibana

多分5601番に立ち上がる。 http://0.0.0.0:5601/

データを可視化する前にKibana設定をする

  1. まずSettingsタブでIndex名を指定する。時間データを入れているキー名もいれておく。(今回は@timestamp) f:id:cocodrips:20160806182648p:plain
  2. Visualizeタブ > Vertical bar chart > From new search を選択
  3. Y-Axis の 矢印をクリックして Count->Sumに変更、Fieldをdata.account
  4. bucketsでX-Axisを選ぶ。AggregationをDate Histgram、Fieldを@timestampに、IntervalをDailyに設定。
  5. 再生ボタンを押すと、日毎の各条件のアカウント数の合計値グラフが出てきます。 f:id:cocodrips:20160806182644p:plain
  6. 右上の保存ボタンを押して、「アカウント」というタイトル保存。

あとはこのあたりを参考に Kibana 4 BETAファーストインプレッション - Qiita

Dashboardを作る

  1. Dashboard」タブをクリック
  2. 右上から + みたいな追加ボタンを押して、「アカウント」を選択 f:id:cocodrips:20160806182635p:plain

  3. "status.age=10" というように、クエリを書くと、その条件にあったデータの合計値のみがでてくる。 f:id:cocodrips:20160806182641p:plain

とりあえず今回はここまで

まとめ

KibanaのDashboardに色々好きなように表示できるのは嬉しい。
クエリを保存してFilterを最初からいくつか準備しておきたいのだけど、
そのやり方がまだわからない・・・。
毎回クエリ書くのはめんどくさいし、 エンジニア以外の人に触ってもらうには、毎回クエリをかくっていうのは困る。

もうちょっといい感じのdashboardが作れたら、また追記したい。

参考にしたページ

女性のためのC++コミュニティ Ladies++を立ち上げました

12月に女性C++erのための、Ladies++というコミュニティを立ち上げました。
今回はLadies++や女性コミュニティについて紹介しようと思います。

この記事は、 Geek Women Advent Calendar 2015 の23日目の記事です!

様々な女性コミュニティ

最近はたくさんの女性向け技術コミュニティがあります。
Rails Girlsなんかが有名かもしれませんが、
Pythonの女性コミュニティPyLadiesや、Java女子部等も活発に活動がされています。

なぜ女性でコミュニティなのか

今年のPyConJP2015では、女性コミュニティに関する「いま求められるコミュニティの多様性と未来 」というパネルディスカッションが行われました。
togetter.com

性コミュニティの良さみたいなのはこちらのまとめを見てもらえるわかるかもしれません。






私の考える女性コミュニティの良いところ

性コミュニティだから出会える女性エンジニアさんたち

普通のお勉強会にいくと、たいてい8割以上が男性で、なかなか女性エンジニアさんには出会えません。
多くの女性エンジニアさんは普段男性ばかりの環境で強く生きています。
でもたまには女性だけで技術トークで盛り上がるのも楽しいものです。

「無刻印キーボードいいよね〜〜」
「超わかる〜!」

みたいな会話もできます。

女性エンジニアさんに、インプットの機会を

みなさんが思っているよりも女性エンジニアさんはそこそこいます。
でも、なかなかコミュニティを知る機会・参加する機会がある方は多くないです。
そういった女性エンジニアさんに、「(女性コミュニティに限らず)コミュニティに参加する」ということへのハードルを下げる役割を果たしています。
(* 女性エンジニアは少ないなんて言わないよなるべく | nocono)

玄人じゃなくてもアウトプットの機会を

普通の技術勉強会に行くと、だいたい愛のある人たちがマサカリをなげてくれます。
でも、そのマサカリが初心者にとっては怖いため、発表するにはなかなか勇気がいります。
そんな人達に、発表慣れしてもらう機会を提供しています。

プログラミングをはじめたての方の
「デザイナーだけど〇〇(プログラミング言語)はじめてみた」
なんていうトークを聞けるのも女性コミュニティならではかもしれません。
(でも、ガチなトークももちろんたくさんありますよ!)

Ladies++発足まで

PyConJPのパネルディスカッションを見て、

みたいにつぶやいたら、PyConJP2015にきてた@scitamehtamさんと意気投合して、
C++性コミュニティを作ることにしました。

私自身はC++超Beginnerで、技術書を読んだり独学で勉強したりしていました。
C++は独特の世界観とお作法とかがあって、お勉強会に参加してみたいな〜と思いつつ、
C++のコミュニティと言えば

_人人人人人人_
> 超怖そう <
 ̄Y^Y^Y^Y^Y ̄

なイメージだったので、なかなかコミュニティに参加できていませんでした。
(その後、おそるおそるBoost.勉強会 に参加してみたのですが、みんな優しかったです・・・!
でも、こわくて参加しづらい・・・と思っている人も実際にいます)

Ladies++の紹介

Ladies++は、女性C++erが集まってもくもくとC++力を高めたり、わいわい情報共有したりするコミュニティです。

東京を中心に、毎月ワークショップ、ハッカソン、勉強会などを企画していきたいと思っています。
初心者/熟練者問わずC++に興味をもつ全ての女性が一緒に勉強したり、
情報交換できる場を目指しています!

Ladies++ meetup #1

1ヶ月前から2,3日集まったりしつつ、企画しました。
当日の内容は、コミュニティの紹介・LT x 8・懇親会という感じで、
12名の方が参加して下さいました。

LTでは、「C++で似顔絵作り」という研究紹介や、
プリプロセッサの話」というコアな話まで、
いろんなトークを聞けました。

meetup中のTweet紹介







今後やっていきたいと考えていること
  • (テーマを決めて)LT大会
  • ワークショップ(初心者向け、ゲームなどをテーマに)
  • SICP/C++関連本 輪読会

Join Ladies++ !!

Ladies++では、C++に興味のある女性の参加をお待ちしています。
これからC++を始めたい方から仕事でC++を書いている方まで、熟練度は問いません。

また、Ladies++ではSlackを使ってメンバー同士でコミュニケーションをとっています。
興味のある方は、以下のフォームよりSlack参加申請をしてください。

申請フォーム - Join Ladies++!!

さいごに

meetup #2はまだ企画中ですが、
これから様々なイベントを開催していきたいと思っています。
よろしくお願いします(`・ω・´)ゞ


あしたは、ichimurayukieさんです!