次の処理を色んな言語1で書いてみた。2言語ごとに特徴が出てて面白かったです。
「range的な関数で作った1
から始まる数列を、join的な関数で,
区切りでくっつける。」
スクリプト言語
perl
# perl 5, version 18, subversion 2 (v5.18.2)
# 終端を含む
print(join(",", (1..10)), "\n")
# => 1,2,3,4,5,6,7,8,9,10
php
# PHP 7.0.6
# 終端を含む
echo join(",", range(1, 10)), "\n";
# => 1,2,3,4,5,6,7,8,9,10
-
join
関数はimplode
関数のエイリアスなので、implode(",", range(1, 10));
でもOK。
ruby
# ruby 2.2.3
# 終端を含まない
puts (1...10).map(&:to_s).join(",")
# => 1,2,3,4,5,6,7,8,9
# 終端を含む
puts (1..10).map(&:to_s).join(",")
# => 1,2,3,4,5,6,7,8,9,10
-
..
と...
がどっちがどっちかいつも不安になる。
python
# Python 3.5.1
# 終端を含まない
print(",".join(map(str, range(1, 10))))
# => 1,2,3,4,5,6,7,8,9
- 2系の場合、そのままだと上記の
print
関数はエラーになる。from __future__ import print_function
しておけば動く。 - 3系の
range
関数の実装は、2系だとxrange
関数のほうが近いらしい。これらは遅延評価されるが、2系range
関数はその範囲の値を全て最初にメモリに展開するようです。
javascript
// node v6.2.1
s1 = [...Array(10).keys()].map(n => n+1).join(',');
console.log(s1);
//=> 1,2,3,4,5,6,7,8,9,10
s2 = Array.from(Array(10).keys()).map(n => n+1).join(',')
console.log(s2);
//=> 1,2,3,4,5,6,7,8,9,10
// 終端を含まない by Underscore.js
s3 = _.range(1, 10).join(',');
console.log(s3);
//=> 1,2,3,4,5,6,7,8,9
// 終端を含まない by immutable-js
s4 = Immutable.Range(1, 10).toArray().join(',');
console.log(s4);
//=> 1,2,3,4,5,6,7,8,9
- 素のJSで
1
から始まるrangeを直接取得する方法が分からなかった。。
JVM言語
java
package jp.sample;
import java.util.stream.IntStream;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) throws Exception {
// 終端を含まない
String s1 = String.join(",", IntStream.range(1, 10).boxed().map(n -> n.toString()).collect(Collectors.toList()));
System.out.println(s1);
//=> 1,2,3,4,5,6,7,8,9
// 終端を含む
String s2 = String.join(",", IntStream.rangeClosed(1, 10).boxed().map(n -> n.toString()).collect(Collectors.toList()));
System.out.println(s2);
//=> 1,2,3,4,5,6,7,8,9,10
}
}
scala
// Scala 2.10.6
// 終端を含まない (1)
println(Range(1, 10).mkString(","))
//=> 1,2,3,4,5,6,7,8,9
// 終端を含まない (2)
println((1 until 10).mkString(","))
//=> 1,2,3,4,5,6,7,8,9
// 終端を含む
println((1 to 10).mkString(","))
//=> 1,2,3,4,5,6,7,8,9,10
clojure
; Clojure 1.8.0
(require '[clojure.string :refer [join]])
; 終端を含まない (1)
(println (join \, (range 1 10)))
;=> 1,2,3,4,5,6,7,8,9
; 終端を含まない (2) スレッディングマクロ
(->> 10 (range 1) (join \,) println)
;=> 1,2,3,4,5,6,7,8,9
CLR言語
c-sharp
// mono-3.2.8.0 (C#5, CLI4.5)
public class Hello{
public static void Main(){
// 終端を含む
System.Console.WriteLine(string.Join(",", System.Linq.Enumerable.Range(1, 10)));
//=> 1,2,3,4,5,6,7,8,9,10
}
}
f-sharp
// F# 3.0 (Open Source Edition) / mono-3.2.8.0
// 終端を含む
System.Console.WriteLine([1..10] |> List.map (fun n -> n.ToString()) |> String.concat ",")
//=> 1,2,3,4,5,6,7,8,9,10
システムプログラミング言語
rust
// rustc 1.8.0
fn main() {
// 終端を含まない
let s: String = (1..10).map(|n| n.to_string()).collect::<Vec<String>>().join(",");
println!("{}", s)
//=> 1,2,3,4,5,6,7,8,9
}
go
// go 1.4.2
package main
import (
"fmt"
"strings"
"strconv"
)
func main(){
var a []string = make([]string, 10)
for i := 0; i < 10; i++ {
a[i] = strconv.Itoa(i+1)
}
fmt.Println(strings.Join(a, ","))
//=> 1,2,3,4,5,6,7,8,9,10
}
- rangeを直接作る方法は見つけられなかった。。
その他
swift
// Swift version 2.2
// 終端を含まない
print((1..<10).map { n in String(n) }.joinWithSeparator(","))
//=> 1,2,3,4,5,6,7,8,9
// 終端を含む
print((1...10).map { n in String(n) }.joinWithSeparator(","))
//=> 1,2,3,4,5,6,7,8,9,10
haskell
-- GHCi, version 7.10.3
-- 終端を含まない (1)
putStrLn (intercalate "," (map (\n -> show n) [1..10]))
-- => 1,2,3,4,5,6,7,8,9
-- 終端を含まない (2) リスト内包
putStrLn (intercalate "," [show n | n <- [1..10]])
-- => 1,2,3,4,5,6,7,8,9
shell
# zsh version 5.0.8
# 終端を含む
a=`seq -s"," 1 10` && echo ${a%,}
# => 1,2,3,4,5,6,7,8,9,10
- 変数
a
を使っているので、なんとなく他とやり方が違う感じがあるが、自分にはここまでしか分からなかった。 - shellはまだまだやり方がたくさんありそう。
まとめ
メソッドをチェーンして書ける言語はどれもだいたい同じ感じになった。
rangeオブジェクトみたいなのを直接作れる言語の場合、要素の型がだいたい数値になると思うけど、それを文字列に変換(map)する一手間がある言語とない言語と。強い型付け/弱い型付けの違い以外にjoin
的関数が内部でtoString()
的処理をするように実装してるかどうかの違いも関わってくる。
..
とか...
で作られるrangeオブジェクトに終端の数値が含まれるかどうかが、言語によってまちまち。覚えるのの諦めがついた。
ScalaのmkString
は各言語のjoin
的関数の上位互換だと思う。とても便利。
参考
- perl
- javascript
- python
- scala
- go
- c++
- swift
- c#
- f#
- Ranges A to B where A > B in F# - Stack Overflow
- f# interactive - F#: String.Join and |> operator - Stack Overflow
- F#の文字列操作関数を調べてみた - komorebikoboshiのブログ
- [http://stackoverflow.com/questions/12202626/int-and-string-f](Int and String F# - Stack Overflow)