色々な言語で偶数自乗和

TL;DR

このごろ新しく言語を見る時、Hello world の次くらいに偶数自乗和を 作る関数を定義してる。Ruby で書くとこんな感じ。

def even_square_sum(n)
    (1..n)
        .select {|n| n % 2 == 0} 
        .map {|n| n * n} 
        .inject {|acc, n| n + acc}
end
puts(even_square_sum(10)) # => 220 が表示されると正解

いくつかルールがあって

  • リストの内包表記は使わない
  • range 的なのがあれば使う
  • 最後の合計はなるべく畳み込み(reduce, fold系) を使う

これをやると

  • 無名関数の定義のしかた
  • 関数の定義のしかた
  • 関数の呼び出しかた
  • 基本的な高階関数の使い方

が分かるので、なかなか気にいってる。 では今まで作ったのを紹介してみる。

Rust

fn even_square_sum(n: isize) -> isize {
    (1..n)
        .filter(|n| n % 2 == 0)
        .map(|n| n * n)
        .fold(0, |acc, x| acc + x)
}

fn main() {
    let result = even_square_sum(10);
    println!("{}", result);
}

普通かな。 でもこの書き方をゼロコストでやってくれるのはいいね。

Common Lisp

(defun range (from to &optional (res '()))
    (if (eq from to) (cons to res)
        (range from (1- to) (cons to res))))

(defun even-square-sum (n)
    (reduce #'+
        (mapcar #'(lambda (n) (* n n))
            (remove-if-not #'evenp (range 1 n)))))

(setq result (even-square-sum 10))
(print result)

range がなかったので自作してみた。末尾再帰ではないので、ヒマがあったら変えたい。 適用する順番が頭で考えるのと逆順になってしまうので読みづらい。 マクロ作ればパイプライン的な事もやれそうだけど。

TypeScript

function evenSquareSum(n: number): number {
    const numList: number[] = Array.from(Array(n).keys());
    return numList
        .filter((n) => n % 2 == 0)
        .map((n) => n * n)
        .reduce((acc, n) => acc + n);
}
const result = evenSquareSum(10)
console.log(result);

普通かな。range がないので、Array.from() を使ったけどやはり気持ち悪い。

Elixir

evenSquareSum = fn (n) ->
    (1..n)
        |> Enum.filter(fn n -> rem(n, 2) == 0 end)
        |> Enum.map(fn x -> n * n end)
        |> Enum.reduce(0, fn n, acc -> n + acc end)
end
result = evenSquareSum(10)
IO.puts(result)

パイプライン演算子(|>)いいね。 リスト操作以外にも使えそうだし、 もっと他の言語にも取り入れてもらいたい。

import Enum
1..10 |> filter(&rem(&1, 2) == 0) |> map(&(&1 * &1)) |> reduce(&(&1 + &2))  

git rebase -i をちょっと楽にするエイリアス

いつもいつも git rebase -i HEAD^^ を打つのが めんどくさいので作ってみました。

使用例

  • git irebase
    • → git rebase -i HEAD~2
  • git irebase 5
    • → git rebase -i HEAD~5
    • 数字をつけるとその数さかのぼる
  • git irebase ^^^
    • → git rebase -i HEAD^^^
    • ^ や ~ だけの場合、 HEAD からさかのぼる
  • git irebase 2 develop
    • →git rebase -i HEAD~2 develop
    • ブランチ指定も可

詳しくはソースを参照の事。 以下を git-irebase として PATH の通ったディレクトリに置いて使います。 https://github.com/yosugi/git-irebase にも上げておいたので、 お好きな方をどうぞ。

#!/usr/bin/env perl
use strict;
use warnings;

sub main {
    my ($upstream, $branch) = @_;

    $upstream = 2 unless ($upstream);
    $branch = "" unless ($branch);

    if ($upstream =~ /^[0-9]+$/) {
        $upstream = "HEAD~$upstream";
    } elsif ($upstream =~ /^[0-9^~]+$/) {
        $upstream = "HEAD$upstream";
    }

    exec "git rebase -i $upstream $branch";
}

main(@ARGV);

__END__

=head1 NAME

git-irebase - alias for git rebase -i

=head1 SYNOPSIS

  $ git irebase [<upstream>] [<branch>]

=head1 DESCRIPTION

  $ git clone https://github.com/yosugi/git-irebase.git
  $ export PATH=./git-irebase:$PATH
  $ git irebase

=head1 AUTHOR

yosugi

=head1 LICENSE

MIT license (http://opensource.org/licenses/mit-license.php)

=cut

github のリポジトリ構造は https://github.com/kyanny/git-copy を参考にさせて もらいました。感謝です。

MODx の管理画面ツールバーにボタンを追加する

MODx の管理画面をカスタマイズした時のメモです。 最後の doLayout() が分からなくてハマったので注意。

MODx.on('ready', function() {

    var buttons = [];
    buttons.push({
        text: 'hello',
        handler: function () {
            alert('hello'); // 実行させたい処理をここに書く
        }
    });

    var toolBar = Ext.getCmp('modx-action-buttons');

    // この toolBar は Ext.Toolbar クラスなので対応するメソッドが使えます。
    // http://extdocs.xenophy.com/?class=Ext.Toolbar

    toolBar.addButton(buttons); // 最後に追加
    // toolBar.insertButton(3, buttons); // 3 番目に追加

    toolBar.doLayout(); // 描画し直す
}

vim のインサートモードで行頭をトグルする

vim を使ってて、emacs みたいに C-a で行頭と空白以外の最初の文字を トグルしたかったので作ってみました。

function! ToggleBol()
    let col = virtcol('.')
    let cmd = (col == 1) ? '^' : '0'
    execute "normal! " . cmd
endfunction
inoremap <C-a> <C-o>:call ToggleBol()<CR>

コメントアウトする時とかに便利かも。

追記

Qiitaのコメント で教えてもらったやり方のがよさそうなので、こっちにも書いときます。

inoremap <expr> <C-a>
      \ search('^\s\s*\%#', 'bcn') ? "\<C-o>0" : "\<C-o>^"

search とか初めて知ったよ。

ubuntu に samba を入れる

もう少し簡単にファイル共有できないかと思い、 ubuntu に samba を入れてみました。

いつも通り、 apt-get を使います

$ sudo apt-get install samba

共有するディレクトリを作成し、 だれでも読み書きできるようにオーナー、権限を設定します。

$ sudo mkdir /var/samba
$ sudo chown nobody:nogroup /var/samba
$ sudo chmod 777 /var/samba

/etc/samba/smb.conf をエディタで開いて設定します。

[global]
workgroup = WORKGROUP

dos charset = CP932      # Windows 側の文字コード
unix charset = UTF-8     # Linux 側の文字コード

map to guest = Bad User  # Linux に存在しないユーザーでのアクセスはゲストとして扱う

[share]
path = /var/samba           # さっき作ったディレクトリ
writeable = yes             # 書き込み許可
force create mode = 0666    # ファイルを作った時の権限
force directory mode = 0777 # ディレクトリを作った時の権限
guest ok = yes              # ゲストアクセスを許可
guest only = yes

設定したら再帰動します。

sudo service smbd restart

これで接続できました。

ubuntu に Symfony2 をインストール

Symfony2 を ubuntu にインストールした時のメモ

まず、 Symfony を落としてきて展開

mkdir ~/temp
cd ~/temp
wget http://get.symfony.com/Symfony_Standard_Vendors_2.3.1.tgz
tar -zxvf Symfony_Standard_Vendors_2.3.1.tgz
sudo mv Symfony /var/www

http://hostname/symfony/web/app_dev.php にアクセス。 以下のエラーが出たので、 app_dev.php を修正します。

You are not allowed to access this file. Check app_dev.php for more information.

sudo vim /var/www/Symfony/web/app_dev.php

app_dev.php はローカルからのみ接続できるようになっています。 今回は開発用に他マシンからも接続するので、 以下の行をコメントアウトします。

 # if (isset($_SERVER['HTTP_CLIENT_IP'])
 #    || isset($_SERVER['HTTP_X_FORWARDED_FOR'])
 #    || !in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1'))
 # ) {
 #    header('HTTP/1.0 403 Forbidden');
 #    exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
 # }

再びブラウザからhttp://hostname/symfony/web/app_dev.php にアクセス

RuntimeException: Unable to create the cache directory (/var/www/Symfony/app/cache/dev)

エラーが出たので権限を変更します

chmod 777 /var/www/Symfony/app/cache

さらにブラウザでチェックすると エラーが出たので権限を変更します。 UnexpectedValueException: The stream or file "/var/www/Symfony/app/logs/dev.log

chmod 777 /var/www/Symfony/app/logs

これで正しく表示できるようになりました。