###########
# # # # # # # #
###########
veer66
###########
# # # # # # # #
###########
ใน Python ตาม code ข้างล่าง append เป็น method ของ object a แต่พอมานับจำนวนสมาชิกใช้ len(a) ซึ่ง len เป็น built-in function แทน ถ้าอยากให้มีรูปแบบเดียวกันเปลี่ยนจาก len(a) ไปเป็น a.__len__() ก็ได้ แต่ก็จะมี ____ เกินมาอีก ใน Python เองก็คงจะมีหลักเกณฑ์ว่าเมื่อไหร่อะไรจะเป็น function อะไรจะเป็น method ซึ่งก็อาจจะต้องเรียนรู้หรือจำไว้
a = [1, 2, 3, 4, 5]
a.append(10)
print(len(a))
ใน JavaScript ก็มีรูปแบบที่ต่างกันคือ push เป็น method แต่ length เป็น property สังเกตได้จากว่าตอนเรียกไม่มีวงเล็บ ใน JavaScript ก็คงมีหลักการว่าเมื่อไหร่อะไรจะเป็น method หรือเป็น property ซึ่งก็ต้องเรียนรู้หรือจำไว้
a = [1, 2, 3, 4, 5]
a.push(10)
console.log(a.length)
ใน Ruby ทีนี้เหมือนกันแล้วคือ push ก็เป็น method และ length ก็เป็น method
a = [1, 2, 3, 4, 5]
a.push(10)
p(a.length)
แต่ก็ยังมีประเด็นต่อไปอีกว่าทำไมใน Ruby เขียนแบบนี้
10 + 20 + 30 + 40 + 50
ไม่เป็น method และเรียกเหมือนอย่างอื่นบ้างล่ะ
10.+(20).+(30).+(40).+(50)
(Emacs) Lisp จะต่างกับอันอื่นหน่อย ตรงที่ push มันไปต่อหน้าแทนที่จะต่อหลัง
(setq a '(1 2 3 4 5))
(push 10 a)
(print (length a))
(+ 10 20 30 40 50)
เขียน Lisp นี่ทุกอย่างก็จะเรียงเหมือนกันหมดเลย ได้แก่ (push ...) (length ...) (+ ...) ไม่เดี๋ยวต่อหน้า len(...) หรือเดี๋ยวต่อหลังเป็น a.length หรือว่าเดี๋ยวมีหรือไม่มีวงเล็บ เช่น a.length กับ a.length
แต่ปัญหาที่มันจะเจอคือหลายท่านรับไม่ได้ที่วงเล็บไปอยู่ข้างหน้าชื่อ function ถึงกับว่ามันวงเล็บย้ายที่แล้วเขียนไม่ได้เลย
แต่ Julia ก็เขียนแบบนี้ได้ append! ก็เป็น length ก็เป็น function ทั้งคู่ แถมตอนบวกก็เขียนแบบ function ได้ด้วย
a = [1,2,3,4,5]
append!(a,10)
print(length(a))
+(10,20,30,40,50) # จะเขียนแบบ 10 + 20 + 30 + 40 + 50 ก็ได้
แต่ก็อาจจะคิดได้ว่าทำเวลาสร้าง array ไม่เป็น function บ้าง ก็อาจจะเปลี่ยน [1,2,3,4,5] เป็น push!([],1,2,3,4,5) แทน ทีนี้ก็จะเหลือแต่ = แล้วที่ดูไม่เหมือนอย่างอื่น ซึ่งอันนี้ผมก็นึกวิธีแก้ให้มันเหมือนกันไม่ออก
from google.colab import drive
drive.mount('/content/drive')
import os
os.listdir('/content/drive/My Drive')
โพสต์นี้คนอ่านที่เป็นเป้าหมายหลักก็คือผมเอง
อย่างแรกเลยสมมุติว่า ElasticSearch ที่รันอยู่แล้ว
สร้าง dir ที่จะเก็บ snapshot และ chown ให้เป็นของ user เดียวกับที่ daemon ของ elasicsearch รันอยู่
แก้ elasticsearch.yml ที่ path.repo ให้ชี้ไปที่ dir ที่สร้างไว้ในข้อ 1 เช่น [“/bak/b1”] ไรงี้
สร้าง repo
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "/bak/b1"
}
}
'
สร้าง repo
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true&pretty"
ตอนนี้ก็คือจะเสร็จแล้ว สิ่งที่ผมทำคือ rsync /bak/b1 ไปเครื่องอื่นแล้วลอง restore เพื่อไม่ให้น่าเบื่อเครื่องอื่นที่ว่าก็จะใช้ docker ด้วย
พอ rsync มาแล้ว ก็ chown -R 1000:1000 $(pwd)/bak/b1
สร้าง elasticsearch.yml
cluster.name: "docker-cluster"
network.host: 0.0.0.0
path.repo: ["/usr/share/elasticsearch/bak"]
รัน ElasticSearch ผ่าน Docker
docker run \
--name=es6 \
--net=host \
-e "discovery.type=single-node" \
-v $(pwd)/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v $(pwd)/bak/b1:/usr/share/elasticsearch/bak \
docker.elastic.co/elasticsearch/elasticsearch:6.8.4
สร้าง repo
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "/usr/share/elasticsearch/bak"
}
}
'
สั่ง restore
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "/usr/share/elasticsearch/bak"
}
}
'
เสร็จแล้ว
คำสั่งต่าง ๆ ก็มาจาก guide ครับ
ผมทำตามตัวอย่างที่ https://tantivy-search.github.io/examples/basic_search.html แต่โมพวก field แล้วก็แก้ให้เป็นสองไฟล์แบบที่อยากใช้งาน
[package]
name = "v_search"
version = "0.1.0"
authors = ["Vee Satayamas <vee.sa@protonmail.com>"]
edition = "2018"
[dependencies]
tantivy = "0.10.2"
[[bin]]
name = "make_index"
path = "src/make_index.rs"
[[bin]]
name = "search"
path = "src/search.rs"
ส่วนที่ผมงงแรก ๆ เลยคือ STORED อ่านมาบอกว่าสามารถอ่านข้อมูลคืนมาด้วย id เข้าใจว่าถ้า field ไหนไม่ STORED คือทำ index อย่างเดียวจริง ๆ แต่ข้อมูลต้นฉบับหาย แต่ผมก็ยังไม่ลองว่าถ้าไม่ใส่มันจะไม่ได้เชียวหรือ ?
use tantivy::doc;
use tantivy::schema::*;
use tantivy::Index;
fn main() -> tantivy::Result<()> {
let index_path = "idx";
let mut schema_builder = Schema::builder();
schema_builder.add_text_field("textunit", TEXT | STORED);
let schema = schema_builder.build();
let textunit = schema.get_field("textunit").unwrap();
let index = Index::create_in_dir(&index_path, schema.clone())?;
let mut index_writer = index.writer(50_000_000)?;
index_writer.add_document(doc!(
textunit => "A",
));
index_writer.commit()?;
Ok(())
}
use tantivy::collector::TopDocs;
use tantivy::query::QueryParser;
use tantivy::schema::*;
use tantivy::Index;
use tantivy::ReloadPolicy;
fn main() -> tantivy::Result<()> {
let index_path = "idx";
let mut schema_builder = Schema::builder();
schema_builder.add_text_field("textunit", TEXT | STORED);
let schema = schema_builder.build();
let textunit = schema.get_field("textunit").unwrap();
let index = Index::open_in_dir(index_path)?;
let reader = index
.reader_builder()
.reload_policy(ReloadPolicy::OnCommit)
.try_into()?;
let searcher = reader.searcher();
let query_parser = QueryParser::for_index(&index, vec![textunit]);
let query = query_parser.parse_query("A")?;
let top_docs = searcher.search(&query, &TopDocs::with_limit(10))?;
for (_score, doc_address) in top_docs {
let retrieved_doc = searcher.doc(doc_address)?;
println!("{}", schema.to_json(&retrieved_doc));
}
Ok(())
}
อันนี้ผมก็คือทำ index ไว้ใน directory ชื่อ idx แล้ว แล้วอีกไฟล์ก็มา search แค่นี้เลย
code แค่นี้เลย
fn cnt_links(s: usize, e: usize, tu: &Textunit, en_sent: &RTok) -> usize {
tu.links.iter()
.filter(|link| link.target > s && link.target < e)
.filter(|link| link.source >= en_sent.s && link.source < en_sent.e)
.count()
}
พอเขียน test แบบยาว ก็เจอจุดพัง
#[test]
fn cnt_links_simple() {
let tu = Textunit {
bi_text: BiText { source: String::from(""),
target: String::from(""),
},
bi_rtoks: BiRToks {
source: vec![RTok {s:100, e:101, text: String::from(" ")},
RTok {s:102, e:103, text: String::from(" ")},],
target: vec![RTok {s:300, e:301, text: String::from(" ")},
RTok {s:302, e:303, text: String::from(" ")},],
},
links: vec![Link {source: 0, target: 1},
Link {source: 1, target: 0}],
};
let en_sent = RTok {s: 302, e:303, text: String::from(" ")};
assert_eq!(cnt_links(0, 1, &tu, &en_sent), 1);
}
ระบบ type ช่วยอะไรไม่ค่อยได้เพราะมันเป็น integer หมด ยกเว้นจะใช้ type แบบที่มีหน่วยได้ แต่แบบนั้นก็ไม่รู้ว่าโปรแกรมจะยาวกว่านี้อีกเปล่า
รู้สึกว่าปัญหาของโปรแกรมนี้หลัก ๆ เลยคือ test มันยาวเกิน
มันเป็น API อยู่ที่ https://cloud.google.com/speech-to-text/ มีวิธีใช้พร้อม ผมเปลี่ยน config นิดหน่อย ตามนี้ครับ
เขามีไฟล์ PDFให้อ่านด้วยนะครับ
แต่แค่อยากลองว่า Google มันจะฟังออกแค่ไหน
config = { encoding: :FLAC,
sample_rate_hertz: 16_000,
language_code: "th-TH" }
เพื่อใช้ในการวิจัยและไม่ได้มีการหาผลประโยชน์อะไรเลยนะครับ ตามนี้ https://file.veer66.rocks/nlp/sample1min7.flac
อันนี้เอาไฟล์เตรียมไฟล์ video ก่อนเพื่องานวิจัยและไม่ได้มีการหาผลประโยชน์
ffmpeg -i http://live.parliament.go.th/livestream/encoder3/playlist.m3u8 -c copy -bsf:a aac_adtstoasc output.mp4
แล้วก็แปลงเป็นเสียงเพื่องานวิจัยและไม่ได้มีการหาผลประโยชน์
ffmpeg -i output.mp4 sample.mp3
หลังจากนั้นผมใช้ Audacity แก้เสียง sample.mp3 ให้เป็น mono 16-bit แล้ว save เป็น .flac ครับ เพื่องานวิจัยและไม่ได้มีการหาผลประโยชน์อีกเช่นเคย
ชาติแห่งชาติขุนกลางยึดมั่นในหลักจริยธรรมและธรรมาภิบาลมีสมรรถนะและความรู้ความสามารถพร้อมต่อการเปิดงานดำเนินการปรับปรุงสวัสดิการสวัสดิภาพชีวิตขวัญกำลังใจความเป็นอยู่ให้เกิดความปลอดภัยในการทำงาน
I guess many people wrote this kind of scripts already. But sometimes searching is more complicated than just writing a new one. 😅 If you know a keyword, please tell me.
This script should work with other commands. I use target/release/main because I want to test my program built from Rust's Cargo. I suppose other commands can replace target/release/main.
#!/bin/sh
CMD=target/release/main
$CMD > log 2>&1 &
export PID=$!
echo "Process $PID is running ..."
trap "echo kill $PID; kill $PID; exit" INT QUIT
rm -f mem.tsv
while true
do
tm=`date '+%Y-%m-%dT%H:%M:%S'`
rss=`ps -u | awk -v PID=$PID '{ if ($2 == PID) { print $6; } }'`
echo "$tm\t$rss" >> mem.tsv
sleep 10
done
It logs memory usage in mem.tsv, so I should be able to plot a graph by LibreOffice Calc easily.
When the producer sends messages too frequently, and the producer takes too much time to process each message. I wrote a code for
I want to discard aging messages and process only the latest one. So I wrote a code for repeating receive messages until the channel is empty for a short duration. However, I found my code was too complicated. So I use shared memory with mutex-lock for inter-thread communication instead of a channel.
use std::sync::{Mutex, Arc};
use std::{thread, time};
use std::collections::HashMap;
fn main() {
let r_shared_data = Arc::new(Mutex::new(None));
let w_shared_data = r_shared_data.clone();
thread::spawn(move || {
let tx_delay_time = time::Duration::from_millis(100);
loop {
for i in 1..1000 {
let mut h = HashMap::new();
h.insert("X", i);
let mut w = w_shared_data.lock().unwrap();
*w = Some(h);
if i % 10 == 0 {
thread::sleep(tx_delay_time);
}
}
}
});
let task_proc_time = time::Duration::from_millis(500);
loop {
let r = r_shared_data.lock().unwrap();
dbg!(r);
// long task
thread::sleep(task_proc_time);
}
}
เดิมโพสต์เมื่อ 2015-06-25
ภาษาใหม่ ๆ เดี๋ยวนี้ ทั้ง Rust, Swift, F#, Scala หรือภาษากลางเก่ากลางใหม่แบบ C#, Java 8, Python, Ruby, JavaScript มักจะมีกลิ่นอายของ Lisp/Scheme ติดมาด้วยเสมอเช่นการ ใช้ closure กับ map, foldl, foldr, filter เป็นต้น
เนื่องจากว่าเขียนได้ทั้งแนว Fortran และแนว Lisp เวลาคนเขียนภาษาใหม่ ๆ เช่น Python บางทีก็จะเถียงกัน (ผมเห็นจากใน blog ของคนอื่น) ว่าจะใช้ map filter reduce ทำไม อ่านยากจะแย่ จะเขียนสั้น ๆ ทำไม ต้องใช้ for-loop แทนสิ บางคนก็บอกว่า map filter reduce มันก็ดีอยู่แล้ว เขียน for-loop มันอ่านง่ายตรงไหน
ส่วนภาษา Go เป็นภาษาใหม่ที่เน้น imperative (แนว Fortran) ล้วน ๆ และออกแนว minimalism คำสั่งที่มีมาให้ก็เป็นไปแต่แบบพอเพียง บางอย่างที่เขาคิดว่าไม่จำเป็นเขาก็ไม่มีให้ ทำให้แน่นอนไม่มี map, fold, foldr, filter แถมมาให้ ถ้าอยากได้ก็ต้องทำเองในระดับ library
แน่นอนว่าในระดับ Library นี้ compiler เข้ามาช่วย optimize ให้ได้ยาก พอใช้ไปก็จะทำให้โปรแกรมช้าได้
ด้วย 2 เหตุนี้คือขัดวิถีโกและช้า ทำให้โอกาสที่ใคร ๆ จะเขียนแนว Lisp/Scheme ใน Go มีน้อย
ดังนั้นใครหรือทีมไหนที่ไม่ชอบเขียนโปรแกรมที่มีกลิ่นอายของ Lisp/Scheme ในยุคนี้ภาษา Go เหมาะอย่างยิ่ง