Hatena::ブログ(Diary)

かきにっき

2015-10-17

[]Petite Chez Schemeインストール

Chez Scheme Version 8.4

tar -xzvf pcsv8.4-ti3osx.tar.gz
cd csv8.4/costom
./configure --installprefix=~/local --installman=~/local/share/man
make
make install

すると petite と scheme-scriptインストールされる。root権限にchownしようとしたりしていろいろエラーが出るがとりあえず無視する。すると、

$ petite
cannot find compatible petite.boot in search path
  "/Users/kaki/lib/csv%v/%m:/usr/lib/csv%v/%m:/usr/local/lib/csv%v/%m"

と言われる。bootパスが間違っているので

petite -b ~/local/lib/csv8.4/ta6osx/petite.boot

で起動できる。そこで

cd ~/local/bin
mv petite petite8.4

petite

#!/bin/sh
exec petite8.4 -b ~/local/lib/csv8.4/ti3osx/petite.boot "$@"

petite-script

#!/bin/sh
exec petite8.4 -b ~/local/lib/csv8.4/ti3osx/scheme-script.boot --script "$@"

としてみた。scheme-script いらなさそうだけどとりあえず保留。

2015-10-12

[]><>(Fish)に入門した

あらすじ

><>という難解プログラミング言語某ゴルフ場に入ったので、入門した。言語の名前上、ググラビリティが非常に低く日本語の情報が見当たらなかったので、ここに日本語で自分の><>入門への道中を記す。あくまで初心者が調べながら書いた文章なので、間違いが多分に含まれている可能性がある。間違いを見付けたら教えてほしい。


(この文章は、Befunger視点で書かれている。前提知識として、(某ゴルフ場の多少カスタマイズされた)Befungeの理解を要求するかもしれない。)

続きを読む

2015-10-08

[]任意の型の引数を無限に消費する空腹関数Haskell(GHC)では書けないのか?

Schemeでいうと

(define (hungry x) hungry)

みたいなやつ。

ここまではできた。参考: https://github.com/jstolarek/sandbox/blob/master/haskell/Hungry.hs

Prelude> :set -XRankNTypes
Prelude> data Hungry = Hungry { (%) :: forall b. b -> Hungry }
Prelude> let fix f = f $ fix f
Prelude> let hungry = fix id :: Hungry
Prelude> :t hungry % 42 % 'c' % []
hungry % 42 % 'c' % [] :: Hungry

unHungry (上では (%)) 無しでは書けないのかなあ。


(追記 18:38)

できた、のか?

参考:可変長引数をHaskellで。 - ここにタイトルを入力|

Prelude> class Hungry f where hungry :: a -> f
Prelude> instance Hungry a => Hungry (f -> a) where hungry _ = hungry
Prelude> :t hungry 42 'c' []
hungry 42 'c' [] :: Hungry t => t

型クラスにするとそれっぽいものが何故かできた。何故だ?

2015-06-08

[][][][][][]はじめてのQuineリレー

概要

昨日、自分自身を出力するHaskellプログラムを生成するOCamlプログラムを生成するSchemeプログラムを生成するRubyプログラムを生成するJavaScriptプログラムを生成するCプログラムを書いた。

#include<stdio.h>
int main(){char*g="var p=print;p('puts %%^(format #t!Printf.printf~s~s!(x->string`main=putStr%%S)^.tr *?!...?#;p <<_;$><<?)');p('#include<stdio.h>');print(%cint main(){char*g=%c%s%c;printf(g,47,34,g,34,47);}%c.source);p('_')";printf(g,47,34,g,34,47);}

以下のように動作する。Makefileは後述。

$ make diff
clang -std=c99 -Wall -W -Werror -pedantic -o quine-relay-c start.c && ./quine-relay-c > quine-relay.js
v8 --use_strict quine-relay.js > quine-relay.rb
ruby quine-relay.rb > quine-relay.scm
gosh quine-relay.scm > quine-relay.ml
ocaml quine-relay.ml > quine-relay.hs
runghc quine-relay.hs > goal.c
diff -u start.c goal.c
$ wc start.c quine-relay.*
       2       9     270 start.c
       0       8     287 quine-relay.hs
       0      13     402 quine-relay.js
       0       8     304 quine-relay.ml
       4      15     360 quine-relay.rb
       2      11     333 quine-relay.scm
       8      64    1956 total

