teleren/devto huggingface dataset:
A Beginner's guide to examining .CSV data in R Studio
Published: 2020-01-21 06:26:19

These days, there are tons of options available for exploring datasets. One of my favorite environments is R Studio. It's free, open-source, and powerful. R Studio is an IDE for R, a popular veteran programming language, tailored toward data analysis and display. R has thousands of packages which are particularly useful for data analysis, with specialized functions for a variety of scientific disciplines.

In this article, we will learn how to convert a .csv file into a data frame in R Studio, and explore the data via the data frame's built-in capabilities. 

Go ahead and download and install the latest version of R for your operating system, and then install R Studio.


Now that you have R Studio installed, the first thing we're going to do is install a handy general purpose library for manipulating data in R.

```R

install.packages("dplyr")

```

We will need some sample data in .csv form. You can use whatever .csv file happens to be hand (there are plenty available for free on the internet). I grabbed a .csv file with 10k records, see the link here: 

http://eforexcel.com/wp/wp-content/uploads/2017/07/10000-Sales-Records.zip

The basic ingredients are in play, now we need to load our .csv frame into R.

First, check our R Studio working directory. In the R Studio console, type

```R
getwd()
```

My directory is documents, so I'm going to place my .csv file my documents folder. Then, I will go ahead and load that .csv file, and convert it into a native R data frame.

```R
my_records = csv.read("my_records")  
```

Now, my data is living in a data frame. This means that I get access to a lot of handy methods.

To view the number of rows

```R
 nrow(my_records)
```

To view the number of columns

```R
 ncol(my_records)
```
To view the column names

```R
 colnames(my_records)
```
To view the first 10 rows of data

```R
  head(my_records, 10)
```

To view the last 10 rows of data

```R
  tail(my_records, 10)
```

To get the sum of the values in a column, by column name

```R
  sum(my_records['Total.Profit']
```
Sample 5 random rows

```R
  dplyr::sample_n(my_records, 5)
```

Filter data frame by column values, where Total Cost is greater than 1000

```R
  dplyr::filter(my_records, Total.Cost > 1000)
```

Remove Duplicate Rows

```R
  dplyr::distinct(my_records)
```

Select top 5 records, sorted by Total.Cost

```R
  dplyr::top_n(my_records, 5, Total.Cost)
```

Average of Total.Cost

```R
  dplyr::summarise(my_records, mean(Total.Profit))
```

Min value in column Total.Cost

```R
  dplyr::summarise(my_records, min(Total.Profit))
```

Max value in column Total.Cost

```R
  dplyr::summarise(my_records, max(Total.Profit))
```
Stop donating your customers' data to Google Analytics
Tags: aws, amplify, contributorswanted, analytics
Published: 2020-01-21 05:53:07

In 2020, with better alternatives available, using Google Analytics (GA) to track your web usage is nothing short of donating data to a multinational corporation. Aside from only letting you sample 25% of your traffic, GA is a free ticket for them to sell your customers' data to their advertising partners.

