読者です 読者をやめる 読者になる 読者になる

function call expression #anagol

anarchy golf - Function call expression
問題初投稿。JavaScript風の関数呼び出し式をS式へ変換しろというお題。
例.

in:
f(f(f(f))(f))
out:
(f ((f (f f)) f))

元のアイディアはParens言語Scheme実装より。

普通に文字列置換で解ける事に気付いてなかったので、トップは関数がファーストクラスオブジェクトな言語で80〜100byteくらいになるんじゃないかなーと考えてた所、1日経たない内にPerlの43Bが来たのでビビった。いやしかしこの置換は普通じゃない…
比較的普通なsedの解

:
s/\(\w*\)(\(\w*\))/o\1_\2c/
t
y/o_c/( )/

\Wか\Dが使えればスペースを置き替えなくても済むのだけど残念ながらsedにはないみたいだ。

JSでの想定解は

function g (s) {
  return function (a) {
    return a ? g("("+s+" "+a()+")") : s;
  }
}
var f = g("f");
for (;;) print(eval(readline())());

こんな感じ。これを1位のnnさんと同点の88byteまで縮めたのだけど、nnさんの解は全く内容が違っていて吹いた。C的なコードだけどこんなに短かくなるのか。

JS想定解と同じ内容でpythonも書いてみたのだけど、1位のSvenさんの解はずっと賢かった。
ruby1.9で書くとこんな感じか。

#!ruby -n
class String
  def call(s)
    "(#{self} #{s})"
  end
end
f="f"
puts eval $_.gsub(/\(/,".(")

Pythonは.callとか.(へ変換しなくて良いから短かくなるみたい。

Lisp系は式全体を( )で囲って読んでevalできるよう関数fを定義するか、ParensのScheme実装のような変換をするか。
Arc

(def f r(if r(reduce list `(f,@r))'f))(while:prn:eval:readall:readline)

CommonLisp

(defun f(&rest r)(reduce'list`("f",@r)))(loop(#0=format t"~A
"(eval(read-from-string(#0#/"(~A)"(read-line))))))

Scheme

(while(print((rec'l(fold(^(b a)`(,a,'b))`f(cdr l)))(read-from-string #`"(,(read-line))"))))

Clojure

(while 1(prn((fn r[l](reduce #(list%(r%2))l))(read-string(str\((or(read-line)\;)\))))))

ArcとCLは関数fを定義してeval、evalしようとすると大変なSchemeとevalするとtimeoutになるclojureはリスト変形。
Arcは全体でも1位取れるんじゃ、と思ったけど甘過ぎだった。

あと参加してない所でHaskellとCが読めない。(毎度の事だけど) 解説欲しいなー。

追記

Haskell解説書いてもらえた!
Function call expression 参戦記 - Life Goes On
携帯でHakell書いて一発通過とか何このBPS

Cの解説も
Function call expression & SQR - nn_xの日記
CとHaskellが一緒の方法だったんだなー。面白い。