動機

SchemeRubyが得意でHaskellOCamlも書けます!」と堂々と言えるようになりたい。ならばそれらの言語でQuineリレーをしよう。思い付いてしまったからには、書かねばなるまい。そう思っていた時期もあった。

かのように決心して書き始めたのだが、存外に難しくはなく、その日のうちにできてしまった。

構想

コンセプト。Quineリレー自体は偉大なる先人が凄いのを成し遂げていらっしゃるし、自分はQuineリレーには初挑戦なので、今回は得意言語のアッピルに重点を置いて、とりあえず高級言語数個での完成を目指すことにした。次に順序が問題となる。Brainf**kやBefungeを入れるでもないのに順序が任意では趣に欠けるというもの。これはなんとなくCを起点にして触った順にした。結果、自分のプログラミングの学びの歴史を辿り最後は初心に帰るという個人的に気持ち悪い大層趣のあるプログラムができあがった。あと、今回の主旨に鑑みて、特定の言語で何重にもエスケープして残りの言語は文字列を出力するだけ、みたいなヒキョウなことはなるべくしないようにした。

もう一つ、追加の制約としてCコンパイラオプション-std=c99 -Wall -W -Werror -pedantic を付けることにした。これでこのプログラムコンパイラも黙る程の真っ当なプログラムであることは確定的に明らか。奇妙な挙動や拡張に依存していたら、コンパイラによってバラバラに引き裂かれることになる。

ついでにちょっと縮めた。

感想

付録

Makefile

.PHONY: all clean diff
CC = clang
CFLAGS = -std=c99 -Wall -W -Werror -pedantic
JavaScript = v8 --use_strict
Ruby = ruby
Scheme = gosh
OCaml = ocaml
Haskell = runghc

DIFF = diff -u

START = start.c
GOAL = goal.c
Q = quine-relay
C_EXE = $(Q)-c

all: $(GOAL)

diff: all
	$(DIFF) $(START) $(GOAL)

$(Q).js: $(START)
	$(CC) $(CFLAGS) -o $(C_EXE) $< && ./$(C_EXE) > $@

$(Q).rb: $(Q).js
	$(JavaScript) $< > $@

$(Q).scm: $(Q).rb
	$(Ruby) $< > $@

$(Q).ml: $(Q).scm
	$(Scheme) $< > $@

$(Q).hs: $(Q).ml
	$(OCaml) $< > $@

$(GOAL): $(Q).hs
	$(Haskell) $< > $@

clean:
	rm -f $(GOAL) $(C_EXE) $(Q).js $(Q).rb $(Q).scm $(Q).ml $(Q).hs

あと各処理系のバージョン。Gaucheは開発版の何か。

$ clang -v
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
$ echo -n | v8
V8 version 3.25.30 [sample shell]
>
$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin13]
$ gosh -V
Gauche scheme shell, version 0.9.5_pre1 [utf-8,pthreads], x86_64-apple-darwin13.4.0
$ ocaml -version
The OCaml toplevel, version 4.02.0
$ ghc -V
The Glorious Glasgow Haskell Compilation System, version 7.8.3

2015-06-05

[]enum型からその中の型へのキャスト

enum型からその中の型へのキャストする underlying_cast を書いた。

#include <cinttypes>
#include <type_traits>
#include <array>
#include <cstdio>

template <class E>
constexpr typename std::underlying_type<E>::type
underlying_cast(E e) noexcept {
  return static_cast<typename std::underlying_type<E>::type>(e);
}

enum class Ki : std::uint8_t {
  momo = 3,
  kuri = 3,
  kaki = 8
};

template <class T>
void p(T n) {
  std::puts("something");
}

template <>
void p(std::uint8_t n) {
  std::printf("uint8_t %" PRIu8 "\n", n);
}

int main() {
  p(underlying_cast(Ki::kaki));
  std::array<int, underlying_cast(Ki::kaki)> a{};
  return 0;
}

$ clang++ -std=c++11 -o underlying_cast underlying_cast.cpp 
$ ./underlying_cast 
uint8_t 8

やったぜ。