二変数以上の関数のほとんどは、どの引数のオブジェクトに属しているともアプリオリには言えないし、オブジェクト指向は不自然
オブジェクトと関数は別物だし、もし関数を特定のオブジェクトに属するようにしたいなら、クロージャでラップすれば簡単にできる
探検
Closures vs Objects
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))
[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
これでどうよ
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
メソッドチェーンっぽく書くには
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
いろいろ書けるんだな
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
いろいろ書けるんだな
2024/02/22(木) 10:55:42.37ID:2PGen9gt
カリー化もクロージャと可変長引数があればできるね
currying = (f, ...args) => (...rest) => f(...args, ...rest)
currying = (f, ...args) => (...rest) => f(...args, ...rest)
2024/02/22(木) 11:04:45.60ID:2PGen9gt
これで、mapなどが
map(f, col)
と、関数を先にとる形でも、>>16のchainlを用いて
chainl([1, 2, 3, 4, 5])(
currying(filter, (x) => x % 2))(
currying(map, (x) => x * x))(
sum)()
と書けるわけか
map(f, col)
と、関数を先にとる形でも、>>16のchainlを用いて
chainl([1, 2, 3, 4, 5])(
currying(filter, (x) => x % 2))(
currying(map, (x) => x * x))(
sum)()
と書けるわけか
2024/02/22(木) 11:11:29.91ID:2PGen9gt
いや、単にchainlを
chainl = (obj) => {
return (f, ...arg) => {
if (!f) return obj
return chainl(f(...arg, obj))
}
}
とすればいいのか
chainl = (obj) => {
return (f, ...arg) => {
if (!f) return obj
return chainl(f(...arg, obj))
}
}
とすればいいのか
2024/02/22(木) 12:04:47.68ID:0KLGqPZR
クロージャの真価はコンテキストを導入できること
(let ((a 1) (b 2)) (+ a b))
((lambda (a b) (+ a b)) 1 2)
は等価
なので、上のa + bの変わりに関数を返却すれば独立したスコープの状態をもつ何かを作れる
クラスベースのオブジェクト指向でも同様だが、そのようなコンテキストのテンプレート(= class)は静的にしか作れない
(let ((a 1) (b 2)) (+ a b))
((lambda (a b) (+ a b)) 1 2)
は等価
なので、上のa + bの変わりに関数を返却すれば独立したスコープの状態をもつ何かを作れる
クラスベースのオブジェクト指向でも同様だが、そのようなコンテキストのテンプレート(= class)は静的にしか作れない
21デフォルトの名無しさん
2024/02/22(木) 12:15:29.98ID:Q3haYGVO 静的なほうがバグの発見は早そう
2024/02/22(木) 13:03:51.54ID:BdBf3uc1
なんでも自由を許すと無秩序になる
>>10だって、シグネチャを無視することが前提の設計になってる
(最後に結果を呼び出す時は第一引数のfを省略する)
TypeScriptが使われるのもそれが理由
今やPythonやRubyにも型がある
>>10だって、シグネチャを無視することが前提の設計になってる
(最後に結果を呼び出す時は第一引数のfを省略する)
TypeScriptが使われるのもそれが理由
今やPythonやRubyにも型がある
23デフォルトの名無しさん
2024/02/22(木) 13:23:57.40ID:v9QmWW2c2024/02/22(木) 13:24:08.05ID:WrtsfcL/
型なんて、プログラマがちまちま書かずとも、コンパイラや型チェッカが実行前に検査してくれればいいと思う
2024/02/22(木) 15:02:53.21ID:bbu+R1aP
currying = (f) => {
args = []
apply = (a) => {
if (a === undefined) return f(...args)
args.push(a)
return apply
}
return apply
}
args = []
apply = (a) => {
if (a === undefined) return f(...args)
args.push(a)
return apply
}
return apply
}
2024/02/22(木) 18:39:34.82ID:SfbO+Gz+
クロージャはポリモーフィズムができない
オブジェクト指向言語ではたとえば比較演算子の動作を型によって変えられる
a.compare(b)とソースコードのどこに書いても、aの型に応じて適切にcompareの動きが選択される
変数の型によって実行する関数を変えるにはどうする?
まさか関数定義に型による条件分岐をいちいち書くわけじゃあるまいし
オブジェクト指向言語ではたとえば比較演算子の動作を型によって変えられる
a.compare(b)とソースコードのどこに書いても、aの型に応じて適切にcompareの動きが選択される
変数の型によって実行する関数を変えるにはどうする?
まさか関数定義に型による条件分岐をいちいち書くわけじゃあるまいし
27デフォルトの名無しさん
2024/02/22(木) 19:07:57.79ID:v9QmWW2c class構文が入るまでどうやってJSでクラスを定義してたのか調べれば分かるよ
2024/02/22(木) 19:20:20.77ID:bu5i+qrs
>>27
a.hoge()のようにしてダックタイピングするなら当然できる
hogeがa(or a.prototype)に属さないただの関数の場合でも
hogeの中で型による条件分岐を書く以外の方法でできるか
a.hoge()のようにしてダックタイピングするなら当然できる
hogeがa(or a.prototype)に属さないただの関数の場合でも
hogeの中で型による条件分岐を書く以外の方法でできるか
2024/02/22(木) 19:30:27.02ID:coyprm7i
30デフォルトの名無しさん
2024/02/22(木) 19:41:55.54ID:v9QmWW2c >>28
なんて?
なんて?
2024/02/22(木) 20:46:51.05ID:5LGf2QVl
>>26,28
a, bではなくcompareのほうを、状態をもった関数オブジェクトとして生成する
一例として、
compareのクロージャには、「型名=>その型の引数を受け取った時に呼び出す関数」のテーブルを保持する
そのテーブルに関数を動的に登録するための関数を作成する
例:
IComparable = () => {
dispatch = {}
compare = (self, other) => { /*dispatchテーブルから関数を検索して実行*/ }
implement = (type, fn) => { /* dispatchテーブルにfnを登録 */ }
return [compare, implement]
}
もちろんdispatchの条件は型名じゃなくても、別の判定用関数を用意してもいい
a, bではなくcompareのほうを、状態をもった関数オブジェクトとして生成する
一例として、
compareのクロージャには、「型名=>その型の引数を受け取った時に呼び出す関数」のテーブルを保持する
そのテーブルに関数を動的に登録するための関数を作成する
例:
IComparable = () => {
dispatch = {}
compare = (self, other) => { /*dispatchテーブルから関数を検索して実行*/ }
implement = (type, fn) => { /* dispatchテーブルにfnを登録 */ }
return [compare, implement]
}
もちろんdispatchの条件は型名じゃなくても、別の判定用関数を用意してもいい
2024/02/22(木) 20:49:14.36ID:5LGf2QVl
インタフェースの実装は、型定義に書くよりも使用時に動的にできた方が自然だ
たとえば木構造にイテレータを実装するとして、深さ優先探索にするのか幅優先探索にするのかは、その時々によって変わる。木構造の定義だけからは決まらない
たとえば木構造にイテレータを実装するとして、深さ優先探索にするのか幅優先探索にするのかは、その時々によって変わる。木構造の定義だけからは決まらない
2024/02/22(木) 22:14:42.54ID:BzyFji/L
最近のフレームワークはどんどん脱オブジェクト指向・関数型化してないか?
Pythonのフレームワークは機能のMixinは継承ではなくデコレータ(ようはクロージャ)によるものが多い
Reactなんか思想は元々関数型的だったけど、ついにクラスコンポーネントやめちゃった
Pythonのフレームワークは機能のMixinは継承ではなくデコレータ(ようはクロージャ)によるものが多い
Reactなんか思想は元々関数型的だったけど、ついにクラスコンポーネントやめちゃった
2024/02/23(金) 00:14:17.41ID:vwgp24xa
cps = (f) => (...args) => args.pop()(f(...args))
eq = cps((a, b) => a === b)
sub = cps((a, b) => a - b)
mul = cps((a, b) => a * b)
fact = (n, k) => {
eq(n, 0, (isZero) => {
if(isZero) {
return k(1)
}
else {
return sub(n, 1, (prevn) =>{
fact(prevn, (prevf) => {
mul(n, prevf, k)
})
})
}
})
}
fact(5, console.log)
eq = cps((a, b) => a === b)
sub = cps((a, b) => a - b)
mul = cps((a, b) => a * b)
fact = (n, k) => {
eq(n, 0, (isZero) => {
if(isZero) {
return k(1)
}
else {
return sub(n, 1, (prevn) =>{
fact(prevn, (prevf) => {
mul(n, prevf, k)
})
})
}
})
}
fact(5, console.log)
2024/02/23(金) 13:52:03.15ID:P8ZW/vvm
Closures are functions with contexts.
Objects are structures with contexts.
A structure can have functions as its member, and vice versa.
So both are equal.
Objects are structures with contexts.
A structure can have functions as its member, and vice versa.
So both are equal.
2024/02/23(金) 19:20:29.47ID:mZKLNS+O
オブジェクトよりも、クロージャよりも、第一級継続のほうが強い
37デフォルトの名無しさん
2024/02/24(土) 00:22:58.31ID:PF21lJOY >>36
パフォーマンスは?
パフォーマンスは?
2024/02/24(土) 06:28:09.62ID:dndVDS6q
39デフォルトの名無しさん
2024/02/24(土) 11:30:44.99ID:PF21lJOY >>38
その回答、第一級継続関係無いやん。
その回答、第一級継続関係無いやん。
2024/02/24(土) 21:14:52.39ID:4BGFiybC
オブジェクトとクロージャが使えることは、コードブロック(+ ローカル変数)を第一級オブジェクトに持っているのだと思える
継続が第一級オブジェクトなのは、プログラム実行時の任意の状態が第一級オブジェクトということ
継続が第一級オブジェクトなのは、プログラム実行時の任意の状態が第一級オブジェクトということ
41デフォルトの名無しさん
2024/02/24(土) 21:42:30.15ID:fbMBQzh4 >>40
継続使う場合のパフォーマンスは?
継続使う場合のパフォーマンスは?
2024/02/25(日) 00:23:07.77ID:bNSutqDu
2024/02/25(日) 09:10:18.70ID:zl+9FS4I
継続はクロージャで表現されるけど、オブジェクトとクロージャが同値なら、オブジェクトによる表現もできるの?
44デフォルトの名無しさん
2024/02/25(日) 10:52:31.35ID:5QMstwYR : fact dup
1 = if
drop
else
dup 1- rot rot *
swap recurse
then
;
1 5 fact cr .
1 = if
drop
else
dup 1- rot rot *
swap recurse
then
;
1 5 fact cr .
2024/02/25(日) 11:03:04.14ID:O8qt4uJC
インタフェースが静的に決まれば保守性はおちないと思う
46デフォルトの名無しさん
2024/02/25(日) 11:17:17.62ID:azDE+Je3 近年まれにみる良スレ
2024/02/25(日) 11:28:28.39ID:PRxvM5Hr
>>31
これ継承の問題点を全部解消してる上に継承よりも強力だな
これ継承の問題点を全部解消してる上に継承よりも強力だな
48デフォルトの名無しさん
2024/02/25(日) 16:27:53.33ID:4fScDWQR ハァ?
2024/02/25(日) 16:36:21.69ID:wVCQJTWx
2024/02/25(日) 17:38:12.08ID:EvE7ghxV
2024/02/25(日) 17:55:13.30ID:BE8i65fG
>>43
できるだろうけど、継続自体が手続き/関数的な概念なので、オブジェクトによる表現をするメリットは少ないと思う
できるだろうけど、継続自体が手続き/関数的な概念なので、オブジェクトによる表現をするメリットは少ないと思う
2024/02/25(日) 19:51:34.20ID:O9l+7I5E
継続とコルーチンなら、継続のほうがprimitiveなの?
2024/02/25(日) 20:50:19.80ID:ZY2lsWgE
>>52
継続が第一級なら保存した継続を何度も呼び出せるが、コルーチンはyieldしたらもうその時点には戻れないので、継続のほうが根本的
継続が第一級なら保存した継続を何度も呼び出せるが、コルーチンはyieldしたらもうその時点には戻れないので、継続のほうが根本的
2024/02/26(月) 12:34:53.26ID:9feDQZG5
なんでもクロージャだと戻り値全部関数だけど、型情報を持つことはできる?
ディスパッチするのに必要だよね?
ディスパッチするのに必要だよね?
2024/02/26(月) 15:19:09.55ID:L4EYeETV
>>54
type属性をもったオブジェクトとして返却すればいいんじゃないんですかね
それを毎回書きたくないなら、生成用関数を受け取って新しい生成用関数を返す関数
makeConstructor = (f) => (type, ...args) => {type: type, value: f(...args)}
みたいなのを使ってみてはどうでしょうか
type属性をもったオブジェクトとして返却すればいいんじゃないんですかね
それを毎回書きたくないなら、生成用関数を受け取って新しい生成用関数を返す関数
makeConstructor = (f) => (type, ...args) => {type: type, value: f(...args)}
みたいなのを使ってみてはどうでしょうか
2024/02/26(月) 18:51:01.76ID:k7j7cG9/
>>55
これ、オブジェクトからtype属性つきオブジェクトへの関数、を持ち上げる関数書けばモナドになるから自動的に変換できるんだな
これ、オブジェクトからtype属性つきオブジェクトへの関数、を持ち上げる関数書けばモナドになるから自動的に変換できるんだな
2024/02/26(月) 22:39:42.49ID:qQrR5NbL
そもそもオブジェクトの型を動的に判定することは不可能なのだ
ただのシンボル'0'が整数であるとは数学的に決して言えない
整数の性質を満たす集合に属しているから整数と言えるのだ
だからオブジェクトが型を授かるためにクラスは絶対に必要なのだ
ただのシンボル'0'が整数であるとは数学的に決して言えない
整数の性質を満たす集合に属しているから整数と言えるのだ
だからオブジェクトが型を授かるためにクラスは絶対に必要なのだ
2024/02/26(月) 22:55:13.16ID:9WvTd710
そもそもふだんそんなにポリモーフィズムしてるか?
型ヒント書いたら実行前にチェックできるとか、中間コードにコンパイルされる時高速になるとか、それでよくないか?
型ヒント書いたら実行前にチェックできるとか、中間コードにコンパイルされる時高速になるとか、それでよくないか?
2024/02/26(月) 22:58:38.34ID:sdXywFcL
モダンなプログラミング言語
Go、Rust、Zig、Nim、Julia、Elixirなどは
クラスおよびその継承を言語仕様から排除している
それぞれの言語は全く異なる方針を採っているがクラス排除だけは全てで一致している
クラスとその継承は悪手であるとプログラミング言語界では結論が出ている
Go、Rust、Zig、Nim、Julia、Elixirなどは
クラスおよびその継承を言語仕様から排除している
それぞれの言語は全く異なる方針を採っているがクラス排除だけは全てで一致している
クラスとその継承は悪手であるとプログラミング言語界では結論が出ている
2024/02/26(月) 23:36:19.27ID:L97i44S4
xの型がT
y = Foo(x)なら
yの型はFoo(T)
というシステムでいいと思うの
Length ::= Float
Angle ::= Float
Point ::= Tuple(Float, Float)
Triangle ::=
Triangle(Length, Length, Length)
| Triangle(Length, Length, Angle)
| Triangle(Length, Angle, Angle)
| Triangle(Point, Point)
y = Foo(x)なら
yの型はFoo(T)
というシステムでいいと思うの
Length ::= Float
Angle ::= Float
Point ::= Tuple(Float, Float)
Triangle ::=
Triangle(Length, Length, Length)
| Triangle(Length, Length, Angle)
| Triangle(Length, Angle, Angle)
| Triangle(Point, Point)
2024/02/26(月) 23:50:16.48ID:TyGRqLb7
62デフォルトの名無しさん
2024/02/27(火) 00:02:52.99ID:woInknqq クラスは不要で型クラスは必要
2024/02/27(火) 06:56:00.52ID:cCaBYlch
Natural = fn
[0] 0
[n: n >= 0] n
end
succ = fn [Natural(n)] Natural(n + 1) end
add = fn
[n, Natural(0)] n
[n, succ(m)] succ(add(n, m))
end
mul = fn
[n, Natural(0)] Natural(0)
[n, succ(m)] add(mul(n, m), n)
end
AdditiveMonoid = Monoid()
AdditiveMonoid.implimentsIdentity(Natural, fn [] Natural(0) end)
AdditiveMonoid.implimentsAppend(Natural, add)
MultiplicativeMonoid = Monoid()
MultiplicativeMonoid.implimentsIdentity(Natural, fn [] Natural(1) end)
MultiplicativeMonoid.implimentsAppend(Natural, mul)
[0] 0
[n: n >= 0] n
end
succ = fn [Natural(n)] Natural(n + 1) end
add = fn
[n, Natural(0)] n
[n, succ(m)] succ(add(n, m))
end
mul = fn
[n, Natural(0)] Natural(0)
[n, succ(m)] add(mul(n, m), n)
end
AdditiveMonoid = Monoid()
AdditiveMonoid.implimentsIdentity(Natural, fn [] Natural(0) end)
AdditiveMonoid.implimentsAppend(Natural, add)
MultiplicativeMonoid = Monoid()
MultiplicativeMonoid.implimentsIdentity(Natural, fn [] Natural(1) end)
MultiplicativeMonoid.implimentsAppend(Natural, mul)
2024/02/27(火) 11:48:35.86ID:T+tKpG5+
たしかに「この関数から返ってたらこの型」というのはそうか
インタフェース型を返す関数から返った値は、その実体がなんであってもインタフェース型として受け取らないといけないのか
インタフェース型を返す関数から返った値は、その実体がなんであってもインタフェース型として受け取らないといけないのか
2024/02/27(火) 14:07:25.42ID:HfXhKUnc
Pythonの型ヒントも、内部的にやってることは型の階層構造を保存したオブジェクト作ったりしてるだけだし、型をクロージャで表すというのは十分に現実的
2024/02/28(水) 09:15:01.79ID:ZVd213Rl
なんでもクロージャでは構造に基づくサブタイピングができないから、ポリモーフィズムするなら必然的に名前に基づくサブタイピングをする必要がある
2024/02/28(水) 18:59:36.77ID:FE9gquBK
型注釈はクロージャで実現できるけど、肝心の個別のオブジェクトに型を付与するには、処理系に手加えないと無理だね
2024/02/28(水) 20:20:50.87ID:YGaU0GOk
ただのクロージャにこれはLinkedListだみたいな型情報をつけるなら
JavaScriptのようにすべてのオブジェクトがフィールドを持てるようにして、クロージャもtype属性みたいなのを持てるようにする
Pythonのように__call__()メソッドを実装すればオブジェクトも関数として呼び出せるようにして、オブジェクトにラップする
おとなしくにハッシュテーブルにラップするとかして、関数としてのインタフェースを保つのは諦める
JavaScriptのようにすべてのオブジェクトがフィールドを持てるようにして、クロージャもtype属性みたいなのを持てるようにする
Pythonのように__call__()メソッドを実装すればオブジェクトも関数として呼び出せるようにして、オブジェクトにラップする
おとなしくにハッシュテーブルにラップするとかして、関数としてのインタフェースを保つのは諦める
2024/02/28(水) 22:56:39.74ID:E1vk9WfJ
型定義
Counter = Type(fn [n]
fn [i] n += i end
end)
f = Counter(0)
f is Counter # true
f(1) # 1
f(2) # 3
f(3) # 6
エイリアス
Adder = Counter
f is Adder # true
多相型
Pair = Type(fn [T, S]
fn [t: T, s: S] (t, s)
end)
p = Pair(Int, Str)(1, 'Hello')
p is Pair(Int, Str) # true
Counter = Type(fn [n]
fn [i] n += i end
end)
f = Counter(0)
f is Counter # true
f(1) # 1
f(2) # 3
f(3) # 6
エイリアス
Adder = Counter
f is Adder # true
多相型
Pair = Type(fn [T, S]
fn [t: T, s: S] (t, s)
end)
p = Pair(Int, Str)(1, 'Hello')
p is Pair(Int, Str) # true
2024/02/28(水) 23:27:14.87ID:BtUR2apE
クロージャはその外の変数をキャプチャできてこそ本領を発揮する
2024/02/29(木) 09:14:52.93ID:kNys7UfZ
実行のたびに無名関数を生成すると
Pair(Int, Str)の実体が毎回変わってしまう
同じ型として扱うならキャッシュしとかんといかん
Foo()の結果がFoo型になるので、自然にヒエラルキー
Pair(Int, Str) ⊂ Pair ⊂ Type
ができる
子はすべての親を知っているが、親は直接の子しか知らない
Pair(Int, Str)の実体が毎回変わってしまう
同じ型として扱うならキャッシュしとかんといかん
Foo()の結果がFoo型になるので、自然にヒエラルキー
Pair(Int, Str) ⊂ Pair ⊂ Type
ができる
子はすべての親を知っているが、親は直接の子しか知らない
2024/02/29(木) 21:57:07.71ID:FO1fpwyp
ユニオン型
Male = Type()
Female = Type()
Sex = Male | Female
代数的データ型
Nil = Type()
Cons = Type(fn
[T] fn [x: T, xs: List(T)] (x, xs) end
end)
List = Type(fn [T] Nil | Cons(T) end)
c = Cons(Int)(1, Nil())
c is Cons(Int) # true
nl = Nil()
nl is Nil # true
nl is List(Int) # ( = Nil | Cons(T) ) true
l = Cons(2, c)
l is List(Int) # true
Male = Type()
Female = Type()
Sex = Male | Female
代数的データ型
Nil = Type()
Cons = Type(fn
[T] fn [x: T, xs: List(T)] (x, xs) end
end)
List = Type(fn [T] Nil | Cons(T) end)
c = Cons(Int)(1, Nil())
c is Cons(Int) # true
nl = Nil()
nl is Nil # true
nl is List(Int) # ( = Nil | Cons(T) ) true
l = Cons(2, c)
l is List(Int) # true
2024/03/01(金) 09:17:33.48ID:uT9YQz7T
クロージャは
(1) 評価可能な任意のコードブロックをオブジェクト化できる
(2) 新しいコンテクストを導入できる
(3) 評価を遅延可能
(4) 即時生成可能
(1) 評価可能な任意のコードブロックをオブジェクト化できる
(2) 新しいコンテクストを導入できる
(3) 評価を遅延可能
(4) 即時生成可能
2024/03/01(金) 13:47:12.10ID:hUzmZgl8
クロージャは、評価可能な任意のコードブロックを第一級オブジェクトとして扱える
継続は、プログラム実行時の任意の状態と処理を第一級オブジェクトとして扱える
継続は、プログラム実行時の任意の状態と処理を第一級オブジェクトとして扱える
75デフォルトの名無しさん
2024/03/01(金) 15:52:11.47ID:5dJkdiP3 欠点は何?
2024/03/01(金) 16:27:28.29ID:lcFJqP/H
>>75
汎用的な制御構造として使うには難解すぎること
汎用的な制御構造として使うには難解すぎること
2024/03/01(金) 17:06:01.87ID:lcFJqP/H
継続を入れ子にするともう予測不可能になる
2024/03/02(土) 00:04:51.39ID:WOl8O7ii
言語の高速化は処理系の仕事なのだから、特定の処理系で実行速度を最適化するために冗長な書き方を強いられるのは馬鹿げている
2024/03/02(土) 00:15:28.02ID:A93OEkS3
型がクロージャなら例外もクロージャで表現できそう
80デフォルトの名無しさん
2024/03/02(土) 01:38:33.15ID:vVlrIC3U >>76
そこはシンタックスシュガー用意できる?
そこはシンタックスシュガー用意できる?
2024/03/02(土) 02:47:41.13ID:WOl8O7ii
>>80
たとえばコルーチンとか、非決定的なバックトラックとかなら
たとえばコルーチンとか、非決定的なバックトラックとかなら
2024/03/02(土) 09:23:44.53ID:ykoZd5Kv
>>79
例外処理こそ継続とパターンマッチを使うべきだよなあと思う
例外処理こそ継続とパターンマッチを使うべきだよなあと思う
83デフォルトの名無しさん
2024/03/02(土) 11:12:48.28ID:hFGO4sAk 決定性のバックトラックなんてあるの?
2024/03/02(土) 16:06:45.66ID:BdR3F6bT
>>81
Pythonでいうとこのジェネレータ内包表記みたいなのがあれば、多くの場面で十分なのかな
Pythonでいうとこのジェネレータ内包表記みたいなのがあれば、多くの場面で十分なのかな
2024/03/02(土) 19:52:13.99ID:IQAkxugo
>>84
コルーチンの中でコルーチンを呼び出したら、yieldしたら最上位の呼び出し元まで返ってくるのが望ましい
コルーチンの中でコルーチンを呼び出したら、yieldしたら最上位の呼び出し元まで返ってくるのが望ましい
2024/03/02(土) 21:01:52.57ID:yMdn9rGJ
>>85
非同期コルーチンAの中で非同期コルーチンBを呼ぼうとしたら自動的にAはyieldして戻ってからコルーチンBを呼び出し
そのBについても全て終えるか他コルーチン呼び出しで自動的にyield
それぞれyieldして待機中の非同期コルーチンは呼び出し先が解決するとyield時点から再開
というスタックレス非同期コルーチンが何万も稼働しています
非同期コルーチンAの中で非同期コルーチンBを呼ぼうとしたら自動的にAはyieldして戻ってからコルーチンBを呼び出し
そのBについても全て終えるか他コルーチン呼び出しで自動的にyield
それぞれyieldして待機中の非同期コルーチンは呼び出し先が解決するとyield時点から再開
というスタックレス非同期コルーチンが何万も稼働しています
2024/03/03(日) 13:45:11.38ID:qMaLplcd
「コ」ルーチンなんだから上位という概念がそもそもない
2024/03/03(日) 14:01:49.17ID:IZl/xWS6
>>87
スタックレス非同期コルーチンは上位ランタイムがCPUコアスレッド数をフルに使って幾万個の軽い非同期コルーチンをスケジューリングすることでCPU性能を使い尽くすことができる
スタックレス非同期コルーチンは上位ランタイムがCPUコアスレッド数をフルに使って幾万個の軽い非同期コルーチンをスケジューリングすることでCPU性能を使い尽くすことができる
2024/03/03(日) 14:47:38.82ID:qMaLplcd
的外れ
2024/03/03(日) 14:53:35.32ID:IZl/xWS6
的外れとは?
現在のネットインフラは>>88の通り動いている現実を認めたくない?
現在のネットインフラは>>88の通り動いている現実を認めたくない?
2024/03/03(日) 17:03:12.55ID:Vr3nU8ht
>>87
あなたの言うコルーチンの定義は?
あなたの言うコルーチンの定義は?
2024/03/05(火) 13:01:59.74ID:hcPpBjWs
スタックフルのコルーチンは、内部で呼び出したコルーチンがyieldしてるかどうか呼び出し元が知っていないといけない
つまりカプセル化を破壊する
つまりカプセル化を破壊する
2024/03/05(火) 14:58:20.75ID:QuH/Int2
複数のスレッドが協調して何かするなんてのは、もはやプログラミング言語の領分じゃないんだよなぁ
2024/03/05(火) 22:53:42.99ID:1H/gFsr2
Erlang OTPみたいなアプローチが良いと思う
2024/03/08(金) 23:46:15.42ID:7wk+t80g
重要なのはプロトコル
定められた型のメソッドを持つことが重要
定められた型のメソッドを持つことが重要
2024/03/11(月) 12:27:38.30ID:HvPoaoEY
実装の継承は悪手
2024/03/13(水) 21:40:17.77ID:lx8X47UA
関数とオブジェクトなんて、要はどっちも値を入れたら何かを返す箱なのだから、内部構造を考えなければ共通化できるはず
配列も、機能だけ見れば、キーが数値なだけのただのオブジェクト
リストやジェネレータなどをイテレートするのも、関数を引数なしで呼び出すようなもの
配列も、機能だけ見れば、キーが数値なだけのただのオブジェクト
リストやジェネレータなどをイテレートするのも、関数を引数なしで呼び出すようなもの
2024/03/13(水) 23:38:55.71ID:+S4Brq3S
Pythonは__call__()メソッドを実装することでオブジェクトも関数のように振る舞える
これは小規模なプログラムでは関数として実装しておき、大規模になったらシームレスに移行できるように
これは小規模なプログラムでは関数として実装しておき、大規模になったらシームレスに移行できるように
2024/03/14(木) 18:36:51.37ID:rbf7F1li
Iterable⊂Callable⊃Associative
だが、Iterableとしての呼び出し方とAssociativeとしての呼び出し方が異なる
だが、Iterableとしての呼び出し方とAssociativeとしての呼び出し方が異なる
100デフォルトの名無しさん
2024/03/14(木) 18:40:46.10ID:rbf7F1li x = [1, 2, 3]をIterableとしてCallableだと思う場合、x() = next(x)
AssociativeとしてCallableだと思う場合、x(n) = x[n]
になる
AssociativeとしてCallableだと思う場合、x(n) = x[n]
になる
101デフォルトの名無しさん
2024/03/14(木) 21:09:23.66ID:xE50NtDY マシン語を知らないと妙なこだわりを言い出すからおもしろいよなw
102デフォルトの名無しさん
2024/03/14(木) 23:24:02.50ID:yxqrN1vV 異なる層の話を出すのもどうかと思うがね
103デフォルトの名無しさん
2024/03/15(金) 08:26:32.50ID:vBMVv6T3 >>101
コンピュータサイエンスにおいて低レイヤーが上位という価値観があるのって、おそらく日本だけだと思うんだけど、どうしてこういう逆行現象が起こるんだろう?
コンピュータサイエンスにおいて低レイヤーが上位という価値観があるのって、おそらく日本だけだと思うんだけど、どうしてこういう逆行現象が起こるんだろう?
104デフォルトの名無しさん
2024/03/15(金) 08:47:50.82ID:0zJIPs3S 数学だと基礎論は馬鹿にされてるよね
通常の数学やるときに選択公理だとか不完全性定理だとかいってるのは素人だけ
そりゃ形式的に「基礎論のほうが原理に近い」というだけならべつに数学を知らなくても分かるからね
通常の数学やるときに選択公理だとか不完全性定理だとかいってるのは素人だけ
そりゃ形式的に「基礎論のほうが原理に近い」というだけならべつに数学を知らなくても分かるからね
105デフォルトの名無しさん
2024/03/15(金) 08:56:58.18ID:wSiNosZi106デフォルトの名無しさん
2024/03/15(金) 09:01:28.78ID:0zJIPs3S ふつうは情報学科でも昔ならSICPでやったようなプログラミングの概念や機能に関する講義があるはずで、
ちゃんと勉強している人で実装と機能を分けて考えるということができない人はいないよ
日本で低レイヤーが偉そうな顔してるのは単に、大学等で体系的に学ばずに昔からパソコンに触ってただけのおじさんが言ってるだけ
日本ではプログラマが高等教育が必要な専門技術職として見なされておらず、パソコンしか取り柄のない社会不適合者を低賃金でこきつかう職種だと見なされていたのが原因
ちゃんと勉強している人で実装と機能を分けて考えるということができない人はいないよ
日本で低レイヤーが偉そうな顔してるのは単に、大学等で体系的に学ばずに昔からパソコンに触ってただけのおじさんが言ってるだけ
日本ではプログラマが高等教育が必要な専門技術職として見なされておらず、パソコンしか取り柄のない社会不適合者を低賃金でこきつかう職種だと見なされていたのが原因
107デフォルトの名無しさん
2024/03/15(金) 09:10:45.64ID:5Fl9dqIV >>104
物理学科の自称秀才がやたらと素粒子論専攻したがるのもこれだよなぁ……
実際に勉強して内容に興味を持てたかどうかではなくて、ラベルで判断してる
20過ぎた大人が将来の進路に関わる選択でそういうことするのは、病的としか言いようがない
物理学科の自称秀才がやたらと素粒子論専攻したがるのもこれだよなぁ……
実際に勉強して内容に興味を持てたかどうかではなくて、ラベルで判断してる
20過ぎた大人が将来の進路に関わる選択でそういうことするのは、病的としか言いようがない
108デフォルトの名無しさん
2024/03/15(金) 12:38:47.19ID:ohT/C40H109デフォルトの名無しさん
2024/03/15(金) 14:11:38.88ID:DTF+UIWv a) 実装継承
b) 多重継承
c) 多段階継承
ができる時点で菱形継承問題は避けられない
Rubyは、クラスは(b)を、モジュールは(c)を諦めることでこの問題を回避している
b) 多重継承
c) 多段階継承
ができる時点で菱形継承問題は避けられない
Rubyは、クラスは(b)を、モジュールは(c)を諦めることでこの問題を回避している
110デフォルトの名無しさん
2024/03/15(金) 14:37:43.94ID:zsH6n39D >>108
pythonはそうだよ
pythonはそうだよ
111デフォルトの名無しさん
2024/03/15(金) 16:37:06.04ID:HEyD2qcN Rubyのrefinementsみたいに、このスコープでは型定義を変えるみたいなのがあればまだマシになんのかな
たとえば、あるブロック内でだけ(Int, Int)をPoint2Dとみなすとか
たとえば、あるブロック内でだけ(Int, Int)をPoint2Dとみなすとか
112デフォルトの名無しさん
2024/03/15(金) 17:16:49.88ID:Ratd2baE >>108
・具象型とインタフェースを分ける
具象型→Int, Str, List<T>など
インタフェース→Comparable, Iterableなど
・多重継承したインタフェースで仮想でないメソッドに名前の重複があったらエラーにする
とするしかないのでは
・具象型とインタフェースを分ける
具象型→Int, Str, List<T>など
インタフェース→Comparable, Iterableなど
・多重継承したインタフェースで仮想でないメソッドに名前の重複があったらエラーにする
とするしかないのでは
113デフォルトの名無しさん
2024/03/15(金) 17:20:27.60ID:Ratd2baE 型とインタフェースは分けないと、たとえば
equal(x: Eq, y: Eq) -> bool
とか無意味になる
xとyには具体的な型が同じものが入ってほしいのに、Eqインタフェースを持っている型すべてを許容してしまう
ほんとうにやりたいのは
equal(x: T, y: T) -> bool where T: Eq
ということ
equal(x: Eq, y: Eq) -> bool
とか無意味になる
xとyには具体的な型が同じものが入ってほしいのに、Eqインタフェースを持っている型すべてを許容してしまう
ほんとうにやりたいのは
equal(x: T, y: T) -> bool where T: Eq
ということ
114デフォルトの名無しさん
2024/03/15(金) 17:33:55.76ID:UiCkupYq 型システムと並行性はむずかしいな
でも、言語がプログラマに好まれるかどうかってそんなとこにないと思うよ
一時期、高機能なタスクランナーやら単体テストフレームワークやらがたくさん出てきたけど、結局はnpm-scriptsとか言語標準のunittestライブラリに収束した
でも、言語がプログラマに好まれるかどうかってそんなとこにないと思うよ
一時期、高機能なタスクランナーやら単体テストフレームワークやらがたくさん出てきたけど、結局はnpm-scriptsとか言語標準のunittestライブラリに収束した
115デフォルトの名無しさん
2024/03/15(金) 17:40:58.53ID:UiCkupYq powershellはプログラミング言語としてはbashよりもはるかに高機能だが、誰もあれで書きたいとは思わない
116デフォルトの名無しさん
2024/03/15(金) 18:11:48.66ID:RqiZ+uh9 >>108
inheritanceを型に対して行うのが間違いな気がする
Int x Intを、Point2DとRationalのサブクラスとしたとする
Point2DとRationalの両方に + を実装(前者にはベクトルとして、後者には有理数として)したとして、
(1, 2) + (3, 4)
はどうなるか?
それは結局、今(1, 2), (3, 4)をどの型だとみなしているかによるのであって、型Int x Intの与り知らぬところだ
inheritanceを型に対して行うのが間違いな気がする
Int x Intを、Point2DとRationalのサブクラスとしたとする
Point2DとRationalの両方に + を実装(前者にはベクトルとして、後者には有理数として)したとして、
(1, 2) + (3, 4)
はどうなるか?
それは結局、今(1, 2), (3, 4)をどの型だとみなしているかによるのであって、型Int x Intの与り知らぬところだ
117デフォルトの名無しさん
2024/03/15(金) 18:25:53.61ID:C8O2+ggF >>109
Mixinで多重継承問題回避できる理屈がよくわからんかったけど、今ようやっと理解できたわ
Mixinで多重継承問題回避できる理屈がよくわからんかったけど、今ようやっと理解できたわ
118デフォルトの名無しさん
2024/03/15(金) 18:31:58.44ID:8+Y0uCh5 >>113
結局Rustのトレイト境界が正解ということか
結局Rustのトレイト境界が正解ということか
119デフォルトの名無しさん
2024/03/15(金) 19:43:07.16ID:UT4yxmsS >>109
Javaの場合は、クラスは(b)を、インタフェースは(a)を諦めている
Javaの場合は、クラスは(b)を、インタフェースは(a)を諦めている
120デフォルトの名無しさん
2024/03/15(金) 21:35:17.15ID:XzxHtHqU121デフォルトの名無しさん
2024/03/15(金) 21:53:50.95ID:WMhMrtUW まあ、でもプログラミング言語が人気になるかどうかは
>>114の言うように、処理系の完璧さではなく、実用のニーズに耐え得ることなんだろうな
>>114の言うように、処理系の完璧さではなく、実用のニーズに耐え得ることなんだろうな
122デフォルトの名無しさん
2024/03/15(金) 22:34:31.87ID:3o/QlmnN クロージャとオブジェクトが同等なのはわかったが、それよりもさらに強力な言語機能はないのか?
123デフォルトの名無しさん
2024/03/15(金) 23:30:35.88ID:rbMui8Ez 継続
プログラマが直接触らないものとしては、ガベージコレクションとかレキシカルクロージャとかもそうかもね
プログラマが直接触らないものとしては、ガベージコレクションとかレキシカルクロージャとかもそうかもね
124デフォルトの名無しさん
2024/03/16(土) 20:49:53.31ID:TBzj9DHS Eiffel、Delphi、C#なんかは菱形継承してもそれぞれに別名を与えて捌ける機能を持ってるが
オブジェクト指向自体が下火なのもあって、最近のやつはそこまで作り込まれてない感
オブジェクト指向自体が下火なのもあって、最近のやつはそこまで作り込まれてない感
125デフォルトの名無しさん
2024/03/16(土) 21:44:17.40ID:gqfrZq4+ 多重継承は名前がぶつかろうがそれ自体に問題は一切ない
抽象型から具象型への継承で実装継承でないならば区別できる限り問題は生じない
本質的な問題は実装継承であること
特にに具象型から具象型への継承が問題
これは多重かどうかに関係なく問題となる
抽象型から具象型への継承で実装継承でないならば区別できる限り問題は生じない
本質的な問題は実装継承であること
特にに具象型から具象型への継承が問題
これは多重かどうかに関係なく問題となる
126デフォルトの名無しさん
2024/03/16(土) 22:15:39.23ID:ajdJdfuW127デフォルトの名無しさん
2024/03/16(土) 22:18:29.76ID:ajdJdfuW 自然数 is a モノイド
と自然にみなす方法は2通りある
その方法は自然数の定義とは関係ない
と自然にみなす方法は2通りある
その方法は自然数の定義とは関係ない
128デフォルトの名無しさん
2024/03/16(土) 22:28:23.06ID:UqSB/mst クラスが欠陥品なのは同意だが
クラスを捨てて型クラスを使えばよい
クラスを捨てて型クラスを使えばよい
129デフォルトの名無しさん
2024/03/16(土) 22:30:52.34ID:ajdJdfuW 行列式=1の2次正方行列が、
自分の型はM(2)なのか、GL(2)なのか、SL(2)なのかなんて知らんがな
自分の型はM(2)なのか、GL(2)なのか、SL(2)なのかなんて知らんがな
130デフォルトの名無しさん
2024/03/16(土) 22:35:57.52ID:TBzj9DHS >>127の問題は型クラスやtraitでも発生するしなあ
C++で没になったconcept_mapのようなものを複数切り替えられる機能が求められる
C++で没になったconcept_mapのようなものを複数切り替えられる機能が求められる
131デフォルトの名無しさん
2024/03/19(火) 03:55:14.66ID:5WuD+qyw x: T where T: K where K: L where ...
のように高階の型や
fn(x: T) -> Type
のようにパラメータに依存する型などがいくらでも作れたらどんなことができるのだろうか
のように高階の型や
fn(x: T) -> Type
のようにパラメータに依存する型などがいくらでも作れたらどんなことができるのだろうか
132デフォルトの名無しさん
2024/03/19(火) 22:24:36.99ID:TBPz9mXO >>131
具象型Tに対して抽象型Kの制約を課すところまでは普通として
抽象型Kに対して高階抽象型Lの制約を課すメリットが見つからなかった
代替の方法として高階とせずに
抽象型Kに対して同じレベルの抽象型Lの制約を常に課す宣言ができれば十分にみえる
具象型Tに対して抽象型Kの制約を課すところまでは普通として
抽象型Kに対して高階抽象型Lの制約を課すメリットが見つからなかった
代替の方法として高階とせずに
抽象型Kに対して同じレベルの抽象型Lの制約を常に課す宣言ができれば十分にみえる
133デフォルトの名無しさん
2024/03/20(水) 17:07:37.10ID:yZelKyNv134デフォルトの名無しさん
2024/04/06(土) 13:15:05.66ID:IRVxBt67 なんでもラムダ
→なんでもオブジェクト
→なんでも型
→なんでもオブジェクト
→なんでも型
135デフォルトの名無しさん
2024/04/07(日) 01:46:27.75ID:HXZiHVf3 全称量化子は関数で
存在量化子はパターンマッチングで
表せるので、一階述語論理もラムダ式で書けそう
存在量化子はパターンマッチングで
表せるので、一階述語論理もラムダ式で書けそう
136デフォルトの名無しさん
2024/04/07(日) 05:29:44.44ID:FOjhJ4gr 書けるの意味がわからんな
書いてどうする?
カリー・ハワード対応とかチューリング完全と関係ある話か?
書いてどうする?
カリー・ハワード対応とかチューリング完全と関係ある話か?
137デフォルトの名無しさん
2024/04/07(日) 06:21:18.75ID:ZeXbAXZK 存在命題とか背理法とか、仮定を仮引数にしたラムダ式を使えば、具体的に証明や値を構成しなくても所望のものを取ってこられるんだな
138デフォルトの名無しさん
2024/04/07(日) 07:33:56.22ID:FOjhJ4gr それは理論的に不可能
139デフォルトの名無しさん
2024/04/07(日) 09:52:53.31ID:/E0pQilp res = hoge()みたいにただ結果返すのと、
hoge((res) => doSomething())みたいに引数に結果入ってくるのと、何が違うんや
hoge((res) => doSomething())みたいに引数に結果入ってくるのと、何が違うんや
140デフォルトの名無しさん
2024/04/07(日) 10:45:31.26ID:thR/d4RZ まず、hogeが同期的でない場合は
res = hoge()
とは書けない
async/awaitのような機構が必要になる
またたとえば、エラーの場合は処理を分岐させたいような場合、
hoge(
(res) => doSomething(),
(err) => handleError())
のように拡張できる
ただし、内部でさらに同じようなことをやっているとコールバック地獄になる
res = hoge()
とは書けない
async/awaitのような機構が必要になる
またたとえば、エラーの場合は処理を分岐させたいような場合、
hoge(
(res) => doSomething(),
(err) => handleError())
のように拡張できる
ただし、内部でさらに同じようなことをやっているとコールバック地獄になる
141デフォルトの名無しさん
2024/04/07(日) 11:19:43.04ID:0gYyGnNT >>134
依存型のあるHaskellやLean4はとくにオブジェクト指向という感じはしない
依存型のあるHaskellやLean4はとくにオブジェクト指向という感じはしない
142デフォルトの名無しさん
2024/04/07(日) 13:08:22.06ID:IfUr/96a >>141
純粋関数型で、(クラスベースの)オブジェクト指向をやる意味は皆無だからな
純粋関数型で、(クラスベースの)オブジェクト指向をやる意味は皆無だからな
143デフォルトの名無しさん
2024/04/07(日) 19:27:40.79ID:m+fa22Uj 純関数型言語でなくても
モダンなプログラミング言語
Go、Rust、Zig、Nim、Julia、Elixirなどは
クラスおよびその継承を言語仕様から排除しておりクラスは存在しない
それら各々の言語は全く異なる方針を採っている言語だがクラス排除だけは全てが同じ方針である
クラスとその継承は悪手であるとプログラミング言語界では結論が出ている
モダンなプログラミング言語
Go、Rust、Zig、Nim、Julia、Elixirなどは
クラスおよびその継承を言語仕様から排除しておりクラスは存在しない
それら各々の言語は全く異なる方針を採っている言語だがクラス排除だけは全てが同じ方針である
クラスとその継承は悪手であるとプログラミング言語界では結論が出ている
144デフォルトの名無しさん
2024/04/07(日) 20:16:17.84ID:mSidkHeO だからってduck typingはクラスよりさらに悪いと思うんだ
145デフォルトの名無しさん
2024/04/07(日) 20:37:39.53ID:rmfTjPEc >>144
だからクラスとダックタイピングを採用しない言語が増えているね
だからクラスとダックタイピングを採用しない言語が増えているね
146デフォルトの名無しさん
2024/04/07(日) 21:18:11.49ID:E193nq4c ポエムはよそでやれ
147デフォルトの名無しさん
2024/04/08(月) 14:29:36.32ID:LhsijIe9 P∧Qの導入則は、P -> Q -> P∧Q
これは(P, Q)ならばP∧Qとも読めるし
Pを仮定したとき、QならばP∧Qとも読める
これは(P, Q)ならばP∧Qとも読めるし
Pを仮定したとき、QならばP∧Qとも読める
148デフォルトの名無しさん
2024/04/09(火) 18:44:27.40ID:kKsSVHOb 限定継続(reset/shift)の動きが意味わかんない
resetで範囲絞ってる分call/ccより実用的には扱いやすいというのは分かるが、ローカルで見たらcall/ccのほうが直感的に思える
resetで範囲絞ってる分call/ccより実用的には扱いやすいというのは分かるが、ローカルで見たらcall/ccのほうが直感的に思える
149デフォルトの名無しさん
2024/04/09(火) 23:18:54.13ID:Aro4tJCD 実装の都合では?
フル機能の継続はそこまでのスタック全部を生かし続けないといけないし分岐できないといけないしで
スタック自体をOSの用意してくれるものとは別に自前で構成しないといけないしそうするとABIからなにからつらい
フル機能の継続はそこまでのスタック全部を生かし続けないといけないし分岐できないといけないしで
スタック自体をOSの用意してくれるものとは別に自前で構成しないといけないしそうするとABIからなにからつらい
150デフォルトの名無しさん
2024/04/10(水) 01:07:10.63ID:uPucvtCR 内部で継続渡しに変換してるなら、フルの継続のほうが実装しやすいと思うけど
Schemeの場合、dynamic-windとかも実装しなきゃいかんからより複雑だろうけど
Schemeの場合、dynamic-windとかも実装しなきゃいかんからより複雑だろうけど
151デフォルトの名無しさん
2024/04/10(水) 03:30:06.71ID:qIIVcoEj 継続渡しはスタック消費をクロージャで置き換えてるわけで、スタックを自前で用意してるのと同じようなもんでは
152デフォルトの名無しさん
2024/04/10(水) 04:04:38.17ID:nlTt4/RM 会話が噛み合ってない
153デフォルトの名無しさん
2024/04/10(水) 09:16:26.52ID:fNUeJXq8 いや割と噛み合ってる
154デフォルトの名無しさん
2024/04/10(水) 11:55:16.47ID:dXGnSmQj 処理が
A → B → C → ...
とあって
A → ... → shift(fn k -> hoge) → B → ... → C → reset
とすると
k に処理 _ → B → ... → Cが束縛される
hogeを実行するとresetまでジャンプする
resetの値はhogeの値になる
なので、たとえばバックトラックがしたいなら、
戻ってきたい場所にshiftを設置して、
fn () -> k next_valueをスタックに積んで、
クロージャの内部でk current_valueを実行すればいい
A → B → C → ...
とあって
A → ... → shift(fn k -> hoge) → B → ... → C → reset
とすると
k に処理 _ → B → ... → Cが束縛される
hogeを実行するとresetまでジャンプする
resetの値はhogeの値になる
なので、たとえばバックトラックがしたいなら、
戻ってきたい場所にshiftを設置して、
fn () -> k next_valueをスタックに積んで、
クロージャの内部でk current_valueを実行すればいい
155デフォルトの名無しさん
2024/04/10(水) 11:57:37.66ID:dXGnSmQj で、スタックから継続をpopして実行する関数を別に作って
選択肢がなくなったときはそれを呼べばいい
選択肢がなくなったときはそれを呼べばいい
156デフォルトの名無しさん
2024/04/10(水) 16:24:50.24ID:gx493tSk カプセル化を破壊するのが前提なので、ものすごく気を遣う
157デフォルトの名無しさん
2024/04/10(水) 17:47:04.13ID:uxnW16Zl call/ccやreset/shiftの型はどうなるの?
158デフォルトの名無しさん
2024/11/11(月) 12:09:40.22ID:eaS0ivay call/ccの型は
((T -> ⊥) -> T) -> T
これは、¬Tを仮定してTが導けるならTということ
つまり、直観主義論理に排中律を追加することに相当する
((T -> ⊥) -> T) -> T
これは、¬Tを仮定してTが導けるならTということ
つまり、直観主義論理に排中律を追加することに相当する
159デフォルトの名無しさん
2024/11/28(木) 14:50:39.31ID:D62ASfXP first-class typeがあると、どのような抽象化が可能になるのか
160デフォルトの名無しさん
2024/11/28(木) 21:23:23.02ID:tgeVSyIQ output_integer = input_string.filter(is_number).map(char_to_integer).sum()
161デフォルトの名無しさん
2024/11/28(木) 22:26:33.20ID:U97loGz8 何かしらんけどHaskell版
import Data.Char
outputInteger = getLine >>= return.sum.map digitToInt.filter isDigit
f = outputInteger >>= putStrLn.("sum = " ++).show -- IOな値は必ず >>= 経由で渡される。
>f
1a2b3
>sum = 6
do表記
f = do x <- outputInteger -- IOな値は必ず <- で束縛された変数経由で渡される。
putStrLn $ "sum = " ++ show x
import Data.Char
outputInteger = getLine >>= return.sum.map digitToInt.filter isDigit
f = outputInteger >>= putStrLn.("sum = " ++).show -- IOな値は必ず >>= 経由で渡される。
>f
1a2b3
>sum = 6
do表記
f = do x <- outputInteger -- IOな値は必ず <- で束縛された変数経由で渡される。
putStrLn $ "sum = " ++ show x
162デフォルトの名無しさん
2024/11/28(木) 22:37:38.47ID:iYyun2JN 代入をなくそう
n = 1ではなく
n: 1 (nは1である)
n: Nat (nは自然数である)
これを基礎とする
n = 1ではなく
n: 1 (nは1である)
n: Nat (nは自然数である)
これを基礎とする
163デフォルトの名無しさん
2024/11/28(木) 22:39:47.41ID:iYyun2JN こうすればパターンマッチなどに統一性がとれるだろう
164デフォルトの名無しさん
2024/11/28(木) 22:59:50.27ID:U97loGz8 map digitToInt だと"1 2 3" = [1, 2, 3] は良いとして、"123" = [1, 2, 3] と1桁ずつになるので改良した
outputInteger = getLine >>= return.sum.map (read.filter isDigit).words
> f
11 22 33 -- Input
sum = 66
> f
1a1 22b k33 -- Input
sum = 66
outputInteger = getLine >>= return.sum.map (read.filter isDigit).words
> f
11 22 33 -- Input
sum = 66
> f
1a1 22b k33 -- Input
sum = 66
165デフォルトの名無しさん
2024/11/29(金) 08:50:35.19ID:ZHbjuyaH よそでやれ
166デフォルトの名無しさん
2024/11/29(金) 18:22:51.77ID:FvJq/OMC167デフォルトの名無しさん
2024/11/29(金) 18:26:10.93ID:FXP1+9fo 具体的なデータ(1とか"Hello"とか)があれば、型が決まるわけでもない
たとえば、、1 + 1は加法モノイドとみれば2だけど、乗法モノイドとみれば1
ただ、前者とみなす慣習が圧倒的に多いに過ぎない
たとえば、、1 + 1は加法モノイドとみれば2だけど、乗法モノイドとみれば1
ただ、前者とみなす慣習が圧倒的に多いに過ぎない
168デフォルトの名無しさん
2024/11/29(金) 19:14:30.73ID:lZOQa9Jb 具体型をなくして抽象型だけにするのは?
169デフォルトの名無しさん
2024/12/12(木) 18:30:39.23ID:XExKLUf8 Leanでは、Exists(fun x: A => p x)は長いから∃x: A, p xと書くらしいので、ラムダ式のシンタックスはさらに短くなる
170デフォルトの名無しさん
2024/12/12(木) 20:50:14.10ID:YVpGcPfJ 命題は型
171デフォルトの名無しさん
2024/12/12(木) 22:51:28.02ID:dX7jmuEY >>144
duck typingもクラスも使わずにinterfaceを使うのが正解
duck typingもクラスも使わずにinterfaceを使うのが正解
172デフォルトの名無しさん
2024/12/13(金) 13:33:11.56ID:ObbUHrIh クラスのフィールドは全く不要な概念
173デフォルトの名無しさん
2024/12/13(金) 21:23:08.37ID:ePsQGGMZ クラス自体が不要
クラスを排除したモダンなプログラミング言語が多数あることが何よりの証拠
クラスを排除したモダンなプログラミング言語が多数あることが何よりの証拠
174デフォルトの名無しさん
2024/12/19(木) 16:09:31.78ID:RMYWDOZr クロージャ指向から述語指向へ
175デフォルトの名無しさん
2024/12/25(水) 16:41:01.48ID:jsf4a+Fl 継続指向プログラミング
176デフォルトの名無しさん
2024/12/28(土) 22:32:57.19ID:U3Qq1irw T :: ((α -> β) -> α -> (_ -> (_, β)), _ -> _)
T = (S, R)
f :: α -> β
S f :: α -> (_ -> (_, β))
S f a = fn x: (R x, f a)
f :: α -> β, g :: β -> γ
S f :: α -> (_ -> (_, β))
S g :: β -> (_ -> (_, γ))
S g >>= S f a = fn x:
let
(x', b) = S f a x
in
(R x', g b)
T = (S, R)
f :: α -> β
S f :: α -> (_ -> (_, β))
S f a = fn x: (R x, f a)
f :: α -> β, g :: β -> γ
S f :: α -> (_ -> (_, β))
S g :: β -> (_ -> (_, γ))
S g >>= S f a = fn x:
let
(x', b) = S f a x
in
(R x', g b)
177デフォルトの名無しさん
2024/12/29(日) 01:19:32.44ID:OIeguool Category theory for programmers読む
178デフォルトの名無しさん
2025/02/04(火) 01:03:51.46ID:63k9bOfa プログラムのすべての箇所で値が(val: a, cont: a -> r)みたいになってたら、
独立したコンテキスト間で状態を受け渡ししなきゃいけないような仕様変更があっても、
その状態を参照できる所の(state, cont1)をセーブポイントとして保存
で、その状態を共有したい所の(val, cont2)を保存してcont1を呼び出す
stateとvalから新しいvalを作ってcont2を呼び出す
とやればいいのか
独立したコンテキスト間で状態を受け渡ししなきゃいけないような仕様変更があっても、
その状態を参照できる所の(state, cont1)をセーブポイントとして保存
で、その状態を共有したい所の(val, cont2)を保存してcont1を呼び出す
stateとvalから新しいvalを作ってcont2を呼び出す
とやればいいのか
179デフォルトの名無しさん
2025/02/04(火) 01:47:21.80ID:Juhgqulp 絶対にやめろ
180デフォルトの名無しさん
2025/02/04(火) 22:33:26.11ID:W8jOB2Il >>178
それクロージャと言う
それクロージャと言う
181デフォルトの名無しさん
2025/02/05(水) 00:00:43.61ID:ZsEHWtVQ 違うが
182デフォルトの名無しさん
2025/02/05(水) 18:33:33.62ID:UzNcF0as 継続は米田埋込み
C^op → (Set)^C
型は層
C^op→(Set)
任意の圏は米田埋込みで前層の圏に埋め込める
C→(Set)^(C^op)
C^op → (Set)^C
型は層
C^op→(Set)
任意の圏は米田埋込みで前層の圏に埋め込める
C→(Set)^(C^op)
183デフォルトの名無しさん
2025/02/05(水) 18:46:54.22ID:UvjLK8GW 継続渡しへの変換は米田埋込み、な。
a: Aの代わりに、ka: (A -> R) -> Rを考える。
a: Aの代わりに、ka: (A -> R) -> Rを考える。
184デフォルトの名無しさん
2025/02/05(水) 18:51:06.97ID:2vUp1NTh 継続渡しやコールバックは
全て高位関数としてクロージャを渡すことで統一化されている
クロージャだけを考えればよくなっている
全て高位関数としてクロージャを渡すことで統一化されている
クロージャだけを考えればよくなっている
185デフォルトの名無しさん
2025/02/05(水) 19:16:41.69ID:Osi5eBbZ まあ、型Aのオブジェクトaを考える代わりに、A上の関数にaを適用する関数を考えるわけだから、そりゃたしかにそうだな
186デフォルトの名無しさん
2025/02/05(水) 22:52:10.46ID:95phW+lE ```
callcc: ((α -> β**) -> α**) -> α**
callcc f = fun (k: α*) => f (fun (x: α) => (fun (_: β) => k x)) k
```
callcc: ((α -> β**) -> α**) -> α**
callcc f = fun (k: α*) => f (fun (x: α) => (fun (_: β) => k x)) k
```
187デフォルトの名無しさん
2025/02/07(金) 22:18:25.29ID:c5jjIiZy 動的に生成される型として、たとえば型 `t`をパラメータにとって、あるコンテナ内 `t` 型のフィールドの一意性を保証する型 `Unique t ` とかを考えてみる
188デフォルトの名無しさん
2025/02/07(金) 22:49:12.48ID:OiS9SGfZ 依存型なら、それもできる
189デフォルトの名無しさん
2025/02/20(木) 01:49:56.71ID:fXOi/Bb7 [0 1]
|> iterate ([a b] -> [b (a + b)])
|> map first
|> head 20
|> iterate ([a b] -> [b (a + b)])
|> map first
|> head 20
190デフォルトの名無しさん
2025/02/20(木) 23:57:19.54ID:zXVkJcm2 >>187
その型を動的生成する必要性が全く感じられない
そして制約を受けるのはコンテナ側
例えば代入やプッシュが一意性を満たしているかどうかで成功と失敗に分かれるインターフェースとなる
つまりコンテナ側の制約導入拡張型となるのではないか
その型を動的生成する必要性が全く感じられない
そして制約を受けるのはコンテナ側
例えば代入やプッシュが一意性を満たしているかどうかで成功と失敗に分かれるインターフェースとなる
つまりコンテナ側の制約導入拡張型となるのではないか
191デフォルトの名無しさん
2025/02/21(金) 09:55:06.25ID:Ip3jb1gD >>190
> 必要性が全く感じられない
データベースのフィールドの一意性制約、ハッシュテーブルのキーの一意性など、いくらでもあると思うが
> 制約を受けるのはコンテナ側
意味的には当然、コンテナも値もともに制約を受けている
メソッドが名前空間に属しているのか、オブジェクトに属しているのかと変わらない
それをどう管理するのかは処理系の実装の問題
> 必要性が全く感じられない
データベースのフィールドの一意性制約、ハッシュテーブルのキーの一意性など、いくらでもあると思うが
> 制約を受けるのはコンテナ側
意味的には当然、コンテナも値もともに制約を受けている
メソッドが名前空間に属しているのか、オブジェクトに属しているのかと変わらない
それをどう管理するのかは処理系の実装の問題
192デフォルトの名無しさん
2025/02/21(金) 19:25:08.97ID:NlF3aFif 「クロージャを引数にとってクロージャを返すクロージャ」を引数にとって「クロージャを引数にとってクロージャを返すクロージャ」を返すクロージャ
193デフォルトの名無しさん
2025/02/21(金) 20:11:13.15ID:lKEY3ckS make-stream head thunk := [cont] -> cont head thunk
head stream := stream ([head _] -> head)
rest stream := stream ([_ thunk] -> thunk [])
nat-from n := make-stream n ([] -> nat-from (n+1))
take 0 stream := []
take _ [] := []
take n stream := cons (head stream) (take (n-1) (rest stream))
head stream := stream ([head _] -> head)
rest stream := stream ([_ thunk] -> thunk [])
nat-from n := make-stream n ([] -> nat-from (n+1))
take 0 stream := []
take _ [] := []
take n stream := cons (head stream) (take (n-1) (rest stream))
194デフォルトの名無しさん
2025/02/21(金) 23:53:10.97ID:zYI+C5dr >>191
必要性は当然わかってる
しかし動的生成する必要性が全く感じられない
一般的に型は静的に扱えるなら静的に扱える方が有利
もう一つ
コンテナも制約を受けるとわかっているならなぜそちらも型パラメータにしないのか?
フィールド 't' だけを型パラメータにしていることを問題視している
必要性は当然わかってる
しかし動的生成する必要性が全く感じられない
一般的に型は静的に扱えるなら静的に扱える方が有利
もう一つ
コンテナも制約を受けるとわかっているならなぜそちらも型パラメータにしないのか?
フィールド 't' だけを型パラメータにしていることを問題視している
195デフォルトの名無しさん
2025/02/22(土) 00:16:39.92ID:2igDN88l >>194
>一般的に型は静的に扱えるなら静的に扱える方が有利
コンパイル時に検査できるものはすればいい
>コンテナも制約を受けるとわかっているならなぜそちらも型パラメータにしないのか?
>フィールド 't' だけを型パラメータにしていることを問題視している
コンテナが制約を受けるのか値が制約を受けるのかは、単に構文と処理系の実装の問題。意味的にはどちらも制約を受ける
変数aの型によって動作が変わる関数を、a.foo()と書く仕様にしようがfoo(a)にしようがどちらでもいいのと同じ
というか「必要性がわからない」なら、首を突っ込まなきゃいいのでは
>一般的に型は静的に扱えるなら静的に扱える方が有利
コンパイル時に検査できるものはすればいい
>コンテナも制約を受けるとわかっているならなぜそちらも型パラメータにしないのか?
>フィールド 't' だけを型パラメータにしていることを問題視している
コンテナが制約を受けるのか値が制約を受けるのかは、単に構文と処理系の実装の問題。意味的にはどちらも制約を受ける
変数aの型によって動作が変わる関数を、a.foo()と書く仕様にしようがfoo(a)にしようがどちらでもいいのと同じ
というか「必要性がわからない」なら、首を突っ込まなきゃいいのでは
196デフォルトの名無しさん
2025/02/22(土) 00:26:40.81ID:2igDN88l >コンテナも制約を受けるとわかっているならなぜそちらも型パラメータにしないのか?
あなたがそうしたけりゃそうすりゃいいだけの話
「集合Gは群であるとする」といっている人に対して、
「群構造は二項演算*、単位元e、逆演算・^(-1)にも依存するのに、なぜ(G, *, e, ・^(-1))と書かないのか」とか言っているようなもん
そう書きたきゃそう書けばいい
俺はめんどくさいからそうしないだけ
あなたがそうしたけりゃそうすりゃいいだけの話
「集合Gは群であるとする」といっている人に対して、
「群構造は二項演算*、単位元e、逆演算・^(-1)にも依存するのに、なぜ(G, *, e, ・^(-1))と書かないのか」とか言っているようなもん
そう書きたきゃそう書けばいい
俺はめんどくさいからそうしないだけ
197デフォルトの名無しさん
2025/02/22(土) 00:28:08.00ID:BHZ6xlR+ バカだから不利となる動的生成しようとしてるのだろう
そのケースは静的で済む
そのケースは静的で済む
198デフォルトの名無しさん
2025/02/22(土) 00:31:03.33ID:2igDN88l199デフォルトの名無しさん
2025/02/22(土) 00:34:02.62ID:2igDN88l 型を動的に生成する、つまり実行時に決まる値に型が依存していても、コンパイル時に検査できる場合はある
ということが分かっていない?
ということが分かっていない?
200デフォルトの名無しさん
2025/02/22(土) 00:36:50.14ID:fju1Vmb5201デフォルトの名無しさん
2025/02/22(土) 00:37:58.92ID:2igDN88l たとえばList nで長さnのリストを表すとする
nが実行時に決まる値だったとしても、関数
concat: List n -> List m -> List (n + m)
の型はコンパイル時にチェックできる
nが実行時に決まる値だったとしても、関数
concat: List n -> List m -> List (n + m)
の型はコンパイル時にチェックできる
202デフォルトの名無しさん
2025/02/22(土) 00:39:25.47ID:2igDN88l203デフォルトの名無しさん
2025/02/22(土) 00:42:20.87ID:fju1Vmb5204デフォルトの名無しさん
2025/02/22(土) 00:45:02.92ID:2igDN88l 正直、あなたの意図がよくわからない
こちらの言っていることが理解できないのか、わざわざこんな辺鄙なスレでよく分からん難癖をつけるのが楽しいのか
こちらの言っていることが理解できないのか、わざわざこんな辺鄙なスレでよく分からん難癖をつけるのが楽しいのか
205デフォルトの名無しさん
2025/02/22(土) 13:49:24.39ID:3Aku5oEk 型を動的に作るなんて、RailsのActiveRecordとかごく一般的に行われていることだと思うが
206デフォルトの名無しさん
2025/02/22(土) 14:03:06.41ID:o5bbno7I207デフォルトの名無しさん
2025/02/22(土) 14:54:10.02ID:H7FLchaf208デフォルトの名無しさん
2025/02/22(土) 15:46:05.77ID:IIYOJqnw 言語のセマンティクスと実装は分けて考えるべき
209デフォルトの名無しさん
2025/02/22(土) 15:57:38.39ID:es3U9V0K >>207
あなたが混同してる
型検査をコンパイル時に行うかどうかは規格、セマンティクスの領分で
実行時の値とされているものを静的にチェックできる範囲でチェックして警告を出したりするのは実装の領分だろう
あなたが混同してる
型検査をコンパイル時に行うかどうかは規格、セマンティクスの領分で
実行時の値とされているものを静的にチェックできる範囲でチェックして警告を出したりするのは実装の領分だろう
210デフォルトの名無しさん
2025/02/22(土) 16:05:21.30ID:W3fSq5/I >>207
その両者は明確に分かれてる
動的型付け言語は実行の途中で初めて型が確定しうる
静的型付け言語は必ず実行前に全ての型が定まる
これらは言語仕様で定まる
静的型付け言語は型の安全性やパフォーマンスに優れている
C/C++, Fortran, Go, Haskell, Java, OCaml, Pascal, Rust, Scala, Swiftなど
スクリプト言語以外は静的型付け言語が多数派
その両者は明確に分かれてる
動的型付け言語は実行の途中で初めて型が確定しうる
静的型付け言語は必ず実行前に全ての型が定まる
これらは言語仕様で定まる
静的型付け言語は型の安全性やパフォーマンスに優れている
C/C++, Fortran, Go, Haskell, Java, OCaml, Pascal, Rust, Scala, Swiftなど
スクリプト言語以外は静的型付け言語が多数派
211デフォルトの名無しさん
2025/02/22(土) 16:35:21.85ID:N/T45y64212デフォルトの名無しさん
2025/02/22(土) 16:51:46.18ID:1JZL08Pv もうブログかなんかに書いててくれないか
213デフォルトの名無しさん
2025/02/22(土) 16:53:22.31ID:W3fSq5/I 静的型付け言語はその言語仕様により
常に全ての型を静的に(=実行前に)確定できる
これは言語仕様により定まることであり実装とは関係ない
常に全ての型を静的に(=実行前に)確定できる
これは言語仕様により定まることであり実装とは関係ない
214デフォルトの名無しさん
2025/02/22(土) 16:54:54.90ID:1JZL08Pv 妄想乙
215デフォルトの名無しさん
2025/02/22(土) 17:46:21.34ID:GOJ2wF4D 実行速度の速い言語がすべて静的型付けな点が答えだろうね
素人向けのスクリプト言語は動的型付けで遅い
素人向けのスクリプト言語は動的型付けで遅い
216デフォルトの名無しさん
2025/02/22(土) 18:03:51.25ID:NU7N7MY+ >>210
しれっとHaskell混ぜるなってのw
しれっとHaskell混ぜるなってのw
217デフォルトの名無しさん
2025/02/22(土) 19:31:02.81ID:wKCHVlKT 馬鹿が常駐して終わったスレ
さよなら
さよなら
218デフォルトの名無しさん
2025/02/22(土) 20:19:25.50ID:FTk8qZlg 無意味な動的型付けにこだわってるのは一人だけだから無視すればよいだけかと
型推論の進歩により静的型付けの唯一の弱点も消えた
型指定を省略できるクロージャなどその典型例
型推論の進歩により静的型付けの唯一の弱点も消えた
型指定を省略できるクロージャなどその典型例
219デフォルトの名無しさん
2025/02/22(土) 22:50:21.56ID:bh0ZAEWN220デフォルトの名無しさん
2025/02/22(土) 22:56:32.72ID:bh0ZAEWN >>187は動的型付けとは何ら関係がない
むしろ、直後に指摘されているようにほとんどのケースでコンパイル前に検査できる
むしろ、直後に指摘されているようにほとんどのケースでコンパイル前に検査できる
221デフォルトの名無しさん
2025/02/23(日) 02:25:36.50ID:tIjZB/Ol 型が第一級オブジェクトの言語は、論理学でいえば命題を量化できる二階述語論理に相当するわけだ
222デフォルトの名無しさん
2025/02/23(日) 03:10:06.06ID:ojjdIlYs f x = 10
g y = 20
h z = 30
h . g . f 10 -- 30
g y = 20
h z = 30
h . g . f 10 -- 30
223デフォルトの名無しさん
2025/02/23(日) 03:10:58.23ID:ojjdIlYs hの定義内で途中の計算結果10, 10, 20を参照するにはどうするか
224デフォルトの名無しさん
2025/02/23(日) 04:40:15.50ID:upqukZrZ トランポリン
225デフォルトの名無しさん
2025/02/23(日) 06:54:06.73ID:jtLYghc/ h z x y = 30にする
226デフォルトの名無しさん
2025/03/09(日) 23:01:10.03ID:eGDnXODc227デフォルトの名無しさん
2025/03/14(金) 17:25:51.81ID:TOg9uiCJ S式
(+ 1 (* 2 3))
RPN
1 2 3 * +
CPS
1 >> (x ->
2 >> (y ->
3 >> (z ->
(y * z) >> (m ->
(x + m))))))
Do記法
x <- 1
y <- 2
z <- 3
m <- y * z
x + m
(+ 1 (* 2 3))
RPN
1 2 3 * +
CPS
1 >> (x ->
2 >> (y ->
3 >> (z ->
(y * z) >> (m ->
(x + m))))))
Do記法
x <- 1
y <- 2
z <- 3
m <- y * z
x + m
228デフォルトの名無しさん
2025/06/17(火) 21:17:24.66ID:66zQf9l5 はぁ? クロージャって何すか?
クローゼットのことですか?
プログラマ「もういい」
クローゼットのことですか?
プログラマ「もういい」
レスを投稿する
ニュース
- 習政権、高市首相への態度硬化 台湾有事発言で連日非難 中国 ★11 [ぐれ★]
- 日本損失1.7兆円に修正 中国渡航自粛の影響試算 [蚤の市★]
- 国内ホテル、既にキャンセルも 訪日客関連業界、事態見守る ★3 [蚤の市★]
- 「どうしようもない」 ため息つくアジアの玄関口 中国の訪日自粛で−福岡市 [蚤の市★]
- 「アベノミクス」で投資対象と化したマンション ローンの低金利続き「年収の12倍」借りる20代出現 [蚤の市★]
- 橋下徹氏 外務省幹部の訪中受け「口だけ番長」へ痛烈指摘 「喧嘩は日本の完敗…なんとかっこ悪い日本か」 [冬月記者★]
- 【実況】博衣こよりのえちえち朝こよ🧪 ★2
- 【!?】高市早苗「靖国神社電撃参拝プラン」浮上!これもう戦争だろ… [481941988]
- 【実況】博衣こよりのえちえち朝こよ🧪
- カカロット、腰痛い
- 【超悲報】中国への武力行使、世論調査で「賛成」「どちらかといえば賛成」48.8% 「反対」「どちらかといえば反対」の44.2%を上回る [314039747]
- 中国「高市が頭を下げて謝罪しない限り、絶対に許さない」 [329329848]
