$ sudo yum install elixir
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
パッケージ elixir は利用できません。
エラー: 何もしません
[ec2-user@ip-10-0-1-175 src]$
$ sudo amazon-linux-extras install -y epel
$ sudo yum install elixir
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
パッケージ elixir は利用できません。
エラー: 何もしません
[ec2-user@ip-10-0-1-175 src]$
$ sudo amazon-linux-extras install -y epel
$sudo yum install git autoconf gcc gcc-c++ glibc-devel make ncurses-devel openssl-devel unixODBC unixODBC-devel java-1.8.0-openjdk-devel
$sudo git clone https://github.com/erlang/otp.git
$sudo chown ec2-user:ec2-user -R otp/
$cd otp
$sudo ./otp_build autoconf
$sudo ./configure #--prefix=/usr/local/erlang
$sudo make
$sudo make install
vi ~/.bash_profile
PATH=$PATH:/usr/local/erlang/bin
#sudo git clone https://github.com/elixir-lang/elixir.git
#sudo chown ec2-user:ec2-user -R elixir/
$make clean test
Flutter を勉強し始めた。
そこで少しハマったところを覚え書きとして記載しておく。
下記のコードでも両方動作する。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Sample Page'),
),
),
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sample Page'),
),
);
}
上記2つは動作するのだが、その違いは大きい。例えば、前画面から上記のページを下記にて呼んだ場合、前者はナビゲータバーの戻るボタンが表示されない。つまり、ページのスタックに積まれるのはAppレベルではないため階層が異なる。
Navigator.push(context, MaterialPageRoute(builder: (context) => NextPage()));
少しづつだが理解を深めたいと思う。
$ mix phx.new ProjectName --app project_name --no-ecto
$ cd ProjectName/assets/node_modules/
$ npm install --save @babel/preset-react
$ npm install --save @babel/polyfill
$ npm install --save react react-dom redux react-redux
$ npm install --save react-router-dom
$ npm install --save connected-react-router history
$ npm install --save redux-thunk
$ npm install --save axios
$ npm install --save redux-form react-hook-form
$ npm install --save react-bootstrap
$ npm install --save history
$ npm install redux-saga --save
assets/.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/react"
]
}
$mv assets/js/app.js assets/js/index.js
index.js
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<div>
Hello React!!
</div>,
document.getElementById('root')
);
webpack.config.js
entry: {
'./js/index.js': glob.sync('./vendor/**/*.js').concat(['./js/index.js'])
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, '../priv/static/js')
},
lib/project_name_web/templates/page/index.eex
<section class="row">
<article class="column">
<div id="root"></div>
</article>
</section>
lib/project_name_web/templates/layout/app.eex
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/index.js") %>"></script>
Timex を使用した時の、現在時間フォーマット。
Timex.format!(Timex.now("Asia/Tokyo"), "%Y/%m/%d %H:%M:%S", :strftime)
GCP VMインスタンスをCentOSで構築しようとした。あまりGCPについて詳しくないまま、インスタンスを立ち上げた。
どうも、必要なライブラリが何も入っていないのでメモ書き。
OS環境の構築
$ sudo yum install gcc
$ sudo yum install ncurses-devel
$ sudo yum install autoconf
Erlang のインストール
$ sudo ./otp_build autoconf
$ sudo ./configure
$ sudo make
$ sudo make install
インストールしたErlangのバージョンの確認
$ erl -v
Erlang/OTP 23 [DEVELOPMENT] [erts-10.4] [source-fe2b132] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [hipe]
Eshell V10.4 (abort with ^G)
ファイルのデータ構造を、縦持ちから横持ちに使用と思い、大量データなのでExcelでは無理、Pandasを使用しようと思ったが挫けた。そこで、久しぶりにElixirで処理を書いてみた。
元ファイル(.tsv)
1 Bob Elixir
1 Bob Java
1 Bob Ruby
2 Tom Elixir
2 Tom C#
3 Dave Python
3 Dave Java
3 Dave Ruby
4 Jane Python
整形後ファイル (.tsv)
1 Bob Elixir Java Ruby
2 Tom Elixir C#
3 Dave Python Java Ruby
4 Jane Python
defmodule FormatTsv do
def convert do
headers = [:id, :name, :lang]
out_file = "out.tsv"
result = "data.tsv"
|> File.stream!
|> CSV.decode(separator: ?\t, headers: headers)
|> Enum.map(&(elem(&1, 1)))
|> Enum.group_by(fn(x)-> x[:id] end)
|> Enum.map(fn {id, values} ->
"#{id}\t#{Enum.at(values, 0)[:name]}\t#{Enum.at(values, 0)[:lang]}\t#{Enum.at(values, 1)[:lang]}\t#{Enum.at(values, 2)[:lang]}\n"
end)
File.write(out_file, result)
end
end
できてしまうと、お気軽で楽しいElixirである。
Elixir の Enum.group_by の使用方法にもやもやしていたので覚え書き。
["Elixir","Java","C#","Python","Ruby"] |> Enum.group_by(fn(x)-> String.length x end) iex(1)> FormatTsv.test %{2 => ["C#"], 4 => ["Java", "Ruby"], 6 => ["Elixir", "Python"]}
出力例を見てわかるように、リストの要素に対して、関数 fn で 返却した値で、グループ化している。
3年に1度は必ず実装する必要がある技術。
覚え書きです。
<html> <head> <title>JS</title> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"> </script> </head> <body> <select name="item" id="item"> <option value="">りんご</option> <option value="">イチゴ</option> <option value="">バナナ</option> </select> <script> $(function(){ $('#item').change(function(){ $.ajax({ url:"/data.json", type:"POST", data:$("#form1").serialize(), dataType:"json", timespan:1000 }).done(function(data1,textStatus,jqXHR) { console.log(jqXHR.status); console.log(textStatus); console.log(data1); console.log(data1["data"][0].name); var data2 = JSON.stringify(data1); console.log(data2); var data3 = JSON.parse(data2); console.log(data3); $("#item option").remove(); $("#item").append("<option></option>"); $.each(data3["data"], function(key, value){ console.log(key + ':' + value); $("#item").append($("<option>").val(value.id).text(value.name)); }); }).fail(function(jqXHR, textStatus, errorThrown ) { console.log(jqXHR.status); console.log(textStatus); console.log(errorThrown); console.log('Failed'); }).always(function(){ console.log("complete"); }); }); }); </script> </body> </html>
{"data" : [ { "id" : "1", "name" : "太郎", "age" : "12" }, { "id" : "2", "name" : "花子", "age" : "14" }, { "id" : "3", "name" : "金太郎", "age" : "32" }, { "id" : "4", "name" : "桃太郎", "age" : "47" }, { "id" : "5", "name" : "赤太郎", "age" : "23" } ]}
RxSwiftのシンプルな説明
Swiftで簡単なアプリを写経するのは簡単なのであるが、やはり実用的なアプリを作成するには、レスポンシブでないと役な立たない(お客さん受けしない)よねということで、RxSwift
を学んでみた。
正直、3日間くらい、泣きながら、挫けそうになりながら、禿げそうになりながら食らいついていた。
はっきりいって理解するのがキツイ。
■ 開発環境
OS : MacOS High Sierra Version 10.13.6
Xcode : Version 9.4.1
■ サンプリアプリ
ボタンを押すとカウントアップするだけのアプリ。
■ ソースコード解説
ViewController.swift
のコードを説明する。
まずは、必要なライブラリをimportする。ここでは、RxSwift
を利用する。
import UIKit import RxSwift
先に、ラベルとボタンを配置する。
StreatBoardでも良いのであるが、敢えてコードで記述。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Label let countLbl = UILabel() countLbl.text = "0" countLbl.textAlignment = .center countLbl.textColor = UIColor.blue countLbl.frame = CGRect(x: (self.view.frame.width-110)/2, y: 150, width: 110, height: 21) // Button let countUpBtn = UIButton() countUpBtn.frame = CGRect(x: (self.view.frame.width-100)/2, y: 200, width: 100, height: 30) countUpBtn.layer.borderWidth = 1.0 countUpBtn.layer.borderColor = UIColor.blue.cgColor countUpBtn.layer.cornerRadius = 5.0 countUpBtn.setTitleColor(UIColor.blue, for: .normal) countUpBtn.setTitle("カウントUP", for: .normal) countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside) self.view.addSubview(countLbl) self.view.addSubview(countUpBtn) }
次に、RxSwift
の肝であるクラスを作成する。
class RxSwiftSample { }
RxSwiftSample
クラスには、private宣言されたsubject
をPublishSubject<Int>()
でインスタンス化して保持しておく。それと、そのsubjectをObservableとして返すeventを定義する。
そして、実際の処理を外部から呼べる myFunc()
メソッドを定義する。その中で、onNext
とかいうイベントを発行する。
これが基本的な雛形という感じかな?
class RxSwiftSample { private let subject = PublishSubject<Int>() var event : Observable<Int>{ return subject } func myFunc(){ // 処理 print("myFuncが呼ばれました。") // イベント発行 subject.onNext(self.data) } }
次に、このRxSwiftSample
クラスの使い方なのであるが、ViewController
から利用できるように、RxSwiftSample
をモデルとしてmodel
で宣言しておく。また、後で利用するdisposeBag
も宣言しておく。
private let model = RxSwiftSample() private let disposeBag = DisposeBag()
上記を、ViewController
から利用する。
先ずは、順を追ってわかりやすく、ボタンに対して、countUp(_ sender: UIButton)
が呼ばれるように記述する。これは特に問題はないはず。
重要なのは、ここからmodel
のmyFunc()
を呼び出すことである。
override func viewDidLoad() { //ボタンへイベント登録 countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside) } @objc func countUp(_ sender: UIButton){ print("カウントアップ") //Modelの関数呼び出し model.myFunc() }
ここから、理解が進むと思うが、model.myFunc()
で処理を行うと、事前に登録されているsubscribe
で通知される。そして、 subject.onNext(self.data)
で渡されたパラメータも、value で受け取れる。
//Reactive処理 model.event.subscribe( onNext: {value in print("ここで通知") countLbl.text = String(value) }) .disposed(by: disposeBag)
これで、ようやく頭の中で処理シーケンスがつながった。
それでも理解できない場合は、私と同じように1日悩んで、print()
仕掛けて、処理を追ってみると良いと思う。
やはり、このようなフレームワークやデザインパターンの理解は正直キツイ。それでも、時間を掛けて手を動かすのが、ベストプラクティスだと思う。
その助けになればと祈る。情報がちょっと時代遅れ感はあるのだが・・・。
始めたのが遅いので仕方ない。w
■ 最後に
ここに記したコードは、自分がRxSwift
の構造を理解するために作成したコードです。間違い等がございましたらご指摘願います。
下記、全ソースコードです。
import UIKit import RxSwift private let model = RxSwiftSample() private let disposeBag = DisposeBag() class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Label let countLbl = UILabel() countLbl.text = "0" countLbl.textAlignment = .center countLbl.textColor = UIColor.blue countLbl.frame = CGRect(x: (self.view.frame.width-110)/2, y: 150, width: 110, height: 21) // Button let countUpBtn = UIButton() countUpBtn.frame = CGRect(x: (self.view.frame.width-100)/2, y: 200, width: 100, height: 30) countUpBtn.layer.borderWidth = 1.0 countUpBtn.layer.borderColor = UIColor.blue.cgColor countUpBtn.layer.cornerRadius = 5.0 countUpBtn.setTitleColor(UIColor.blue, for: .normal) countUpBtn.setTitle("カウントUP", for: .normal) countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside) self.view.addSubview(countLbl) self.view.addSubview(countUpBtn) //Reactive処理 model.event.subscribe( onNext: {value in countLbl.text = String(value) }) .disposed(by: disposeBag) } @objc func countUp(_ sender: UIButton){ //Modelの関数呼び出し model.myFunc() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } } class RxSwiftSample { private let subject = PublishSubject<Int>() private var data = 0 var event : Observable<Int>{ return subject } func myFunc(){ // 処理 data = data + 1 // イベント発行 subject.onNext(self.data) } }
Lovly Swift!!!