はてなキーワード: constとは
正直動けばいいと思うので、現状でも問題ないと思うけれどちょっとだけ気になった点。
$$使ってる時点で、デベロッパーツール前提なのは分かるけど、 javascriptで動かしたいのか、デベロッパーツールで動かしたいのか、どっちつかずな書き方になっている。
$$('.hatena-star-inner-count').map(a => a.click()); let data = {}; Array.from($$('.entry-comment-contents')).forEach(x => {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y => y.href.split('/')[3]);data[userName] = [comment, stars];}); console.info(Object.entries(data).map(x => { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("92;n"));
デペロッパーツールだけで動くだけでいいなら、3行目のArray.fromがなくても動く。多分、forEachをmapに書き換えても動く。個人的にはforEachに統一したいけど、そこは好みレベルの問題だと思う。
$$('.hatena-star-inner-count').map(a => a.click()); let data = {}; $$('.entry-comment-contents').forEach(x => {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y => y.href.split('/')[3]);data[userName] = [comment, stars];}); console.info(Object.entries(data).map(x => { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("92;n"));
逆に、javascriptで動かしたいなら1行目と3行目はquerySelectorAllに書き換えれる。
document.querySelectorAll('.hatena-star-inner-count').forEach((a)=>{a.click()}); let data = {}; document.querySelectorAll('.entry-comment-contents').forEach(x => {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y => y.href.split('/')[3]);data[userName] = [comment, stars];}); console.info(Object.entries(data).map(x => { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("92;n"));
これも好みの問題だけど、途中のconstの宣言は一回しか使ってないので、宣言せずにそのまんま入れてもいいんじゃないかと思った。
document.querySelectorAll('.hatena-star-inner-count').forEach((a)=>{a.click()}); let data = {}; document.querySelectorAll('.entry-comment-contents').forEach(x => {data[x.querySelector('.entry-comment-username a').href.split('/')[3]] = [x.querySelector('.entry-comment-text').innerText, Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y => y.href.split('/')[3])];}); console.info(Object.entries(data).map(x => { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&#92;n")); |<<
でもよー、それJavaScriptだろ?
const sode = []; // 袖が存在しない! const swing = sode.every(it => it.canSwing); // 振れるだろ? console.log(swing); //=> true(振れるぜ)
だぜ。
aa ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʔ
じゃなくて
aa ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ
にしたい
javascript:(function (d, lowerThan, count) { const MinimumRequiredLength = 33; let currentCount = count(); const elem = d.querySelectorAll(".bookmarkadd-comment-form")[0]; if (!elem) { return; } if (lowerThan(count(), MinimumRequiredLength)) { if (elem.value.slice(-1) !== " ") { elem.value += " "; currentCount += 1; } } if (lowerThan(count(), MinimumRequiredLength)) { const kumas = ['ʕ•̫͡•', 'ʔ•̫͡•']; const indexes = '001101'; for (let i = 0; i === 0 || (lowerThan(currentCount + i * 5, MinimumRequiredLength) || currentCount + i * 5 === MinimumRequiredLength); i++) { elem.value += kumas[indexes[i % 6]]; } elem.value += 'ʔ'; elem.dispatchEvent(new Event("input")); } })(document, function(a, b) { return Math.floor(b / a) !== 0 }, function() { return Number(document.querySelectorAll('.js-bookmarkadd-comment-count')[0].innerText) || 0 } ); //add bear
こういう、特定の URL で特定の bookmarklet を呼び出す extension とか欲しい。これは用途に合わないけれど、クマを消すやつは自動で実行されてほしいものだろうし
クマが30匹程度では建設的と判定されないことがあるようなので、そんな時は
const MinimumRequiredLength = 30;
の部分を変えてみてください。
その際は、ドラッグし直すのでなく、
追加済みのブックマークレットを右クリック→「編集」で、30の部分だけ書き換えればOKです。
追記ここまで
https://anond.hatelabo.jp/20210803012020
に刺激を受けて作りました。
https://b.hatena.ne.jp/entry/4706344345181168386/comment/new3
で、書き込み時の自動クマ補完について書かれてたので、それを実装しました。
以下の文字列を選択して、Chromeのブックマークバーにドラッグしてください。
javascript:(function () { const MinimumRequiredLength = 30; const currentCount = Number(document.querySelectorAll(".js-bookmarkadd-comment-count")[0].innerText); if (Math.floor(MinimumRequiredLength / currentCount) !== 0) { const elem = document.querySelectorAll(".bookmarkadd-comment-form")[0]; if (elem.value.slice(-1) !== " ") { elem.value += " "; } const loopNum = Math.ceil((MinimumRequiredLength - currentCount) / 5); for (let i = 0; i !== loopNum; i++) { elem.value += "ʕ•̫͡•"; } elem.value += "ʔ"; elem.dispatchEvent(new Event("input")); } })();
「_5)」みたいな変な名前で追加されるので、右クリック→「編集」から好きな名前に変えてください。(addBearとか)
はてブのコメント書き込み画面でブックマークレットをクリックしてください。
これで追加したクマを、コメント一覧画面で削除するためのブックマークレットは、
javascript:(function () { document.querySelectorAll(".entry-comment-text").forEach(function (e) { e.innerText = e.innerText.replace(/[ʕ•̫͡•ʔ]+$/, ""); }); })();
です。
セットでお使いください。(名前はremoveBear?)
私はクマで埋めることはしないのですが、埋めたい人もいるでしょうから、道具としてはあればよいと思いました。
最後のクマだけ左頬のパーツを変えて……、など10秒くらい掛けてると思うのです。
その間、「ああ……またこんな作業をして……私ったら承認欲求の塊なのかしら、いやらしいわ」と自己嫌悪してたら可哀想なので、
少しでもネガティブな時間が短くなるよう、活用してみてください。
https://github.com/kokorohamoe/OpenProfile/blob/master/700_sample/Java/Jurina/reader.cpp
int main(int argc,const char*argv[]){
int v;
char buffer[1024];
while(1){
printf("input\n");
scanf("%s%d",buffer,&v);
if(strcmp(buffer,"print")==0)
fprintf(stderr, "public class base{\n"
"public static void main(String[] args){\n"
"int i = %d;\n"
"System.out.println(i);}}\n",v);
}
return 0;
}
https://b.hatena.ne.jp/entry/s/qiita.com/Yametaro/items/621bfd8c894f8fd36539
https://www.google.com/search?q=site%3Aqiita.com+%E3%83%91%E3%83%91
5歳娘「パパ、余分なpropsいっぱい書くんだね!」
4歳娘「パパ、具体的な名前をつけないで?」
5歳娘「パパ、変なAPIを作らないで?」
5歳娘「パパ、型はドキュメントだよ?」
5歳娘「パパ、依存性を注入して?」
4歳娘「パパ、懐かしいJavaScript書いてるね!」
5歳娘「パパ、型ガードって何?」
0歳娘「パパ、型を作る関数はないの?」
4歳娘「パパ、Promiseやasync/awaitって何?」
4歳娘「パパ、具体的な名前をつけないで?」
const array1 = [1,2,3,1,3,5];
const reducer = (accumulator, currentValue,idx) =>{
if(!(currentValue in accumulator)){
accumulator[currentValue]=[idx];
}else{
accumulator[currentValue].push(idx);
}
return accumulator;
};
console.log(array1.reduce(reducer,{}));
何だせっかく考えたのに
(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
プログラミングはセンスです。センスの無い人がプログラマになると、他のすべての人に迷惑がかかります。だから、センスの無い人は絶対にプログラマにならないで下さい。
プログラミングのセンスが無い人や、プログラミングをやったことの無い人は、知識を得たり経験を積んだりすれば、誰でも「良いプログラマ」になれると思っているようですが、無理です。
というのも、センスの無いプログラマの問題は、知識や経験の不足ではないからです。センスの無いプログラマの救いようの無い問題は「頭がおかしいこと」なのです。
題材は何でもいいのですが、具体的なコードを見た方がイメージがつきやすいと思いますので、とりあえず以下の問題を考えます。
住民のリストが与えられるので、背の低い順に男女ペアにしたリストを作って下さい。ただし、男女の数は同数であるとします。
const makePair = (persons) => { const males = persons.filter(person => person.sex === MALE) const females = persons.filter(person => person.sex === FEMALE) const compareHeight = (a, b) => a.height - b.height males.sort(compareHeight) females.sort(compareHeight) return males.map((male, idx) => [male, females[idx]]) // 男女の数は同数 }
この例はJavaScriptなので高階関数を使っていますが、仮にそういう機能が無かったとしても、
一方、センスの無いゴミプログラマは、以下のような名状しがたきコードを書いてきます。
function pair(psns) { var i = -1; var cnt = 0; var flg = psns[0] &amp;&amp; psns[0].sex; var j = -1; var tmp = null; for(i = 0; i < psns.length; i++) { //console.log('■■■■■■■■■■■■■■■■■■■■ BEGIN ■■■■■■■■■■■■■■■■■■■■') //console.log(psns, 'i=' + i, 'cnt=' + cnt, 'flg=' + flg); if(psns[i].sex == flg) { //console.log('cnt: ' + cnt + '->' + (cnt+1)); cnt++; } else { j = i - cnt + 1; //console.log('swap ' + i + '<-->' + j); tmp = psns[j]; psns[j] = psns[i]; psns[i] = tmp; i = j - 1; // <- 理由は分からないが、i = jだと上手くいかない(by XXXX)。 cnt = 0; flg = flg == MALE ? FEMALE : MALE; while(j > 1) { if(psns[j].height < psns[j-2].height) { //console.log('swap ' + j + '<-->' + (j-2)); tmp = psns[j-2]; psns[j-2] = psns[j]; psns[j] = tmp; } j -= 2; } } //console.log(psns, 'i=' + i, 'cnt=' + cnt, 'flg=' + flg); //console.log('■■■■■■■■■■■■■■■■■■■■ END ■■■■■■■■■■■■■■■■■■■■') //console.log('') } for(i = 0; i < psns.length; i++) { //console.log('■■■■■■■■■■■■■■■■■■■■ BEGIN ■■■■■■■■■■■■■■■■■■■■') j = Math.floor(i / 2); //console.log(psns, 'i=' + i, 'j=' + j); tmp = psns[i]; if(!(i % 2)) { psns[j] = [null, null]; } if(tmp.sex == MALE) { psns[j][0] = tmp; psns[j][1] = psns[i+1]; } else { psns[j][0] = psns[i+1]; psns[j][1] = tmp; } i++; //console.log(psns, 'i=' + i, 'j=' + j); //console.log('■■■■■■■■■■■■■■■■■■■■ END ■■■■■■■■■■■■■■■■■■■■') } psns.splice(psns.length / 2, psns.length); }
こんなコードのメンテナンスは御免被りたいです。一見して配列の要素を入れ替えていることが分かるだけで、実装を全て読まなければ(いや読んでも)処理の意図が全く分かりません。また、たとえば「i = j - 1」が間違って「i = j」などと書かれていてバグを起こしたとしても、原因を突き止めるのは困難を極めます。
さて、このコードは具体的に何がいけないのでしょうか。長すぎることがいけないのしょうか。変数名が分かりにくいのがいけないのでしょうか。引数を破壊的に変更しているのがいけないのでしょうか。不要なコメントが残っているのがいけないのでしょうか。よく見ると、ソート処理で車輪の再発明をしていたり、「j」や「tmp」などが場所によって意味が違うカメレオン変数になっていたりしますが、それがいけないのでしょうか。どれも正しいですが、それらを逐一直したところで、本質的な解決にはならないでしょう。
後者のコードはもはや「ここを直したら良くなる」とかいうレベルを超えています。たしかに、問題を具体的に挙げることはできます。このコードの致命的な問題が、凝集度の低さと、単一責任の原則(SRP)違反にあるのは間違いありません。しかし、後者のコードを書いてくる人に、
「住民リストを男女に分ける処理や、リストをソートをする処理、2つのリストをまとめる処理は、この問題とは独立して意味のある操作だから、別の関数として抽出しましょう。その方がコードの見通しがよくなるし、一部の処理を修正したときの影響も小さくなるし、単体テストも書きやすくなります」
なんて言ったって聞く耳を持たないでしょう。
そもそも、こういうコードを書く人は、この処理自体を「pair」なんて関数に抽出すらしません。まだこの問題では入出力のフォーマットが明確に定義されているので、他人が1から書き直せますが、実際のプロダクトでは、無数の副作用を起こす数千行のコードの迷路を彼の脳内フォーマットのデータが通るわけです。もちろん、テストコードなんてありません。
つまり、指摘をしても絶対に直らないのです。いくら言語の優れた機能やベストプラクティスを紹介しても、馬の耳に念仏。それらの利点を理解できるだけの脳みそが足りていないのです。
どうして、同じ処理を実装するのに、ここまでの違いが生じるのでしょうか。
これは、プログラミングの技術の問題ではありません。既に述べた通り、ふつうの人なら、特定の機能の有無とか知識の程度にかかわらず、ふつうのコードを書くのです。なぜなら、ふつうの人にはそちらの方が楽だからです。つまり、前者のコードは別に何か卓越した技術を身につけた結果書けるようになるものではなく、まともな感覚さえ持っていれば、プログラミング初心者にとっても前者のコードの方が書きやすいのです。
つまり、後者のようなコードを書いてくる奴というのは、現実世界の捉え方が常人とは著しくずれているのです。要するに、「頭がおかしい」のです。この病気はもう直りません。だから、センスの無い人は絶対にプログラマにはならないで下さい。
Bluetooth端末で動作する。(CC0 License)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>A10 Cyclone SA easy controller</title> </head> <body> <span id="status">initializing...</span> <script> let status = document.querySelector('span#status'); let device, characteristic; const connect = async _ => { try { device = await navigator.bluetooth.requestDevice({ filters: [{ services: ['40ee1111-63ec-4b7f-8ce7-712efd55b90e'] }], }); status.textContent = 'connecting...'; let server = await device.gatt.connect(); let service = await server.getPrimaryService('40ee1111-63ec-4b7f-8ce7-712efd55b90e'); characteristic = await service.getCharacteristic('40ee2222-63ec-4b7f-8ce7-712efd55b90e'); } catch (e) { status.textContent = `failed to connect: ${e.message}`; return; } document.addEventListener('pointermove', evt => { evt.preventDefault(); let y = evt.y / innerHeight * 2 - 1; let data = Math.abs(y) * 0x7f | (y < 0 ? 0x80 : 0x00); characteristic.writeValue(new Int8Array([0x01, 0x01, data])); }); status.textContent = 'swipe up and down to move'; document.removeEventListener('click', connect); } document.addEventListener('click', connect); status.textContent = 'tap screen to connect'; </script> </body> </html>
例えば以下の文章がメッセージで出力されてた時にエラーの根本原因が即わかる奴っているのかよ…
[ts]
型 '{ inputs: SymbolicTensor; outputs: (SymbolicTensor | Tensor<Rank> | Tensor<Rank> | SymbolicTensor)[]; }' の引数を型 'ContainerArgs' のパラメーターに割り当てることはできません。
型 '(SymbolicTensor | Tensor<Rank> | Tensor<Rank> | SymbolicTensor)' を型 'SymbolicTensor | SymbolicTensor' に割り当てることはできません。
型 '(SymbolicTensor | Tensor<Rank> | Tensor<Rank> | SymbolicTensor)' を型 'SymbolicTensor' に割り当てることはできません。
型 'SymbolicTensor | Tensor<Rank> | Tensor<Rank> | SymbolicTensor' を型 'SymbolicTensor' に割り当てることはできません。
型 'Tensor<Rank>' を型 'SymbolicTensor' に割り当てることはできません。
大きなシステム開発プロジェクトにアサインされて、プログラミングしている。
言語はC++なんだけど、構造体同士を比較するのに、memcmp() 使ってて、みんなもそれを使えっていう。
中身を一個一個比較するより早いけど、構造体には内部にギャップができてるかもしれなくて、なので、
そのギャップの部分だけが違う二つの構造体は、「中身が異なる」と判断されてしまうのよね。
だから、構造体を作って各要素に中身を代入する前に構造体の領域全体を memset() でゼロで塗りつぶしましょう
ってことになってて、毎回それをやるんだけど、塗りつぶし忘れがないかどうか心配だったりする。
構造体メンバとして bool operator==(const T &other) を作るか、あるいは関数として
bool operator==(const T &obj1, const T &obj2) を作って、どちらにしても中身を一個一個比較するべきだとおもうんだよね。
class mystring { public: char *buffer; mystring() { buffer = (char*)""; } void operator = (const char*t) { int len = strlen(t); buffer = new char[len + 47]; strcpy(buffer, t); } void operator = (const mystring&src) { int len = strlen(src.buffer); buffer = new char[len + 47]; strcpy(buffer, src.buffer); } mystring& operator + (const char*t) { int len = strlen(buffer); int len2 = strlen(t); char *buffer2 = new char[len + len2 + 47]; strcpy(buffer2, buffer); strcpy(buffer2+len, t); buffer = buffer2; return *this; } mystring& operator + (const mystring&src) { return ((*this) + src.buffer); } };
class mystringV { public: std::vector<char> buffer; mystringV() { buffer.resize(2); buffer[0] = ' '; buffer[1] = NULL; } void operator = (const char*t) { int len = strlen(t); buffer.resize(len+1); strcpy(&buffer.at(0), t); } void operator = (const mystringV&src) { buffer = src.buffer; } mystringV& operator + (const char*t) { int len = strlen(&buffer.at(0)); int len2 = strlen(t); buffer.resize(len + len2 + 47); strcpy(&buffer.at(0) + len, t); return *this; } mystringV& operator + (const mystringV&src) { return ((*this) + &src.buffer.at(0)); } };
いろんな事をプログラマにかわってライブラリがやってしまうということ
どうなんだろうね。
この辺は あまりしっかり おしえてもらえないところではある。
でも プロならみんな 知っている
class mystring { public: char *buffer; mystring() { buffer = (char*)""; } void operator = (const char*t) { int len = strlen(t); buffer = new char[len + 47]; strcpy(buffer, t); } void operator = (const mystring&src) { int len = strlen(src.buffer); buffer = new char[len + 47]; strcpy(buffer, src.buffer); } mystring& operator + (const char*t) { int len = strlen(buffer); int len2 = strlen(t); char *buffer2 = new char[len + len2 + 47]; strcpy(buffer2, buffer); strcpy(buffer2+len, t); buffer = buffer2; return *this; } mystring& operator + (const mystring&src) { return ((*this) + src.buffer); } };
mystring my_space_org; for (int i = 0; i < 8; i++) { mystring space; space = my_space_org + " "; printf("%sHello world\n", space.buffer); my_space_org = space; }