ChatGPTとGoogleBardを利用したメタプログラミング構文の提案

まとめ

ChatGPTとGoogleBardを利用して新しい構文を考えてもらう 新しい構文はChatGPTを利用してS式を展開することを期待する

メタプログラミングするために必要なlispの新しい構文を3つ創造してください. 生成AIの入出力に利用できるメタプログラミング構文を考えてください 以下に事例を3つ共有します。ai-eval:
目的: 生成AIのモデルを直接呼び出し、与えられた入力に対する応答を評価する。
構文: (ai-eval model input)
説明: model はAIモデルを指定し、input にはモデルに送る入力が含まれる。この関数はモデルからの出力を返す。
ai-define:
目的: 生成AIの応答を利用して、新しい関数やマクロを動的に定義する。
構文: (ai-define function-name input-pattern output-model)
説明: function-name は新しく定義される関数またはマクロの名前、input-pattern はこの関数に渡される入力のパターン、output-model は出力を生成するために使われるAIモデル。この構文は、与えられたパターンに基づいて入力を解析し、対応するAIモデルを用いて出力を生成する関数またはマクロを作成する。
ai-transform:
目的: 既存のコードに対してAIモデルを使用して変換を適用する。
構文: (ai-transform code-block transformation-model)
説明: code-block は変換されるLispコードのブロック、transformation-model はこの変換に使用されるAIモデル。この関数は、与えられたコードに対してAIモデルを使用して変換を行い、新しいコードブロックを生成する。
 上記の他によりよい構文を考えてみてください

Bardからの返答

以下に、生成AIの入出力に利用できるメタプログラミング構文を3つ考えました。

1. ai-generate

目的: 生成AIのモデルを使用して、新しいコードを生成します。

構文:

(ai-generate model input-pattern)

説明:

  • model は生成AIのモデルを指定します。
  • input-pattern は、生成AIに渡す入力のパターンを指定します。

この構文は、与えられたパターンに基づいて入力を解析し、対応する生成AIモデルを用いて新しいコードを生成します。

例えば、次のコードは、与えられた入力に基づいて、ランダムな文字列を生成する関数を生成します。

(defmacro ai-generate-random-string (model input-pattern)
  `(lambda ()
    (ai-generate model ,input-pattern)))

(defvar random-string-model (make-instance 'ai-random-string-model))

(defmacro generate-random-string ()
  (ai-generate-random-string random-string-model `(length ,(read))))

2. ai-rewrite

目的: 生成AIのモデルを使用して、既存のコードに変更を加えます。

構文:

(ai-rewrite code-block transformation-model)

説明:

  • code-block は変更されるLispコードのブロックを指定します。
  • transformation-model はこの変更に使用される生成AIモデルを指定します。

この構文は、与えられたコードに対して生成AIモデルを使用して変更を行い、新しいコードブロックを生成し、それを返します。

例えば、次のコードは、与えられた入力に基づいて、コード内のすべての関数名を大文字に変換します。

(defmacro ai-rewrite-uppercase (model input-pattern)
  `(lambda (code)
    (ai-rewrite code model ,input-pattern)))

(defvar uppercase-function-model (make-instance 'ai-uppercase-function-model))

(defmacro rewrite-uppercase (code)
  (ai-rewrite-uppercase uppercase-function-model `(code ,code)))

3. ai-generate-and-rewrite

目的: 生成AIのモデルを使用して、新しいコードを生成した後、そのコードを変更します。

構文:

(ai-generate-and-rewrite model input-pattern transformation-model)

説明:

  • model は生成AIのモデルを指定します。
  • input-pattern は、生成AIに渡す入力のパターンを指定します。
  • transformation-model はこの変更に使用される生成AIモデルを指定します。

この構文は、まず与えられたパターンに基づいて入力を解析し、対応する生成AIモデルを用いて新しいコードを生成します。次に、生成されたコードに対して、2番目の生成AIモデルを使用して変更を行い、新しいコードブロックを生成し、それを返します。

例えば、次のコードは、与えられた入力に基づいて、ランダムな文字列を生成し、その文字列をすべて大文字に変換します。

(defmacro ai-generate-and-rewrite-uppercase (model input-pattern)
  `(lambda ()
    (let ((code (ai-generate model ,input-pattern)))
      (ai-rewrite code transformation-model `(code ,code)))))

