(ruby) rubyでは ifやcaseは if文 case文 ではなく if式 case式 である

rubyに関する記事一覧→ rubyのまとめ



だいたいの言語って ifって文ですよね?、でもrubyでは ifも式なんです、caseも式なんです


if式ってなんやねん!?
って感じですが、まぁ論より証拠

puts(
	if true then
		100
	end
)

を実行すると 100 と表示されます
つまり trueだった場合その中の処理が実行され
一番最後の処理の戻り値が if式の結果 として返ってくるのです


もちろん、else や elsif が加わった場合も同じです

puts(
	if false then
		100
	else
		200
	end
)

これなら 200になります


caseも同じく

val = 2
puts(
	case val
	when 1
		'a'
	when 2
		'b'
	when 3
		'c'
	else
		'z'
	end
)

val に 2 がセットされているので表示されるのは b になります


今回、if式とcase式を紹介しましたが、実は他にもrubyの制御構造は戻り値を持つものが多いのです

puts(
	(100 if true)
)

100 が表示される

puts(
	(false ? 100 : 200)
)

200 が表示される


puts(
        unless false
                100
        end
)

100 が表示される

c = 0
puts(
	while
		c += 1
		break(c) if (c > 10)
	end
)

11 が表示される



など、他にもまだまだ有ります、もし興味を持ったのなら
もっと詳しい内容 Rubyリファレンスマニュアル → 制御構造 を参照してください

(ruby) 後置if式で実行内容を複数個書きたい場合

rubyに関する記事一覧→ rubyのまとめ



rubyには 先に実行内容を書いて、その後に if を挟んで 条件式を書く書き方があります
if修飾子 とか 後置if って言われているやつですね

puts('hello') if true

便宜上 trueと書いてますが、この部分に条件式を書くわけですね
この例では条件式は true なので puts('hello')が実行されます


ただし実行されるのは ifの左隣の一つだけです
複数個の処理を対象としようとして

puts('hello'); puts('world') if false

と書き 条件式がfalseの場合なら「hello」も「world」も表示されない のを期待しても
思ったような動作はせず
「hello」は true false に関わらず表示されてしまいます。
つまり ;を使ってワンライナーで書いたとしても
puts('hello') の方は 後置ifには掛かっていないという事ですね


こういった場合には この二つの処理を () で括って纏めてしまえば
二つとも 後置if に掛ける事が出来ます

(puts('hello'); puts('world')) if false


複数行に渡って処理を書く必要がある時は 普通のif式を使った方が良いとは思いますが
後置if でも複数行に渡る処理を書く事は不可能ではありません

(
	puts('hello')
	puts('world')
	exit()
) if true
sleep(100)

この例では3行とも実行されますので sleep以前に exitで実行が終了されます


少し実用的な書き方をすると

(puts('コマンドラインオプションで入力ファイル名を指定してください'); exit(0)) if (ARGV[0] == nil)

こういう感じになりますかね

(ruby)(python3)(node.js)(c++)(c#)(java) いろんな言語の超基本的なクラス定義を書き並べてみる

rubyに関する記事一覧→ rubyのまとめ
node.jsに関する記事一覧→ node.jsのまとめ



クラス定義っていろんな言語使ってるとなんかごっちゃになってしまいますよね
そこで、各言語の超基本的なクラス定義を書き並べて比較してみることにしました
全てやっていることは同じで、Nekoクラスを定義して 名前を「ミケ」にセットして、挨拶をさせています


c++

#include <iostream>
#include <stdio.h> //printf用
class Neko
{
	private:
		std::string name;
	public:
		Neko(std::string new_name)
		{
			name = new_name;
		};
		void hello()
		{
			std::cout << "吾輩は " << name << " である" << std::endl; // c++的にはこちらの方が一般的?
			printf("吾輩は %s である", name.c_str()); // prinfで出力する場合は c_strでchar*に変換する
		};
};
int main(int argc, char* argv[])
{
	Neko mike = Neko("ミケ");
	mike.hello();
};


node.js

#!/usr/local/bin/node
class Neko{
	constructor(new_name){
		this.name = new_name;
	};
	hello(){
		console.log('吾輩は '+ this.name + ' である');
	};
};
const mike = new Neko('ミケ');
mike.hello();


ruby

#!/usr/local/bin/ruby -Ku
class Neko
	def initialize(new_name)
		@name = new_name
	end
	def hello()
		puts('吾輩は ' << @name << ' である')
	end
end
mike = Neko.new('ミケ')
mike.hello()


python3

#!/usr/bin/python3
class Neko:
	def __init__(self, new_name):
		self.name = new_name
	def hello(self):
		print("吾輩は " + self.name + " である")
mike = Neko("ミケ")
mike.hello()


C#

namespace NekoApp
{
	class Neko
	{
		private string name;
		public Neko(string new_name)
		{
			name = new_name;
		}
		public void hello()
		{
			System.Console.WriteLine("吾輩は " + name + " である");
		}
	}
	class NekoMain
	{
		static void Main()
		{
			Neko mike = new Neko("ミケ");
			mike.hello();
		}
	}
}


java

class Neko{
	private String name;
	public Neko(String new_name){
		name = new_name;
	};
	public void hello(){
		System.out.println("吾輩は " + name + " である");
	};
};
public class ClassTest{
	public static void main(String[] args){
		Neko mike = new Neko("ミケ");
		mike.hello();
	};
};

(node.js)(javascript) インスタンスのクラス名を調べたい

node.jsに関する記事一覧→ node.jsのまとめ



インスタンスのクラスを調べようとして typeof を使っても objectとしか返ってこない時があって困る事がありますが
きちんとクラス名を調べたい時は Object.prototype.toString を使います

#!/usr/local/bin/node

const puts = console.log;
const classname = Object.prototype.toString;
puts(classname.call({a: 1024, b: 2048}));
puts(classname.call(undefined));
puts(classname.call(1));
puts(classname.call(Infinity));
puts(classname.call(null));
puts(classname.call(true));
puts(classname.call([1,2,3]));
puts(classname.call("hello"));
puts(classname.call(new RegExp()));
puts(classname.call(()=>{}));

のようにします
今回の例だと

[object Object]
[object Undefined]
[object Number]
[object Number]
[object Null]
[object Boolean]
[object Array]
[object String]
[object RegExp]
[object Function]

という結果が得られます


いちいち call するのが億劫だという場合は

#!/usr/local/bin/node

const puts = console.log;
const classname = (obj)=>{return Object.prototype.toString.call(obj)};
puts(classname(new RegExp()));

みたいにすればいいですね

(WSL) Windows側のPATHを取り込まないようにする

WSLは デフォルトだとWindows側の環境変数のPATHを取り込んでしまいます
それが好ましくないと思う場合はレジストリを変更することでLinux環境だけのパスにすることが可能です


Windows側のPATH取り込み無効化のレジストリファイル

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LxssManager]
"DistributionFlags"=dword:fffffffd

このレジストリファイルを実行するか
直接レジストリエディタで DistributionFlags を追加してください
元に戻したい場合は DistributionFlags を削除してください