読者です 読者をやめる 読者になる 読者になる

Cyanのリスト操作

リテラルのリストの操作は色々短く書けてよさげ。
Lispとの対応

  • [a | b] -> (a . b)
  • [a, b] -> (a b)
  • [*a, b] -> `(,@a b)

*(Expander)が便利。

cyan> a=[1,2,3]
 => [1, 2, 3]
cyan> [0|a]
 => [0, 1, 2, 3]
cyan> [*a,4]
 => [1, 2, 3, 4]
cyan> b=a.map^(n):n+4
 => [5, 6, 7]
cyan> [0,*a,4|b]
 => [0, 1, 2, 3, 4, 5, 6, 7]

+演算子がないのはちょっと不便。でも自分で書いてしまえば。

cyan> a+b
(stdin):2: error: invalid message for [1, 2, 3]: (+)
cyan> def(List.(+))^(l):[*self|l]
 => ^(self, l){ [*self | l] }
cyan> a+[4]+b+[]+[8]+9
 => [1, 2, 3, 4, 5, 6, 7, 8 | 9]
cyan> iota(4,[],'[a,b])
 => [[], [a, b], [a, b, a, b], [a, b, a, b, a, b]]

標準でfilterはあるけど、removepartitionがないのでゴルフ風味で書いてみる。

[].remove=^(_,p):[]
def(List.remove)^(p):
 $(x,r):=&(.car(),.cdr().remove(p))
 p(x)&&r||[x|r]

[].partition=^(_,p):&([],[])
def(List.partition)^(p):
 $(x,a,b):=&(.car(),*.cdr().partition(p))
 p(x)&&&([x|a],b)||&(a,[x|b])

partitionを使ってquicksort

[].qsort=^(_,f):[]
def(List.qsort)^(f):
 x:=.car()
 $(l,r):=.cdr().partition^(n):f n,x
 [*l.qsort(f),x|r.qsort(f)]
cyan> iota(20).remove^(n):n.rem(3)>0
 => [0, 3, 6, 9, 12, 15, 18, 19]
cyan> iota(10).partition^(n):n.rem(2)==0
 => &([0, 2, 4, 6, 8], [1, 3, 5, 7, 9])
cyan> [2, 5, 1, 32, 5, 10].qsort^(x, y){ x < y }
 => [1, 2, 5, 5, 10, 32]

quicksortが1,2行で書けないとブレイクできないらしいけど、Cyanのリスト表記は好きだなー。