(defvar generate-and-rewrite-uppercase-model (make-instance 'ai-generate-and-rewrite-uppercase-model))

(defmacro generate-and-rewrite-uppercase ()
  (ai-generate-and-rewrite-uppercase generate-and-rewrite-uppercase-model `(length ,(read))))

これらの構文は、生成AIの入出力に利用することで、より柔軟で強力なメタプログラミングを実現することができます。

なぜ自分はLISPが好きなのか

tl;dr

S式ならばこの心配はありません。なぜならどんな問題であれ、 それが計算機で処理可能ならば何らかの内部表現を持つはずなので、 新たな問題に対応する内部表現を考えたらそれをそのまま書き下せば良いだけ だからです。

これに尽きる

なぜ自分はLISPが好きなのか

これまでLISPをなんとなく学んでいたが、S式の理由 を読んで言語化することができた。

終わりに

この文章はWIPなので定期的に更新する

ChatGPTの入力をLISPのS式にするメリデメ

tl;dr

chatGPT内のLLMは自然言語テキストから多く学習しているため、S式入力の理解・解釈が制約される可能性あり。

ChatGPTへの入力

ChatGPTへの入力文にて 自然言語よりも LISPのS式を選択する事によるメリデメを教えてください

ChatGPTへの出力

LISPのS式(S-expressions)をChatGPTへの入力文として使用することは、ある程度のメリットとデメリットがあります。

まず、メリットについては以下のとおりです:

  • 構造的明瞭さ:S式は、プログラムやデータの構造を明確に表現することができます。これにより、複雑な入力を構造的に表現することが可能となります。

  • エラーの発生が少ない:適切なS式が提供されると、一般的には文法的なエラーが少なくなる傾向にあります。これは、S式が事前に定義された明確な構造を持つためです。

  • 処理の再現性:同じS式を与えれば、その実行結果は一定であり、再現性があります。

一方で、デメリットも存在します:

  • 可読性と書きやすさ:自然言語に比べてS式は人間にとって直感的に理解しにくい場合があります。これは特に、LISPやS式に不慣れな人々にとっては大きな問題となる可能性があります。

  • 表現の自由度:S式は構造的である一方で、自由な表現を制約する場合があります。自然言語はその表現力が非常に高く、あらゆる種類の思考やアイデアを表現することが可能です。

  • ChatGPTの理解能力:GPT-4の訓練データは主に自然言語から構成されており、LISPやS式のような特定のプログラミング言語の理解や解釈は、自然言語に比べて制約される可能性があります。

以上が、LISPのS式をChatGPTへの入力文として使用することのメリットとデメリットです。

commonlispでFizzbuzz問題を解いてみる

最初の実装

まずはシンプルなFizzBuzz実装から始める。1から100までの数字を列挙し以下の条件に基づいて出力する。

  • 3で割り切れる場合は "Fizz"
  • 5で割り切れる場合は "Buzz"
(dotimes (i 100)
  (let* ((n (1+ i))
         (fizz (if (zerop (mod n 3)) "Fizz" ""))
         (buzz (if (zerop (mod n 5)) "Buzz" ""))
         (fizzbuzz (concatenate 'string fizz buzz)))
    (format t "~a~%" (if (string= fizzbuzz "") n fizzbuzz))))

これでFizzBuzzの基本的な実装が完成した。ここからコードを拡張する。

拡張版実装

こちらではルールを柔軟に追加できるようにした。

(defun print_fizzbuzz (i rules)
  (let* ((n (1+ i))
         (result (reduce (lambda (acc rule)
                           (let ((condition (first rule))
                                 (output (second rule)))
                             (if (funcall condition n)
                                 (concatenate 'string acc output)
                                 acc)))
                         rules
                         :initial-value "")))
    (if (string= result "")
        n
        result)))

(defun print_fizzbuzz_with_rules (limit rules)
  (dotimes (i limit)
    (let ((result (print_fizzbuzz i rules)))
      (format t "~a~%" result))))

(let ((rules (list (list #'(lambda (n) (zerop (mod n 3))) "Fizz")
                   (list #'(lambda (n) (zerop (mod n 5))) "Buzz"))))
  (print_fizzbuzz_with_rules 100 rules))

拡張版では rules 変数にルールを追加することで、例えば「7で割り切れる時は "hoge" を返す」といった機能を簡単に追加できるようになった。 また表示とルールを分離することでテストしやすいコードになった。

ChatGPTにLISPの新しい構文を考えてもらった (要求定義編)

以下は、要求定義を表現するために使用できる新しい構文の一連の具体的な例です。これらはLISPの構文を拡張し、より高い抽象度で情報処理システムの要求を表現するために使用できます。

1. `(def-case CASENAME CONDITIONS ACTIONS)` - 特定の条件が満たされた場合に実行されるアクションを定義する。例えば、`(def-case "ログイン" (user-exists? user-name) (login user-name))` は、ユーザーが存在する場合にログインするアクションを定義します。

2. `(def-entity ENTITY ATTRIBUTES)` - エンティティの属性を定義する。例えば、`(def-entity "ユーザー" (name age email))` は、ユーザーエンティティの名前、年齢、メールアドレスの属性を定義します。

3. `(def-function FUNCTIONNAME PARAMETERS BODY)` - 関数を定義する。例えば、`(def-function "加算" (a b) (+ a b))` は、2つの引数を加算する関数を定義します。

4. `(def-module MODULENAME FUNCTIONS)` - モジュール内の関数のグループを定義する。例えば、`(def-module "計算" *1 (def-function "減算" (a b) (- a b))))` は、計算モジュール内の加算と減算の関数を定義します。

5. `(def-requirement REQUIREMENT)` - システムの要求を定義する。例えば、`(def-requirement "ログイン機能")` は、ログイン機能の要求を定義します。

6. `(def-component COMPONENTNAME REQUIREMENTS)` - システムのコンポーネントとその要求を定義する。例えば、`(def-component "ユーザーサービス" ("ログイン機能"))` は、ユーザーサービスコンポーネントとそのログイン機能の要求を定義します。

7. `(def-interface INTERFACENAME METHODS)` - インタフェースとそのメソッドを定義する。例えば、`(def-interface "データベース接続" ("接続する" "切断する"))` は、データベース接続インタフェースとその接続と切断のメソッドを定義します。

8. `(def-class CLASSNAME ATTRIBUTES METHODS)` - クラスを定義し、その属性とメソッドを指定する。例えば、`(def-class "ユーザー" (name age) *2 ("情報を更新する" (new-name new-age) (set-name new-name) (set-age new

*1:def-function "加算" (a b) (+ a b

*2:"情報を表示する" () (display-info

GPT隆盛の時代にLispを勉強する

思いつきで上記文章書いたけど、「拾う」「書く」という既存の言語にはない概念をdefmacroしてそれぞれの要素(人間、鉛筆、ノート) に適用させてた。

きちんと理解できているみたい。すごい

 

```lisp

;; シミュレーション世界の定義
(defvar *world* (list (list 'pencil '(0 0))
                      (list 'notebook '(1 1))
                      (list 'person '(0 1))))

;; マクロ定義
(defmacro with-object *1
     result))

;; 出来事のシミュレーション
(with-object (pencil 'pencil '(0 0))
  (with-object (person 'person '(0 1))
    (with-object (notebook 'notebook '(1 1))
      (setf pencil (list 'pencil nil))
      (setf person (list 'person '(0 0)))
      (setf notebook (list 'notebook '(1 0)))
      (with-object (pencil 'pencil '(0 0))
        (with-object (person 'person '(0 1))
          (pick-up pencil person)
          (with-object (notebook 'notebook '(1 1))
            (write-on-notebook person notebook "かきくけこ"))))))))

;; 出来事の定義
(defun pick-up (pencil person)
  (let *2
    (setf pencil nil)
    result))

(defun write-on-notebook (person notebook text)
  (with-open-file (stream "note.txt" :direction :output :if-exists :supersede)
    (format stream "~aがノートに「~a」と書いた。"
            '彼 text)))

```

*1:var class position) &body body)
  `(let* ((,var (find-if (lambda (obj) (and (eq (car obj) ',class)
                                             (equal (cadr obj) ',position)))
                         *world*)))
          (result (progn ,@body)))
     (setf (cadr ,var) (position result

*2:result pencil

NotionとChatGPTを組み合わせてみた

chrome.google.com

 

最初にChatGPTとのやり取りを記録するNotion上データベースの指定が必要。

プラグイン自体の設定からテーブル指定し直しできる。

個人的にはスペースのトップに配置しておくのが良さそう