ArcでGolf

もう半月以上経ってるけど祝Arc追加

色々書いてみて気付いた点とか適当に。

special syntax charactors (intrasymbol)

2以前はa.b.c => (a b c), a!b!c => (a 'b 'c)だったけどver 3でa.b.c => ((a b) c), a!b!c => ((a 'b) 'c)に変更。
++.iが意図通りに展開されないという問題があるけど、forumで公開されているver 3.1ではandfの+が&に変更されて解決している。
まあしかしこれ大概便利。

echo

(while:prt:readc)

;; 無理矢理+を使ってみる
(while:idfn+pr:readc)  ; == (while ((andf idfn pr) (readc)))

murky-satyrさんのtime outの解答

while!?

☆ボタンがあったら連打したい所

n-of (n expr)

カウンタの要らない単純なループに使えるんだけど (sig 'n-of) は (n . body) じゃなくて (n expr) なので、繰返したい式が2つ以上の場合はdoで囲む、よりはrepeatを使う。
けど自分の書いた範囲ではrepeatの出番全くなかったな。

drain (expr (o eof nil))

eofを返すまでexprを評価し、結果をリストにして返すという便利マクロ。色んな場面で使える。

(def f (n) (if even.n (/ n 2) (+ (* n 3) 1)))

(let i 19 (drain (zap f i) 1))
; (58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2)

でもeofはfindやposみたく関数も指定できるようにしてくれるともっと便利かなーとか思った。

(mac drain2 (expr (o eof nil))
  (w/uniq (gacc gdone gres geof)
    `(with (,gacc nil ,gdone nil ,geof (testify ,eof))
       (while (no ,gdone)
         (let ,gres ,expr
           (if (,geof ,gres)
               (= ,gdone t)
               (push ,gres ,gacc))))
       (rev ,gacc))))

(let i 27 (drain2 (zap f i) [or (is _ 1) (< 1000 _)]))
; (82 41 124 62 31 94 47 142 71 214 107 322 161 484 242 121 364 182 91 274 137 412 206 103 310 155 466 233 700 350 175 526 263 790 395)

zap op place [args ...]

解説。これが使える形に式変形できると楽しい。
eの小数点アリ版

(for i(= e 1 d 1)70(++ e(/:zap * d i)))(pr:num e 100)

小数点ナシの方はさっぱりわからん。

accum accfn [body ...]

字数コスト高いかなーと思ったけどこれ書こうとしたらaccumより短かく書ける方法が思い付かなかった。

(pr:most[if(iso(= s(coerce(+""_)'cons))(rev s))_ 0](accum a(for x 100 999(for y x 999(a:* x y)))))

revで文字列の反転ができなかったりと色々残念な事に。

readとか

(w/instring ins "1,2,3" (rem'unquote(flat:readall ins)))
; (1 2 3)

(w/instring ins "1:2:3" (cdr:ssexpand:read ins))
; (1 2 3)

コンマ区切りもっといい方法ないかな。真面目にtokensとか使うよりは若干短いんだけど。

rankingとか

貢献率3%くらいかな。CLももう少し貢献したい。