新次元新発想!新しい文法を作るスレ

このエントリーをはてなブックマークに追加
LISP scheme 向けの埋め込み構文 #n<num>
書式 #n <num> [<sexpr> ...]
<num>で指定した回数だけ後続のS式を読み込み、
1つのリストとみなす。

;#nで記述したアッカーマン
#n3 define #n3 ack m n
 #n4 if #n2 zero? m
  #n3 + n 1
  #n4 if #n2 zero? n
   #n3 ack #n3 - m 1 1
   #n3 ack #n3 - m 1 #n3 ack m #n3 - n 1

;↓と等価
(define (ack m n)
 (if (zero? m) (+ n 1)
  (if (zero? n) (ack (- m 1) 1)
   (ack (- m 1) (ack m (- n 1))))))

#n3 ack 3 8
=>2045

見ての通り、括弧が全く無い。
そのかわり、アンカーを頭に書く必要がある。

・・・どうかなあ?
すげー分かりづらい。その状態でどうやってS式を数えるんだよ。
>>861
うーん… python 風?
indent を固定しちゃえば、慣れれば読めそうだけど…
でも、 >>861 に同意。
内包できる Sexp の数を前置すると、最初に書くのもちょっと大変だし、
変更するときとかも複雑になりそう。
数字がずれるとわかりにくい bug になるだろうし。
>861
考え方は非常に原始的です。
最初に個数を置く関係上、
使う段階で数え終わっている必要があります。
まあ、>>860は極端な例です。

#n〜も1つのS式なので、
#n自身も>>860の様にネストできます。
例えば固定長のテーブルを書く場合に

>#n3 define data '
#n4 ; y
#n3 a b c ;x
#n3 d e f
#n3 g h i
#n3 j k l
=>data

>data
=>((a b c) (d e f) (g h i) (j k l))
というわけです。
メリットは、
括弧の閉じ忘れを気にしなくてよい、とか。
あと、リストの長さを限定したいときに
読み込み時チェックが掛かる。
>>862
ちなみにインデントは関係ないです。
#n3 define #n3 ack m n #n4 if #n2 zero? m #n3 + n 1
#n4 if #n2 zero? n #n3 ack #n3 - m 1 1 #n3 ack #n3 - m 1 #n3 ack m #n3 - n 1
これでもちゃんとパースされます。
慣れると1行野郎が楽に書けるかも・・。
全部に対して無理に使う必要もないので、
好きなところで長さ制限したい場合にでも使えそうです。
(そういう局面は少ないですが。)

#3 define data '
#n4
(a b c)
(d e f)
(g h i)
(j k l)
(m n o) ;←エラー
この拡張のソース

