Skip to content

Instantly share code, notes, and snippets.

@t-sin
Last active February 18, 2023 15:33
Show Gist options
  • Save t-sin/c0eefb3a7bdf3ee5078ca429e337f2c5 to your computer and use it in GitHub Desktop.
Save t-sin/c0eefb3a7bdf3ee5078ca429e337f2c5 to your computer and use it in GitHub Desktop.
multiple dispatchingなOOP言語ってなんだろう……という妄想。

複数レシーバOOP言語てきなもの

Common Lispの総称関数みたいな複数レシーバ (multiple dispatching) のOOP言語(Lispでない)を考えるとなにかならないかなあ…。

動機

CLOSのmultiple dispatchはこう

;; メソッド定義
(defmethod method1 ((a int) (b string) (c int))
   ...)
;; メソッド呼び出し
(method1 1 "hoge" 3)

だけど、Lispじゃない言語でこれはどういう言語になるのかなあという妄想。

multiple dispatchingは「レシーバ型任意」を含意するのか?

上のはRubyっぽく書くと

# メソッド定義
def method1(a:Int, b:String, c:Int)
  ...
end

# メソッド呼び出し
(1, "hoge", 3).send-like :method1

となる。この(1, "hoge", 3)は (generic function lambda listの評価結果の値で) たとえばTupleクラスとかのインスタンスかしらん。これはgf-lambda-listクラスの値にsend的なことができるってことにも見える。じゃあたとえばArrayインスタンスとかHashインスタンスとか、あとユーザが勝手に定義できる型Hogeのインスタンスにもsend的なことできるべきなのでは…? こんなかんじで。

{a: 1, b: 2}.send-like method1
#<hoge>.send-like method1

そんなかんじの言語ってどんなのになるのかしらーという妄想をしたい。

言語のしくみ

プリミティブ

こんなのあるといいの…?

  • primitives
    • nil nil
    • boolean true false
    • integer 10, -10
    • float 1.0, 123e10, -12e5
    • array (e1 e2 ...)
    • hash table {k1: v1 k2: v2 ...}
    • list [1 2]
    • string "string desu"
    • symbol name
    • proc [arg1:type1* arg2:type2* ...] [ ...] { ... }`

OOPのsingle dispatchingのコア?

;;;; object-oriented primitives (single-dispatch)
;;;
;;; `obj: send message-name arg-list`
;;;    Send a message `message-name` with arguments `arg ...` to `obj`.
;;;    If it's sent `invoke` with a name `nil`, it returns itself.
;;;
;;; `obj: make-slot name type`
;;;    Create a slot named `name` as `type`.
;;;    `type` is one of `reader`, `writer` and `accessor`.
;;;    If `type` is `reader`, the slot can be read.
;;;    If `type` is `writer`, the slot can write.
;;;    If `type` is `accessor`, the slot can write and be read.
;;;
;;; `obj: read slot-name value`
;;;    Read `value` to `obj`'s slot named `slot-name`.
;;;
;;; `obj: write slot-name`
;;;    Write a value to `obj`'s slot named `slot-name`.
;;;
;;; `: message-name [arg ...]`
;;;    Send a message to the global object `@`.

;; an object itself can be a message to return itself
10
; -> 10

"Hello, fungi world!": print
; Hello, fungi world!
; -> "Hello, fungi world!"

"Hello, fungi world!": format "  %s"
;   Hello, fungi world!
; -> "  Hello, fungi world!"

;; numeral operation
10: + 20
; -> 30

;; multiple-times method invocation in oneline
10: + 20: +30
; -> 60

;; proc object and invoke
;; `[arg`:type1* arg1:type2* ...] [<ret1-type> <ret2-type> ...] { ... }`
;; Argument and return value types are optional.
;;
[a:Int b:Int] [Int] { a: + b }
; -> #<proc: [Int Int] [Int]
[a:Int b:Int] [Int] { a: + b }: send 10 20  ; oh commutativity... (in the primitive layer)
; -> 30

multiple dispatchingのコア言語

;; multiple dispatching (succeeded)
+
; -> #<symbol: +>
20 10: +
; = invoke generic method: + [Number Number] Number
; -> 30

;; multiple dispatching (failed)
20 "s": +
; -> #<error.method-not-found: [Number String] [Number]>

ちゃんとした言語で書く任意型レシーバ…?

TBD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment