Closures vs Objects

2024/02/19(月) 20:39:15.91ID:VT95BnI9
It is well-known that closures and objects are equivalent. So are actors. Which one is the most fundamental?

よく知られたように、クロージャとオブジェクトは等価です。アクターも同様です。どの概念が最も基本的なのでしょうか?
2024/02/19(月) 20:49:06.93ID:VT95BnI9
A closure is a function with state in the local scope.
An object also has methods and state which belong to its instance.
These are compatible with each other.

クロージャはローカル・スコープに状態をもつ関数です。
オブジェクトもまたそのインスタンスに属するメソッドと状態を持ちます。
これらは互いに互換性があります。
2024/02/20(火) 09:36:12.34ID:fQy0X2aE
オブジェクトは複数のメソッドを持てる

クロージャは関数をひとつしか返せない

オブジェクトの勝ち
2024/02/20(火) 11:01:18.21ID:BFMbzAij
>>3
ハッシュテーブルに関数を追加して返すことで、複数のメソッドを返すことが可能
より柔軟に、オブジェクトとそれを操作する関数の組を返すこともできるし、無限個のメソッドをもったオブジェクトだって作れる
これらは書く対象によって使い分ければよいのであって、オブジェクトにメソッドが属しているのが常に最適とは限らない
たとえばイベントハンドラにコールバック関数として渡すような場合は、ひとつの関数として取得できたほうが便利
2024/02/20(火) 23:29:16.13ID:0cXn/136
クロージャのほうがprimitive
今時、高階関数やイテレータを書くのにわざわざデザインパターンとか使いたいかって話
クラスは、レキシカル環境つきオブジェクトだけが欲しくても必ず新しい名前空間が作られるし、単品で購入できない福袋みたいなもん
2024/02/21(水) 05:55:14.17ID:j79lZ4PO
二変数以上の関数のほとんどは、どの引数のオブジェクトに属しているともアプリオリには言えないし、オブジェクト指向は不自然
オブジェクトと引数は別物だし、もし関数を特定のオブジェクトに属するようにしたいなら、クロージャでラップすれば簡単にできる
2024/02/21(水) 05:56:37.93ID:j79lZ4PO
二変数以上の関数のほとんどは、どの引数のオブジェクトに属しているともアプリオリには言えないし、オブジェクト指向は不自然
オブジェクトと関数は別物だし、もし関数を特定のオブジェクトに属するようにしたいなら、クロージャでラップすれば簡単にできる
2024/02/21(水) 10:09:33.92ID:HBySQ9lj
2変数関数をクロージャにラップして1変数関数にしても、メソッドチェーンはできないよね
2024/02/21(水) 10:29:18.43ID:Cg6r5DK9
[1, 2, 3, 4, 5]にメソッドが属してれば

[1, 2, 3, 4, 5]
.filter(hoge) # ←戻り値もオブジェクト
.map(piyo) # ←これも
.sum()

みたいにできるけど、配列がオブジェクトじゃなかったら

map([1, 2, 3, 4, 5], hoge)

の戻り値はただの配列なので、繰り返し関数適用するには、Lispみたいな醜い入れ子にするしかない

sum(
 map(
  filter([1, 2, 3, 4, 5], hoge),
 piyo))
2024/02/21(水) 12:32:59.23ID:pWazjr0Z
>>8-9
これでどうよ

chain = (obj) => {
 return (f, ...args) => {
  if (!f) return obj
  return chain(f(obj, ...args))
 }
}

chain([1, 2, 3, 4, 5])(
 filter, (x) => x % 2)(
 map, (x) =>x * x)(
 sum)()
// => 35
2024/02/21(水) 15:43:45.17ID:im/wtuEl
一時期メタプログラミングとかいって、動的にクラスやメソッドを作れるのがすごいって言われてたけど、クロージャをデータ構造として使うならそれは自明にできることでは
2024/02/21(水) 16:28:56.20ID:4iB0jwLo
やり方が複数ある場合は、一番綺麗に書けるコードを採用するのが基本
2024/02/21(水) 22:54:29.50ID:DX/jvS2m
入れ子にしなくても関数合成でいいのでは?
メソッドチェーンっぽく書くには
Reverse-application operatorってのもあるけど
個人的には関数合成のほうがスッキリしててすこ

https://ideone.com/gCWxLP
let hoge n = n mod 2 = 1
let piyo = ( * ) 2
let () = print_int (List.fold_left (+) 0 (List.map piyo (List.filter hoge [1;2;3;4;5])))

(* function composition *)
let (<<) f g x = f (g x)
let f = print_int << List.fold_left (+) 0 << List.map piyo << List.filter hoge
let () = f [1;2;3;4;5]

let (>>) f g x = g (f x)
let f = List.filter hoge >> List.map piyo >> List.fold_left (+) 0 >> print_int
let () = f [1;2;3;4;5]

(* @@ Application operator *)
let () = print_int @@ List.fold_left (+) 0 @@ List.map piyo @@ List.filter hoge [1;2;3;4;5]

(* |> Reverse-application operator *)
let () = [1;2;3;4;5] |> List.filter hoge |> List.map piyo |> List.fold_left (+) 0 |> print_int
14デフォルトの名無しさん
垢版 |
2024/02/22(木) 01:30:07.21ID:seCGgTJE
Forth で書いてよ
2024/02/22(木) 08:01:15.94ID:5dknMZXg
>>13
カリー化のなせる技やね
2024/02/22(木) 08:40:34.15ID:GWomKHpC
chainl = (obj) => {
 return (f, arg) => {
  if (!f) return obj
  return chainl(f(arg, obj))
 }
}

cons = (x, xs) => [x, xs]

foreach = (lst, f) => {
 if(!lst) return
 [x, xs] = lst
 f(x)
 foreach(f, xs)
}

linkedList =
 chainl(null)(
  cons, 1)(
  cons, 2)(
  cons, 3)()

chainl(linkedList)(foreach, console.log)()
// 3
// 2
// 1

いろいろ書けるんだな
レスを投稿する

5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況