(define (fetch-sharp-nlist)
#let1 num (read)
(if (number? num) 'ok (error "Syntax Error : expect nuber. #n<num> [<sexpr> ...] ==>" num))
#let loop ((r '()) (n num))
(if (zero? n) (apply list (reverse r))
#let1 s (read)
(if (eof-object? s) (error "unterminated #n " num " " (reverse r)) 'ok)
(loop (cons s r) (- n 1))))

このfetch-sharp-nlistを#のディスパッチ関数から呼び出す。
readが再帰的に#フックを呼び出す仕様でないと使えません。

次の様にするとテストできます。
(fetch-sharp-nlist)3 define data '
(fetch-sharp-nlist)4
(a b c)
(d e f)
(g h i)
(j k l)
ぶっちゃけ多量の括弧のほうがはるかによみやすい。
わかりますわかります
こういう気分転換ができるところも、LISPの良い所。
>>860
数を数えるなんていう機械がやるべき単純作業を何故人間様がわざわざやらにゃならんのか
>>870
ソース見る限り<num>自体もS式だから、計算で求める事もできるよ。


なんつったりして。
>>871
そうだよ、リストの終りが分かるようになんかおきゃいいんだよ。




…閉じカッコとかどうよ?
整数型・ポイント型・実数型等と比較できるBOOL型配列を作って、
さらに、関数によって異なるBOOL型を扱えるのって、どう?

int foo::bar(void)::BOOL FALSE[]={-1,0}
/* or TRUE[]={1} 等々TRUEかFALSEのどちらかを指定でき、配列は返り値と同じ型 */
{ … /* 関数の定義 */ }

使い方は

foo a,b ;
int i ;
if ( a.bar() == FALSE ) … /* 返り値が、-1か0ならば */ ;
i = b.bar() ;
if ( i == b::bar()::TRUE /* foo::bar()::TRUE 等も可 */ ) … /* iが -1及び0でなければ */ ;
何が嬉しいのかサッパリ
875名無し@沢森:03/07/17 10:42
しょうがないな、おまいらよ。
俺が新文法を提示してやるよ。

・再帰用デフォルト引数
再帰関数でしか使えないデフォルト引数で、
外からはそのデフォルト引数しか使えず、
再帰呼び出しの時のみそれ以外の引数を指定できる。

例)
let pow x n (res := 1) =
 if n = 0 then
  res
 else
  pow x (n - 1) (res * x);; (* OK *)
pow 4 2;; (* OK *)
pow 4 2 5;; (* Irregal! *)

どうよ?
876名無し@沢森:03/07/17 10:43
sage ちまったよ。おい。
illegal 不法な、違法な
irregal リーガル(TM)でない
878名無し@沢森:03/07/17 11:59
すまんよ。
879磯斡葦胃飲斡:03/07/17 16:48
磯斡葦胃飲斡
>>875
再帰用関数が外から見えなきゃそれで済むやん
>>871
その場合はnumをevalに掛けないとS式そのものが渡される気がする
>>872
ソレダ (・∀・)
883デフォルトの名無しさん:03/07/18 00:37
>>859
#letは良い気がする。
一時変数作るだけで括弧のネストいるのは正直めんどいので。
884名無し@沢森:03/07/18 01:52
>>880
ヌヒよ。
いちいちインタフェイス関数と再帰用関数と
2つの関数を作るのは二度手間だと思わないのか?

あと、型に厳密な Objective Caml を例にしたのはまずかったやもしれんが、
再帰呼び出しだと引数を必ず指定することにすれば型推論できるな。
>>884
> いちいちインタフェイス関数と再帰用関数と
> 2つの関数を作るのは二度手間だと思わないのか?
いいえ

例えば named let とか
886山崎 渉:03/08/02 02:35
(^^)
887山崎 渉:03/08/15 17:10
    (⌒V⌒)
   │ ^ ^ │<これからも僕を応援して下さいね(^^)。
  ⊂|    |つ
   (_)(_)                      山崎パン
>> 885
884ではないんだが、schemeあんまり知らないんで教えてくれ。

named-let syntax sugarで、どうやって再帰関数を表に出さないで、
かつ2つの関数を作らないで記述するの?
889デフォルトの名無しさん:03/09/26 10:44
>>888
以下の2つは等価

(let loop ((hoge foo)
(fuga bar))
...)

(letrec ((loop (lambda (hoge fuga)
...)))
(loop foo bar))
(((lambda (loop) (set! loop (lambda (hoge fuga) ...)) loop) ())
891888:03/09/26 20:18
まだわからん(泣

defineだろうがletだろうがローカルか否かの違いはあっても
束縛じゃないの?
ocamlのletはLocalかどうかの区別がないだけだし。
named letであろうがなかろうが、インターフェースが必要でないの?
(define (pow x n)
(let loop (.....

(define (pow x n)
(letrec ((loop ...

let pow x n =
let loop =
....
とに関数の(束縛の)数に違いはないんじゃ?

lambda式だって名前なし関数だから、lambdaでくくれば
良いってものでもないし。
ローカル束縛のみで行うつーのがそもそも
理解できないんだけど。。。

ただ、>>875のはoptional labelつかえば
(checkはしてくれないけど)良いから
いらないと思う、すくなくともocamlには。

>>891
この話題は簡便に書けるかどうかじゃないの?
束縛の数とかは裏の作りの問題の様な気もするし。
LISP系ならあれこれ言う前にマクロで作ってみればいいんじゃないかと。
(define-macro (define-optional (name . arg)...)
`(define ,name (lambda ,(filter-not-optional arg)
 (let ,name ,(filter-optional arg),...)))
みたいにして、
(define-optional (pow x n (&optional res 1))
 (if(zero? n)res(pow x(1- n)(* res x))))
894888:03/09/26 21:20
>>892いや、2つの関数を作るのがめんどくさいという875(884)に対してnamed letがある、という885への疑問なのさ。named letってそんなに凄い文法だったか?と。>>893のようにoptionalで表現するのが普通だと俺も思うけど。
895888:03/09/26 21:22
改行ミスったうえに、あげてしまった。
schemeで、「場所」や「スレッド」という概念をfirst-classの値として
扱うことで、すっきりとしたモバイル計算が考えられそう、
ってたった今夢想してしまった。とっくに研究されているのだろうか?
>>896
継続とは違うの?
>>894
named let なら外部に内側の実装用引数を見せることなく、かつ
(見た目上) 内側に関数を入れ子にすることなく簡便に再帰を書ける、というだけのこと。
そんな深い話じゃない。
>>897
漏れの言った「スレッド」はあくまで計算の実行主体という意味で、
「継続」のような「計算の内容」とはちょっと異なるものを
想像してました。
なんていうか、、、

(let ((athread (make-thread) ; 別のスレッドを作って、
(alocation (bind-location "xxx.yyy.zzz.jp")) ; 場所をバインドして
(+ (+ 2 2) (eval-at alocation athread '(+ 1 1)))) ; (+ 1 1)はathreadが
; alocationにて実行
; (+ 2 2)とその後の
; 足し算は自分で実行

みたいなことができたらいいなとふと思った。研究レベルでなら山ほど
ありそうだが。。。
上のソースの2行目の最後に、閉じカッコもう1つ追加でした。。。
901デフォルトの名無しさん:03/11/28 01:20
tes
>>899
process migration っつーはなし?
903デフォルトの名無しさん:03/11/28 02:28
文法ではないけど、変数の名前付けに結構手間取ることが多いので、
ある程度言語側で決めてもらったら楽だと思った。
obj1->check<-obj2

obj1とobj2でデータを突き合わせてその結果を両方のobjに反映させる
>>903
implicit のことかーーーーーっ!!!
906デフォルトの名無しさん:04/01/14 01:39
2004
2005
908デフォルトの名無しさん:04/01/14 03:42
考えた
弁償型言語 D・V・D!
hello world はこんな感じ

定義
helloworld.dvdの目的: D・V・D!と言われたら 割れたDVDを 弁償 する
->弁償 とは お金 が ある なら それを支払う
->弁償 とは お金 が ない なら 代償 を行う
->代償 とは hello world を 表示 する

helloworld.dvd> お金 は ない
helloworld.dvd> D・V・D!
hello world


以上でっす!!!
自殺してくる!!!!!
909デフォルトの名無しさん
おっぱいだよ!