junk
Up one levelUbuntuにGoをインストールしてみた
アリエルでは最近「最新技術に飛びついて注目されようぜ」というムードがあります。
私としてはもっと古い言語を覚えてみたいんですけどね。
AdaとかLEGOとかForthとかIoとかSmalltalkとかAdaとか。
とはいえ知らない言語を使ってみるのは嫌いじゃないんで、今アリエルで最も熱い言語「Go」をさわってみました。
基本はここにある通りですが、いろいろはまったんで書いておきます。
http://golang.org/doc/install.html
大体この人と同じところで躓きました。なのでほとんどこちらの方のサイトのコピペになってしまいました。
http://d.hatena.ne.jp/kidd-number5/20091111/1257939793
まずMercurialのインストール必要がありますが、Synapticからインストールすると少し古いバージョンのものがインストールされます。
こいつはプロキシ経由でhttpsにアクセスできないバグがあるのでインストールしてはいけません。
アリエルでは外部のネットワークに接続するためにプロキシを使用しているため、ここで苦戦しました。
http://d.hatena.ne.jp/ursm/20080820/1219250897
最新版をインストールするにはソースからビルドするかeasy_installでインストールします。
easy_installをインストールするにはez_setup.pyをダウンロードします。
http://labs.unoh.net/2007/04/python.html
Mercurialのビルドにはpython-develが必要です。
Synapticからpython-all-devをインストールします。
プロキシの設定は~/.hgrcにこんな感じ。
[http_proxy]
host=123.45.67.89:1234
あとPATHを設定するので~/.bash_profileに以下を追加して、
export GOROOT=$HOME/go
export GOOS=linux
export GOARCH=386
export GOBIN=$HOME/go/bin
PATH=$PATH:$GOBIN
読み込ませます。
$ source ~/.bash_profile
全部できたらやっとGoのソースを取得できます。
$ hg clone -r release https://go.googlecode.com/hg/ $GOROOT
取得できたらディレクトリの作成
$ mkdir $GOBIN
あとbisonがないとビルドに失敗するのでインストールします。
ビルド
$ ./all.bash
最後に$GOROOT/misc/emacs/以下にあるelファイルをemacsのパスの通ったところにおいてバイトコンパイルします。
そして.emacsファイルに以下を追記します。
(何言ってんのかわかんねえ、って人はこの辺無視してください。アリエルにはemacsって書くと喜ぶ人が多いんです)
(require 'go-mode-load)
(add-hook 'go-mode-hook
'(lambda()
(setq tab-width 4)
GoのトップページにあるHello Worldをコピペしてこんにちは。
$ ~/go/bin/8g hello.go
$ ~/go/bin/8l hello.8
$ ./8.out
Hello, 世界
試しにGo目並べを作ってみました。
「Go目並べ」言いたかっただけです。
gomoku.zip
package main
import (
"bufio";
"os";
"fmt";
"strconv";
"regexp";
)
const BOARD_LENGTH = 20
const PLAYER1 = "*";
const PLAYER2 = "@";
type Board [BOARD_LENGTH*BOARD_LENGTH]int
func (b *Board) Display() {
fmt.Print(" ");
for i := 0; i < BOARD_LENGTH; i++ {
fmt.Printf("%3d", i);
}
fmt.Println();
for i, n := range *b {
x := i % BOARD_LENGTH;
if x == 0 {
fmt.Printf("%3d", i / BOARD_LENGTH);
}
switch n {
case 1: fmt.Printf(" %s", PLAYER1);
case 2: fmt.Printf(" %s", PLAYER2);
default: fmt.Print(" -");
}
if x == BOARD_LENGTH - 1 {
fmt.Println();
}
}
}
func inRange(n int) bool {
return 0 <= n && n < BOARD_LENGTH;
}
func (b *Board) Put(x, y, n int) bool {
if (!inRange(x) || !inRange(y)) {
fmt.Println("out of index");
return false;
}
index := x + y * BOARD_LENGTH;
if b[index] != 0 {
fmt.Println("already put stone");
return false;
}
b[index] = n;
return true;
}
func (b *Board) IsWinner(putx, puty, putn int) bool {
for i := 0; i < 4; i++ {
var xx, yy int;
switch i {
case 0: xx, yy = -1, -1;
case 1: xx, yy = -1, 0;
case 2: xx, yy = 0, -1;
case 3: xx, yy = -1, 1;
}
x, y := putx, puty;
five := 1;
d := 1;
for {
x += (xx * d);
y += (yy * d);
if inRange(x) && inRange(y) &&
b[x + y * BOARD_LENGTH] == putn {
if five++; five >= 5 {
return true;
}
continue;
}
if d == -1 {
break;
}
x, y = putx, puty;
d = -1;
}
}
return false;
}
func main() {
var stones = []string{" ", PLAYER1, PLAYER2};
turn := 1;
board := new(Board);
board.Display();
fmt.Printf("player%d's(%s) turn\n", turn, stones[turn]);
reXY := regexp.MustCompile(`^ *([0-9]+) +([0-9]+) *\n$`);
in := bufio.NewReader(os.Stdin);
for {
lineBuf, err := in.ReadString('\n');
if err != nil {
fmt.Fprintln(os.Stderr, "ReadLine err:", err);
os.Exit(2);
}
line := string(lineBuf);
if line == "exit\n" {
os.Exit(0);
}
params := reXY.MatchStrings(line);
if len(params) > 0 {
x, _ := strconv.Atoi(params[1]);
y, _ := strconv.Atoi(params[2]);
if board.Put(x, y, turn) {
board.Display();
if board.IsWinner(x, y, turn) {
fmt.Printf("player%d win\n", turn);
os.Exit(0);
}
if turn == 1 { turn = 2; }
else { turn = 1; }
fmt.Printf("player%d's(%s) turn\n", turn, stones[turn]);
}
}
}
}
さわってみた感想は次回書きます。
唐突ですが私の得意言語はDelphi(Object Pascal)です。
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/uchida/ubuntu306bgo309230a430f330b930c830fc30eb30573066307f305f/tbping
関数内関数欲しいな
(Goを)さわってみた感想は次回書きます。Pascalが好きではない人に何か言ってやろうと思ってたんですが、勝てそうにないんで代わりに以前書いたDelphiのプログラムを貼ってお茶を濁すことにしました。
唐突ですが私の得意言語はDelphi(Object Pascal)です。
Goで好きになれそうにないところは関数内関数がないあたりです。
とりあえずコード書いて、似たようなコードやレイヤーが違うコードを関数内関数で括り出しといて、汎用的に使えそうならグローバルやprivateな関数にする、というプロセスは慣れるとなかなかいいものです。
Lispもlabelsを使うCommon Lispより普通に関数が書けるSchemeの方が好きです。
ちなみにGoの
var f := func() {
fmt.Printf("closure %c", a[0]);
};
を関数内関数と呼ぶには抵抗があります。最適化と慣れの問題かもしれませんが。
関数内関数を作れるとその関数ポインタをどうするのか、という問題が発生します。
Delphiでは関数内関数のポインタをとれないことにして問題を解決しています。
正確に言うとこんな感じだったはず(未テスト)。
// 普通の関数を変数に入れるのはOK
procedure Hoge;
begin
Writeln('hello');
end;
type
TProc = procedure;
var
hoge: TProc;
begin
hoge := Hoge;
end.
// 関数内関数を変数に入れるのはコンパイルエラー
procedure Test;
procedure Hoge;
begin
Writeln('hello');
end;
var
hoge: TProc;
begin
hoge := Hoge; // コンパイルエラー
end;
// これはOK、ただしHoge内でTestのローカル変数を触ると実行時エラー
procedure Test;
procedure Hoge;
begin
Writeln('hello');
end;
var
hoge: TProc;
begin
hoge := @Hoge;
end;
しかしytqwerty氏の発明した関数内関数渡しの方法を使うと親関数のローカル変数を触れるようになります。
正確に理解できてはいないのですが、関数内関数を呼ぶ時のスタックのポインタを連れ回してCallする前に書き換えてしまう技のようです。
これをつかってprototype.jsのEnumerable的なものをDelphiで作成してみたのがこれです。
enumerable.zip
IEnumerableを実装するとEnumerableをmixinしたのと似たようなことになります。
Javaな人は「interfaceを実装することがなんでmixinなんだ?」と思われるかもしれませんが、Delphiには「委任」という便利な機能があるのです。
(この辺の「Delphiのinterfaceは使えない」という世間の認識に対してもそのうち何か言いたい)
まあ作ってみたはいいものの実用には使わないと思います。
ちなみに最近のDelphiだと無名関数が使えるらしいです。
やっぱり単なる慣れの問題なのかなあ?
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/uchida/95a26570518595a265706b3230573044306a/tbping
Adaで超いい加減HTTPサーバ
Adaのタスクはもっと評価されいい、のかな?
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Maps; use Ada.Strings.Maps;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Streams;
with Ada.Streams.Stream_IO;
with GNAT.Sockets;
with Ada.Integer_Text_IO;
use Ada.Integer_Text_IO;
procedure Run_Server is
package GS renames GNAT.Sockets;
CRLF: constant String := ASCII.CR & ASCII.LF;
task type HTTP_Request is
entry Process(Client_Socket: in GS.Socket_Type);
end;
task body HTTP_Request is
Client: GS.Socket_Type;
Connection: GS.Stream_Access;
function Read return String is
Request_Error: exception;
Offset: Ada.Streams.Stream_Element_Count;
Buffer: Ada.Streams.Stream_Element_Array(1..1024);
Result: Unbounded_String := To_Unbounded_String("");
begin
loop
GS.Receive_Socket(Client, Buffer, Offset);
if Natural(Offset) = 0 then
Put_Line("EOF");
raise Request_Error;
end if;
for i in 1..Offset loop
Result := Result & Character'Val(Buffer(i));
end loop;
exit when Tail(Result, 4) = CRLF & CRLF;
end loop;
return To_String(Result);
end;
function Parse_URL(Headers: String) return String is
first: Positive;
last: Natural;
begin
Find_Token(Headers, To_Set(" "), Ada.Strings.Outside, first, last);
Find_Token(Headers(last+1..Headers'Last), To_Set(" "), Ada.Strings.Outside, first, last);
declare
Url: String := Headers(first+1..last);
begin
if Url = "" or else Url(Url'Last) = '/' then
Url := Url & "index.html";
end if;
return Url;
end;
end;
procedure Write(Url: String) is
package ASS_IO renames Ada.Streams.Stream_IO;
File: ASS_IO.File_Type;
begin
ASS_IO.Open(File, ASS_IO.In_File, Url);
declare
File_Stream: ASS_IO.Stream_Access;
Offset: Ada.Streams.Stream_Element_Count;
File_Buffer: Ada.Streams.Stream_Element_Array(1..1024);
begin
String'Write(Connection, "HTTP/1.0 200 OK" & CRLF & CRLF);
File_Stream := ASS_IO.Stream(File);
loop
Ada.Streams.Read(File_Stream.all, File_Buffer, Offset);
exit when Natural(Offset) = 0;
Connection.Write(File_Buffer(1..Offset));
end loop;
ASS_IO.Close(File);
exception
when others => ASS_IO.Close(File);
end;
Put_Line("done");
end;
begin
accept Process(Client_Socket: in GS.Socket_Type) do
Client := Client_Socket;
end Process;
Connection := GS.Stream(Client);
declare
Headers: String := Read;
Url: String := Parse_URL(Headers);
begin
Write(Url);
end;
GS.Close_Socket(Client);
exception
when others =>
GS.Close_Socket(Client);
end;
type HTTP_Request_Access is access HTTP_Request;
Server: GS.Socket_Type;
Server_Address: GS.Sock_Addr_Type;
Client: GS.Socket_Type;
Client_Address: GS.Sock_Addr_Type;
begin
GS.Initialize;
GS.Create_Socket(Server);
Server_Address.Addr := GS.Inet_Addr("127.0.0.1");
Server_Address.Port := 1972;
GS.Bind_Socket(Server, Server_Address);
GS.Listen_Socket(Server);
loop
GS.Accept_Socket(Server, Client, Client_Address);
Put_Line("Request came");
declare
req: HTTP_Request_Access := new HTTP_Request;
begin
req.Process(Client);
end;
end loop;
end;
Goのgoroutine、Adaのタスクと来たら次はScalaのアクターで書くとどうなるのか、是非見てみたいですね。
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/uchida/ada8d853044304452a06e1bhttp30b530fc/tbping
logoでハローワールド
to hello.Next
PenUp
setheading 90
Forward 50
end
to hello.DrawHa
setheading 90
PenUp
Forward 20
Right 120
PenDown
Forward 40
PenUp
Back 40
Left 120
Forward 10
Right 60
PenDown
Forward 40
PenUp
Back 40
Left 60
Back 30
end
to hello.DrawRo
setheading 90
Forward 5
PenDown
repeat 4 [
Forward 40
Right 90
]
PenUp
Back 5
end
to hello.DrawHyphen
setheading 180
Forward 20
Left 90
Forward 5
PenDown
Forward 40
PenUp
Back 45
Right 90
Back 20
end
to hello.DrawWa
setheading 135
Forward 5
Right 45
PenDown
Forward 10
PenUp
Back 10
PenDown
Left 90
Forward 40
PenUp
Back 40
PenDown
arc 90 40
PenUp
Left 135
Forward 5
end
to hello.DrawRu
setheading 90
Forward 20
Right 90
PenDown
Forward 35
PenUp
Right 90
Forward 10
Right 180
PenDown
arc 90 10
PenUp
Forward 10
Left 90
Forward 35
Right 90
Forward 15
Right 90
PenDown
Forward 45
Left 135
Forward 30
PenUp
Back 30
Right 135
Back 45
Left 90
Back 35
end
to hello.DrawDo
setheading 90
Forward 25
Right 90
PenDown
Forward 45
PenUp
Back 25
Left 60
PenDown
Forward 20
PenUp
Back 20
Right 60
Back 20
Left 90
repeat 2 [
Forward 10
Right 45
PenDown
Forward 5
PenUp
Back 5
Left 45
]
Back 45
end
setPenSize 5
HideTurtle ClearScreen Window FullScreen
hello.DrawHa
hello.Next
hello.DrawRo
hello.Next
hello.DrawHyphen
hello.Next
hello.DrawWa
hello.Next
hello.DrawHyphen
hello.Next
hello.DrawRu
hello.Next
hello.DrawDo
たかがハロワの癖に可読性が悪すぎます。
- Category(s)
- junk
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/uchida/logo30cf30ed30fc30ef30fc30eb/tbping
S式は時代遅れ
http://dev.ariel-networks.com/Members/inoue/lisp-seminar
これからは関数型言語grassです。
warota.grass
wwWWwWWWwWWWWw v
wwWWWwwWwwWWwWWWwWWWWwWWWWWWWwWWWWWWWWw v
wwWWWwwWwwWWwWWWwWWWWwWWWWWwWWWWWWwWWWWWWWwWWWWWWWWwWWWWWWWWWwWWWWWWWWWWwWWWWWWWWWWWwWWWWWWWWWWWWwWWWWWWWWWWWWWwWWWWWWWWWWWWWWwWWWWWWWWWWWWWWWwWWWWWWWWWWWWWWWWwWWWWWWWWWWWWWWWWWWWWWwwwwwwwwwwwwwwwwwwwWwwWWwWWWwWWWWWWWWWWWWWWWWWWWWWWWw v
wwWWwWWWw v
WWWWWwwwwwww
WWWwwwwwwwWwwWWWWWWWWw
WWWWWWWwwwwwwwwwwWwwWWWWWWWWWWwwwwwwwwwwwwWwwWWWWWWWWWWWWWwWWWWWWWWWWWWWWwwww
WWWWWWWWWWWwwwwwwwwwwwwwwwwWwwwWWWWWWWWWWWWWWWWWw
WWWWWWWWWWWWWWWWWWwwwwwwwwww
$ .grass warota.grass
warota
以前私の作ったgrass実装はマルチバイト文字を全く考慮していないため、使う場合は全角を半角に変換するか消してください。
- Category(s)
- junk
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/uchida/s5f0f306f66424ee39045308c/tbping