Compared to AWS Pinpoint, which is even [HIPAA compliant](https://aws.amazon.com/about-aws/whats-new/2019/07/amazon-pinpoint-achieves-hipaa-eligibility/), GA works by asking you to add a tracker to your website that cross examines your customers' habits across all the websites they use to find out everything about them.

And if you think that's okay, you should take your head out of the sand because consumers are demanding it. Please tell me how many of your users like the large cookie agreement popups that they have to dismiss...I-I mean read and accept just to consume your content. Agreements that you're forced to have them agree to because you're using cookie-based trackers like GA.

Tracker blockers are increasing in popularity so consumers can protect themselves against this tracking, reducing the effectiveness of your analytics.

Even if you want to be selling your customers' data, data is the new oil and GA is Deepwater Horizon. As in raking it in, but also about to catch fire and sink. Tools like Pinpoint on the other hand keep the data in your closed system and even allows you to attach more extensive analytics like Kinesis. To train machine learning models on data you've collected would require you to create pipelines between data centres. It's a single click:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/wgnsep2aexoglwd2e84k.PNG)

Currently, AWS Pinpoint requires you to import Amplify to your project. If you're looking for a tracking-tag solution like for Google Analytics, it's now that simple:

```html
<script
    data-id-pool="us-east-1:abcd1234-abcd-1234-5678-abcd12345678"
    data-pinpoint-id="1234abcd5678abcd7890abcd1234"
    id="aws-web-analytics"
    src="https://goatandsheep.github.io/aws-web-analytics/dist/aws-web-analytics.js"
    type="text/javascript"
></script>
```

This is thanks to an analytics package I built that uses Amplify to connect to AWS Pinpoint. If you're interested in contributing, please [visit the project repo](https://github.com/goatandsheep/aws-web-analytics/).
Blockchain 
Tags: blockchain, hyperledger, ethereum
Published: 2020-01-21 05:35:05

Hello i am a Phd Student that is interested in working in Blockchain. I want to develop Blockchain networks for my research. I want to users to send the transactions signed by a group signature instead of the private key of each user. can this be implemented on the hyperledger fabric. or it is easier to implement on ethereum. 

Thanks in Advance
It's that time of year again
Tags: discuss, career
Published: 2020-01-21 05:04:33

# Ask yourself:

What would it take to make me happy here?

Am I running away or towards something?

What would quitting solve?

Am I financially prepared for this?

Am I scared?

Do I want to leave my job or just my manager?

Am I having a technical problem or a political problem?

---

Are you asking yourself any of these? Discuss. Vent. Ask. Share.

Remember:

Hang in there, comrade. It gets better. We've all been there at some point. Ultimately, you've got to do what's best for _you_
grpc vs protorpc
Tags: discuss, grpc, protorpc
Published: 2020-01-21 04:22:44

---
title: grpc vs protorpc
published: true
description: what is difference between grpc and protorpc
tags: #discuss #grpc #protorpc
---

In Google app Engine py2.7 standard I mainly use cloud endpoint framework to make web apis,
They use protorpc their to make serialization and deserialize and parhaps more.

But in GAE py3, they don't support cloud endpoint framework, so our team want to migrate to flask but want strict serialization in json like protorpc, ( structured json )
There is many alternatives, grpc is one of them and also support http2 stream, protobuff

So I'm confuse how protorpc different from grpc 
Are protorpc use same architecture and protobuffer internally ?
#state{} が太る話
Tags: erlang
Published: 2020-01-21 03:29:49

## 結論

別に太っても良い、定期的にダイエットするなら。

## 前提

Erlang でプロセスの状態を保存する場合は #state{} というレコードを作ってそこに状態を持たせるというのが良くやるパターンだ。プロセスの管理方法はいろいろなパターンがあるのだが、自分が良くやるパターンは中央集権方式を取る。

1 つの TCP や UDP の接続に対して複数のプロセスを上げるという実装をよくすることになる。処理毎にプロセスを分ける、といった方式だ。

ただ、それらの処理するプロセスが状態を持つこともあるのだが、あまり状態を持たせないようにしている。
コアとなるプロセスが他のプロセスの状態もできる限り管理するという方法だ。ただし、完全にそのプロセスに閉じている場合は別。

## 中央集権型について

1 つの WebSocket 接続に対していくつかの処理があり、 1 つ接続がある毎にプロセスが 3 つ上がるとする。

- ws プロセス
    - 通知プロセス
    - データベースプロセス
    - ログプロセス

このような構成を取る場合、教科書通りだと simple_one_for_one で supervisor をぶら下げて、その下に one_for_all でぶら下げるといった方式だと思うのだが、自分はその選択は取らない。

ws プロセスから自前で link を全てのプロセスにはるようにしている。つまり再起動処理などを自前で実装するようにしている。supervisor は大変便利なのだが、グレイスフルシャットダウンをする場合、色々トリッキーな処理をいれることになり、コードがわけわからなくなる。

そのため supervisor でそれぞれのプロセスを simple_one_for_one の temporary でぶら下げるようにし、 supervisor:start_child/2 と link や monitor を使う事で自前でのプロセス管理を実現できるようになる。

今回の構成はデータベースプロセスや通知プロセスが死んだとしても ws プロセスはしなないが、ログプロセスが死んだら ws も切断するといった構成にする。

データベースや通知のプロセスはそこがぶら下がっている無限再起動にすると良いだろう、そして monitor で上げる事で、一方向の通知で、再度上げる処理を ws 側で実装することができる。ログプロセスが死んだら、ws プロセスも死んで欲しいので、そこは link を利用しておく。

そんなの supervisor を上手く使えよという話になりそうだが、自分の経験上シンプルな場合は supervisor は素晴らしいのだが、細々したシャットダウン戦略をとる場合はかなり苦しい、というか無理。

そのため、monitor/link を利用した自前でのプロセス管理戦略をできるようにすると良い。

## 太る理由

中央集権型にした場合、ログプロセスとデータベースプロセスで利用したい情報が同じ場合は ws プロセスで持っておく必要がある。という話が増えていくと、 ws プロセスの #state{} には他のぶら下がってるプロセスの #state{} に持たせる値を管理する必要があるため、太っていく。

また、 データベースプロセスが何かしらの影響で切り替わった事を ws プロセスの #state{} でも持っておきたいとかがある場合もあり、そうすると重複することになる。

## 太らせて大丈夫なのか

もちろん常にダイエットは意識しなければならない。太らせたくて太らせているわけでは無く、イヤイヤ太っているのだし。

太ったなぁと思ったらダイエット時期なので、ソースを見直すと良い。

## 状態の中央集権は楽か？

かなり楽。そもそもそこに置いておけば良い。最悪ぶら下がってるのは取りに行ったり、送られてきたりする。重要なのは ws プロセス以外のプロセスは自分以外には ws プロセスしかしらないという状態を作る。

つまり親しかしらない。他の子を知らない状態にする。そうすると子は親を通してしか状態を変更できなくなるので管理がとても楽になる。

個人的には好きな構成、ただ複雑になるのでお勧めはしない。
erlang:process_info(Pid, message_queue_len) の話
Tags: erlang
Published: 2020-01-21 03:27:59

## 結論

プロセスにメッセージが詰まると破綻するので、 性能検証をする際は message_queue_len を使ってちゃんと確認しましょう。

## 説明

erlang:process_info/2 は指定したプロセスの情報を取得する仕組みです。その中に message_queue_len という項目があります。

これは何かというと、プロセスのキューに **貯まっている** メッセージ数を表示します。

### プロセスのキュー？

そもそも Erlang のプロセスに情報を渡す場合はメッセージパッシングが基本です。そのメッセージは受け取った側のプロセスのキューに入ります。

このキューが message_queue です。 message_queue_len はその **現時点でのキューに詰まっているメッセージの長さ** です。receive でその送られてきたメッセージにマッチすれば、そのキューから取り出されます。

### 詰まる？

メッセージをキューから取り出して、メッセージを処理して、次のメッセージをキューから取り出すという処理になります。この **メッセージを処理する速度** が送られてくるメッセージが送られてくる速度より遅くなってしまうと、ひたすらキューにメッセージが詰まることになります。

ここが詰まるとそのプロセスはもう使い物にならないと考えて問題ありません。プロセスのキューは 10 万メッセージ以上格納可能です。もちろんその分のメモリーも消費します。

## 回避策

詰まらないようにする、という悲しい対策しかできません。

## おまけ

Erlang/OTP 19.0 で process_flag(message_queue_data, MQD) という機能が入りました。

http://erlang.org/doc/man/erlang.html#process_flag_message_queue_data

これは、キューにメッセージをストアする際に off_heap と on_heap を選べるようになりました。デフォルトは on_heap が有効になっています。

### off_heap 

プロセスヒープの外部に保存され、プロセスキューに入っているメッセージがガベージコレクションの対象ではななくなります。

### on_heap

全てのキューのメッセージが最終的にはヒープにおかれます。ただし、一時的にヒープで無いところに置くことも可能です。

### どっちつかえばいいの？

メッセージを多く受け取る可能性がある場合に off_heap を使うといい結果が出る可能性があります。ヒープに置かれたメッセージのためのガベージコレクションが極端に負荷が高くなるためです。

メッセージの量を多く受け取り、変に GC が走りまくっているような場合は off_heap を試してみるのも良いでしょう。
gen_server で同期的に値を得てからプロセスをシャットダウンする
Tags: erlang
Published: 2020-01-21 03:27:02

## 期待している動作

指定したプロセスに対して処理が終わったら、そのままキレイに死んで欲しい。

## 結論

handle_call(_Request, _From, State) の戻りに対して {stop, {shutdown, Reason}, Reply, State} とやるだけです。

```erlang

handle_call(_Request, _From, State) ->
    Reply = ok,
    Reason = spam,
    {stop, {shutdown, Reason} Reply, State};
```

使いどころなんですが、ほとんどありません。ただ連鎖で死ぬときに、最後にこの処理をして貰ってから死んで欲しい、というときに使うと良いです。

## 蛇足

なぜこの記事を書いたかというと、この動きが必要な実装がでてきたのですが、値を同期的に戻して stop するという機能が gen_server にあると思っていなかったという、無知をさらすためです。
Erlang で POSIX Time を秒で返す方法
Tags: erlang
Published: 2020-01-21 03:26:32


Erlang/OTP 19 以降でのみ確認している。

## 結論

**erlang:system_time/1 を使う**

Erlang で時間だと今までは erlang:timestamp/0 のような値を使って、色々面倒な感じだった。

calendar:datetime_to_gregorian_seconds({{1970,1,1},{0,0,0}}). こんな値を定義したこともあるだろう。これはもう不要になった。

```
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] [sharing-preserving]

Eshell V8.0.2  (abort with ^G)
1> erlang:system_time(seconds).
1470493137
```
format_error/1 のススメ
Tags: erlang
Published: 2020-01-21 03:24:33

ライブラリにロギングを入れると訳わからなくなるので基本的に入れない事が普通です。

そこで ok/error の {error, Reason} をうまく使うというのをオススメします。
別にデファクトなわけではないです。好み問題だと思ってます。

## file:format_error/1

format_error は file モジュールで出てきます。これは file モジュールでエラーが起きた場合に {error, Reason} で返ってきた Reason を format_error(Reason) とするとヒューマンリーダブルなエラーに変更してくれるという仕組みです。

```erlang
1> file:format_error(einval).
"invalid argument"
2> file:format_error(eexist).
"file already exists"
```

## オレオレ format_error/1

この仕組みをうまく使うことで format_error/1 をアプリ側でラッピングするという仕組みを使います。

```erlang
format_error({missing_user_id, UserId}) ->
    %% format は io_lib:format/2 のラッピング
    format("MISSING-USER-ID | user_id=~p", [UserId]);
format_error(_Reason) ->
    <<"INTERNAL-ERROR">>.
```

あとはこれを lager:warning(format_error(Reason)) という形で突っ込むパターンが多いです。

## まとめ

エラーメッセージは王道がなく、難しいと思っています。個人的には format_error/1 をうまく活用し Reason をそのまま食べさせロガーにはかせる仕組みが綺麗かなと思っています。

ちなみにエラーフォーマットは "ERROR-MESSAGE | key=value, key=value" key は sanke_case というルールで運用しています。
simple_one_for_one と monitor
Tags: erlang
Published: 2020-01-21 03:24:09

simple_one_for_one の中で simple_one_for_one のプロセスを動的に上げた場合、綺麗に終了する方法はいくつかありますが、 monitor を使うのが自分は好みです。

## monitor

monitor はプロセスを監視する仕組みです。supervisor を使うと再起動してくれるじゃないかと思いがちですが、何か不都合があったら **関連する全てのプロセスを終了したい** ということがたまにあります。

one_for_all でいいのではと思いがちですが、順番に起動していきたい、つまり依存関係がある場合に monitor を使います。

monitor は demonitor とセットで使います。supervisor:start_child/2 で上げて戻ってきた Pid を監視します。

そして terminate_child/2 する直前に demonitor します。demonitor しないと {'DOWN', MonitorRef, Type, Object, Info} が送られてきてしまいます。

### {'DOWN', MonitorRef, Type, Object, Info}

monitor はとても便利です。好きなプロセスを監視できます。 monitor に Pid を渡してあげるだけです。そのプロセスが死ぬときに {'DOWN', MonitorRef, Type, Object, Info} を monitor Ref を持っているプロセスに送ってきてくれます。

ほとんどの場合は Type は process で、Object は Pid で、Info は Reason です。

## 例

まずは UDP のソケットを動的に上げる仕組みを作るとします。

gen_server + gen_udp でそれを supervisor で simple_one_for_one にセットします。

よくあるパターンとして、パケットの書き換えに状態を必要とする場合があります。
暗号の鍵で IV を使うとかがいい例でしょうか。

その場合は復号/暗号処理用のプロセスを立ち上げます。ただほとんどの場合このプロセスはライブラリとして外に切り出しており supervisor もそのライブラリに含まれていることが多いでしょう。

この場合は process の監視を monitor を使うと良いです。つまり gen_server + gen_udp なプロセスが init/1 する際に、ライブラリの暗号プロセス（自分専用）を立ち上げて monitor して #state{monitor_ref = ...} として保存しておくべきでしょう。

### gen_server + gen_udp が死んだとき

まず terminate 部分で demonitor して terminate_child/2 して殺しましょう。この場合死ぬタイミングによっては monitor_ref が存在しない場合もあるので注意しましょう。

### 別ライブラリの monitor してるプロセスが死んだとき

想定外のエラーの場合、Erlang ではクラッシュさせて殺すのが通例です。

monitor していれば 'DOWN' で上がってきますので、あとは handle_info でハンドリングして、{stop, {shutdown, Reason}} で終了させてしまいましょう。


## まとめ

monitor/demonitor を使えるようになってやっと初心者卒業という印象を持っています。simple_one_for_one と monitor を使って色々やってみましょう。
.all? method of Enumerable for Array, Hash in Ruby is awesome!
Tags: rails, ruby
Published: 2020-01-21 03:22:22

## What is .all?
https://ruby-doc.org/core-2.7.0/Enumerable.html

## 🤔 Situations1: Stop the short circuit evaluation ( && )
Because .valid? has side effect and they want all of forms to evaluate validation, they can't use &&.

```ruby
@form_a.valid? & @form_b.valid?  # 🤔 evaluate both of valid? but using & is not natual
@form_a.valid? && @form_b.valid? # 🤔 evaluate only forward if it is false
```

## 👍 Solve it
```ruby
forms = [@form_a.valid?, @form_b.valid?]
(forms.map(&:valid?)).all?
```

## 🤔 Situation2: isn't there any errors?
```ruby
valid = true
users.each do |user|
  valid = false unless user.valid?
end
valid
```

## 👍 Solve it
```ruby
users.map{ |user| user.valid? }.all?
```
GUI for Salesforce CLI
Tags: vscode, salesforce, sfdx, salesforcecli
Published: 2020-01-21 03:19:59

Whenever I wanted to run a Salesforce CLI command, I had to switch between Command prompt and Salesforce CLI documentation and do the following:

<Ol>
<li>Search for the Command in the documentation</li>
<li>Read about its usage</li>
<li>Copy paste the sample command to command prompt</li>
<li>Modify it to suit my needs
<li>And finally run it (BAMM ! ERROR 😋)</li>
</Ol>

I had to go through this strenuous routine every time. **What if all these can be done in one spot with just point and clicks?** This thought pushed me to develop a Visual Studio code extension [**Salesforce CLI Command Builder - A GUI for Salesforce DX CLI**](https://marketplace.visualstudio.com/items?itemName=VignaeshRamA.sfdx-command-builder)

It provides a simple GUI (Graphical User Interface) to build, execute, learn & play around SFDX CLI commands from within vs code. It uses Reactjs for frontend code and standard VS Code Extensions API, nodejs & typesript for backend logic. Basically I am not a ReactJS developer. But the knowledge in Lightning Web Components helped me to learn ReactJS in no time (planning to write a separate post on my LWC to ReactJS journey).

**Screenshots:**
![Screenshot1](https://thepracticaldev.s3.amazonaws.com/i/vebyfjgbdyu7s10d58x2.PNG)

![screenshot2](https://thepracticaldev.s3.amazonaws.com/i/7evn8tzao5mu5qjw3d3o.PNG)

Check out my extension Salesforce CLI Command builder
https://marketplace.visualstudio.com/items?itemName=VignaeshRamA.sfdx-command-builder

GitHub
https://github.com/vignaesh01/sfdx-command-builder#readme
What is a good option for a PWA?
Tags: discuss
Published: 2020-01-21 03:19:07

---
title: What is a good option for a PWA?
published: true
description: pwa frontend framework
tags: discuss
---

Hi all, I need to start building a PWA for a client. I am bit new to it, so want some suggestion from you. 

What will be a good option for PWA? React, Angular, Vue or Flutter or any other options you want to mention.
gen_server を終了させる
Tags: erlang
Published: 2020-01-21 03:18:21

プロセスをちゃんと終了させるのは Erlang のプログラミングでとても重要です。

gen_server を終了するにはいくつかの方法があります。

## gen_server の callback

### init/1 

{stop, Reason} を使用します。

### handle_call/3 

{stop, Reason, Reply, NewState} という値を戻してから終了します。

### handle_cast/2 

{stop, Reason, NewState} を使用します。これは call でも使えます。
cast は非同期なので戻り値は常に ok のため、 Reply は使用できません。

### handle_info/2

これは call と同様 {stop, Reason, State} を使用します。

### stop

18.0 で gen_server:stop/1,3 が導入されました。これは外から gen_server プロセスを終了させられます。

stop/1 では terminate/2 に上がってくる理由はデフォルトでは normal です。
もし変えたい場合は stop/3 を使います。

## shutdown

終了の Reason には 3 つ report を上げない方法があります。その 3 つの理由以外では error_logger:format/2 が上がります。

- normal
- shutdown
- {shutdown, Reason}

上記の gen_server の callback を使うときに **正常終了** をする場合は、この 3 を使います。
正常終了というのはレポートを上げない終了です。

たとえば init/1 時に問題が合った場合はその理由を元に {stop, Reason} とやりがちですが、これだとレポートが上がりエラーとなります。

エラーレポートを上げないで終了する場合は {stop, {shutdown, Reason}} としましょう。

もし gen_server を simple_one_for_one の supervisor:start_child/2 で上げていた場合の {error, Reason} のReason は {shutdown, Reason} となります。

## 丁寧に終了するメリット

不必要にログをはかなくなります。握りつぶしているわけではなくちゃんと Reason を指定すれば terminate で拾えますのでそこでログをはいた方が良いです。

simple_one_for_one などでプロセスを管理している場合は monitor で連携したりすることもあるでしょう。その際正常に終了しないと、プロセスがクラッシュしたと判断されてしまうことがあります。

## まとめ

Erlang ではプロセスが簡単に上げられます。立ち上げるのは簡単ですが、役目を終えたプロセスを正常に終了することを意識した記事はあまりないので書き出してみました。


## 参考

リンクに関する話は以下を読みましょう。

- [リンクされたプロセスの終了時の挙動 #Erlang - Qiita](http://qiita.com/KOU_CHANG/items/a75bf7f882fe1f8cc9dd)
Deno vs Node.js: Deno Will Replace Node.JS?
Tags: javascript, node, webdev, tutorial
Published: 2020-01-21 03:16:57

A decade after Node.js was first announced, JavaScript and the web platform have evolved, and TypeScript has changed the way JS applications are developed. Deno is a new JavaScript/TypeScript runtime that was designed with all those new capabilities in mind.

{% youtube PnRUiS1B_a8 %}
Erlang 17.5 で使用可能な楕円曲線暗号
Tags: erlang
Published: 2020-01-21 03:15:36


crypto:ec_curves() で見れる。

```
> crypto:ec_curves().
[secp112r1,secp112r2,secp128r1,secp128r2,secp160k1,secp160r1,secp160r2,
 secp192r1,secp192k1,secp224k1,secp224r1,secp256k1,secp256r1,secp384r1,
 secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,
 prime256v1,wtls6,wtls7,wtls8,wtls9,wtls12,brainpoolP160r1,brainpoolP160t1,
 brainpoolP192r1,brainpoolP192t1,brainpoolP224r1,brainpoolP224t1,
 brainpoolP256r1,brainpoolP256t1,brainpoolP320r1,brainpoolP320t1,
 brainpoolP384r1,brainpoolP384t1,brainpoolP512r1,brainpoolP512t1,sect113r1,
 sect113r2,sect131r1,sect131r2,sect163k1,sect163r1,sect163r2,sect193r1,
 sect193r2,sect233k1,sect233r1,sect239k1,sect283k1,sect283r1,sect409k1,
 sect409r1,sect571k1,sect571r1,c2pnb163v1,c2pnb163v2,c2pnb163v3,c2pnb176v1,
 c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,c2tnb239v2,c2tnb239v3,
 c2pnb272w1,c2pnb304w1,c2tnb359v1,c2pnb368w1,c2tnb431r1,wtls1,wtls3,wtls4,
 wtls5,wtls10,wtls11,ipsec3,ipsec4]
```

QUIC で使われている prime256v1 には対応している模様。
Erlang/OTP で <<15,254>> を <<"0FFE">> にする方法
Tags: erlang
Published: 2020-01-21 03:12:43


もう、何度も作っててツラくなってきた。早く標準ライブラリとして実装して欲しい。

## 今後皆が使うべき実装

```erlang
<< <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= <<0,1,253,255>> >>.
```

## よく使ってた実装

```erlang
> list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= <<0,1,254,255>> ]).
<<"0001FEFF">>
```

```erlang
-spec hexlify(binary()) -> binary().
hexlify(Binary) ->
    list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= Binary ]).
```

もっとシンプルで早い方法があれば是非教えて欲しい。


## 皆様の実装

https://twitter.com/k0u_chang/status/600686773279199232

```erlang
> << <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= <<0,1,253,255>> >>.
<<"0001FDFF">>
```

https://twitter.com/hio/status/600690978287013888

```erlang
> << <<(X + if X < 10 -> $0; true -> $A - 10 end)>> || <<X:4>> <= <<0,1,254,255>> >>.
<<"0001FEFF">>
```

https://gist.github.com/sile/c8df7cc9a106c7d86039

コンパイルをすると ...

## 測定大会

環境

```
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
```

```erlang
> timer:tc(fun() -> list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= list_to_binary(lists:seq(0,255)) ]) end).
{3486,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
> timer:tc(fun() -> << <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= list_to_binary(lists:seq(0,255)) >> end).
{6650,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
> timer:tc(fun() -> << <<(X + if X < 10 -> $0; true -> $A - 10 end)>> || <<X:4>> <= list_to_binary(lists:seq(0,255)) >> end).
{9026,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
```

https://gist.github.com/sile/c8df7cc9a106c7d86039

実行は提案者の環境

```erlang
> timer:tc(fun() -> hexlify:hex1(list_to_binary(lists:seq(0,255))) end).                                                                   
{220,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
 
> timer:tc(fun() -> hexlify:hex2(list_to_binary(lists:seq(0,255))) end).
{36,
 <<"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435"...>>}
```
 
```erlang
-module(hexlify).
 
-export([hex1/1, hex2/1]).
 
hex1(Bin) ->
  list_to_binary([ io_lib:format("~2.16.0B", [X]) || <<X:8>> <= Bin ]).
 
hex2(Bin) ->
  << <<if X < 10 -> X + $0; true -> X - 10 + $A end>> || <<X:4>> <= Bin >>.
```
Erlang/OTP でのロギングについて
Tags: erlang
Published: 2020-01-21 03:12:17


あんまりたいしたこと書いてないです。追記型。

## lager

Riak の Basho が公開しているフレームワーク。ほぼデファクトであろう。

良く出来てる。

### crash.log のローテーション時間や世代を管理したい

https://github.com/basho/lager/blob/master/src/lager.app.src

ここにデフォルトが設定してあるので、これを上書きしてあげれば良い。

```erlang
%% Whether to write a crash log, and where. Undefined means no crash logger.
{crash_log, "log/crash.log"},
%% Maximum size in bytes of events in the crash log - defaults to 65536
{crash_log_msg_size, 65536},
%% Maximum size of the crash log in bytes, before its rotated, set
%% to 0 to disable rotation - default is 0
{crash_log_size, 10485760},
%% What time to rotate the crash log - default is no time
%% rotation. See the README for a description of this format.
{crash_log_date, "$D0"},
%% Number of rotated crash logs to keep, 0 means keep only the
%% current one - default is 0
{crash_log_count, 5},
```

- crash_log
    - ファイル出力先
- crash_log_msg_size
    - crash ログは error_logger をリダイレクトに渡してるので、そのサイズ指定
- crash_log_size
    - ログローテーションサイズ
    - 0 にすればローテーションされない
- crash_log_date
    - ログローテの日時
    - "" にすれば時間していはなくなる
- crash_log_count
    - 世代、デフォルトは 5 まで、 0 にすれば世代管理されない

## erlang.log

勝手に出来るけど、こいつ何者だ感があるやつ

デフォルトだと 100キロバイト単位で 5 世代でログローテーションしていく

だが、環境変数で設定は変更可能だったりする。

http://www.erlang.org/doc/man/run_erl.html

```
RUN_ERL_LOG_GENERATIONS
Controls the number of log files written before older files are being reused. Default is 5, minimum is 2, maximum is 1000.
RUN_ERL_LOG_MAXSIZE
The size (in bytes) of a log file before switching to a new log file. Default is 100000, minimum is 1000 and maximum is approximately 2^30.
```

- RUN_ERL_LOG_GENERATIONS
    - 世代管理、デフォルトは 5
    - 最小は 2 で、最大は 1000
- RUN_ERL_LOG_MAXSIZE
    - ログローテーションのサイズですデフォルトは 100キロバイト
    - 最小 1000 バイト