Common Lispの総称関数みたいな複数レシーバ (multiple dispatching) のOOP言語(Lispでない)を考えるとなにかならないかなあ…。
CLOSのmultiple dispatchはこう
;; メソッド定義
(defmethod method1 ((a int) (b string) (c int))
...)
;; メソッド呼び出し
(method1 1 "hoge" 3)
だけど、Lispじゃない言語でこれはどういう言語になるのかなあという妄想。
上のは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* ...] [ ...] { ... }`
- nil
;;;; 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 (succeeded)
+
; -> #<symbol: +>
20 10: +
; = invoke generic method: + [Number Number] Number
; -> 30
;; multiple dispatching (failed)
20 "s": +
; -> #<error.method-not-found: [Number String] [Number]>
TBD