Help us understand the problem. What is going on with this article?

Perl6 と Python3 の基本的な文法を並べてみる

More than 3 years have passed since last update.

こんにちは:whale2:
Perl 6 Advent Calendar 2016の7日目です。
昨日は @titsuki さんの 「初めてのInline::Perl5」でした。1

今日は、他の言語の人にPerl6を知ってもらおうという気持ちで、基本的な文法について Python3 と Perl6 を並べてみたいと思います。2

環境情報

# Mac のバージョン
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.12.1
BuildVersion:   16B2555
# Perl6 のバージョン
$ perl6 -v
This is Rakudo version 2016.11 built on MoarVM version 2016.11
implementing Perl 6.c.
# Python3 のバージョン
$ python3 --version
Python 3.5.1 :: Anaconda 4.1.0 (x86_64)

算術計算

Python3
print(1 - 2) #=> -1
print(4 * 5) #=> 20
print(7 / 5) #=> 1.4
print(3 ** 2) #=> 9
Perl6
use v6;
say 1 - 2 ; #=> -1
say 4 * 5 ; #=> 20
say 7 / 5 ; #=> 1.4
say 3 ** 2 ; #=> 9

セミコロン(;)の前に半角スペースを入れているのは趣味です。

データ型

の調べ方

Python3
print(type(10)) #=> <class 'int'>
print(type(2.718)) #=> <class 'float'>
print(type("hello")) #=> <class 'float'>
Perl6
use v6;
say 10.WHAT ; #=> (Int)
say 2.718.WHAT ; #=> (Rat)
say "hello".WHAT ; #=> (Str)

10.^name.say ; #=> Int
2.718.^name.say ; #=> Rat
"hello".^name.say ; #=> Str

WHAT(直球)

変数

動的型付け

Python3
# 初期化
x = 10
y = 3.14
print('%d is %s.' % (x, type(x))) #=> 10 is <class 'int'>.

# 代入
x = x * y
print('%.1f is %s.' % (x, type(x))) #=> 31.4 is <class 'float'>.

Perl6では1つの値が入る変数(スカラー変数)の先頭には$を付けます。

Perl6
use v6;
# 初期化
my $x = 10 ;
my $y = 3.14 ;
say $x ~ ' is ' ~ $x.^name ~ '.' ; #=> 10 is Int.

# 代入
$x = $x * $y ;
say sprintf '%.1f is %s.', $x, $x.^name ; #=> 31.4 is Rat.

Perl6は静的型付けもできます

Perl6
use v6;
# 型を指定して初期化
my Int $x = 10 ;
my Rat $y = 3.14 ;

# Int型の$xへのRat型の値代入はエラーになる
# $x = $x * $y ;

# Int型にすれば代入できる
$x = ($x * $y).Int ;
say $x ~ ' is ' ~ $x.^name ~ '.' ; #=> 31 is Int.

Perl5 では . を使っていた文字列連結が、Perl6 では ~ を使うようになりました。

リスト

Python3
# リストの作成
a = [1, 2, 3, 4, 5]

# リストの中身を出力する
print(a) #=> [1, 2, 3, 4, 5]

# リストの長さを取得
print(len(a)) #=> 5

# 先頭の要素にアクセス
print(a[0]) #=> 1

# 末尾の要素にアクセス
print(a[-1]) #=> 5

# 値を代入
a[4] = 99
print(a) #=> [1, 2, 3, 4, 99]

# インデックスの0番目から2つ取得
print(a[0:2]) #=> [1, 2]

# インデックスの1番目から最後まで取得
print(a[1:]) #=> [2, 3, 4, 99]

# インデックスの最初から3つ取得
print(a[:3]) #=> [1, 2, 3]

# 最初から、最後の要素の1つ前まで取得
print(a[:-1]) #=> [1, 2, 3, 4]

Perl6では配列の変数の先頭には@を付けます。

Perl6
use v6;
# 配列の作成
my Int @a = < 1 2 3 4 5 > ;

# 配列の中身を出力する
say @a ; #=> [1 2 3 4 5]

# 配列の長さを取得
say @a.elems ; #=> 5

# 先頭の要素にアクセス
say @a[0] ; #=> 1

# 末尾の要素にアクセス
say @a[*-1] ; #=> 5

# 値を代入
@a[4] = 99 ;
@a.say ; #=> [1 2 3 4 99]

# インデックスの0番目から2つ取得
say @a.head(2).Array ; #=> [1 2]

# インデックスの1番目から最後まで取得
say @a[1..*].Array ; #=> [2 3 4 99]

# インデックスの最初から3つ取得
say @a.head(3).Array ; #=> [1 2 3]
say @a[^3].Array ; #=> [1 2 3]

# 最初から、最後の要素の1つ前まで取得
say @a[0..^*-1].Array ; #=> [1 2 3 4]
say @a[0..*-2].Array ; #=> [1 2 3 4]

※ Perl6の操作でList型が返却されるものについて、一応Array型に変換しています。

ディクショナリ

Python3
# ディクショナリを作成
me = {'height':180}

# 要素にアクセス
print(me['height']) #=> 180

# 新しい要素を追加
me['weight'] = 70
print(me) #=> {'weight': 70, 'height': 180}

Perl6ではこういうのをハッシュと呼んで、先頭には%を付けます。

Perl6
use v6;
# ハッシュを作成
my %me = 'height' => 180 ;

# 要素にアクセス
say %me{'height'} ; #=> 180

# 新しい要素を追加
%me{'weight'} = 70 ;
say %me ; #=> {height => 180, weight => 70}

ブーリアン

Python3
hungry = True
sleepy = False

print(type(hungry)) #=> <class 'bool'>
print(not hungry) #=> False
print(hungry and sleepy) #=> False
print(hungry or sleepy) #=> True
Perl6
use v6;
my Bool $hungry = True ;
my Bool $sleepy = False ;

say $hungry.^name ; #=> Bool
say not $hungry ; #=> False
say ( $hungry and $sleepy ) ; #=> False
say ( $hungry or $sleepy ) ; #=> True

ちゃんとBoolean型があるなんて、なんて素晴らしい言語なんだ

if文

Python3
hungry = True
if hungry:
    print("I'm hungry")

hungry = False
if hungry:
    print("I'm hungry")
else:
    print("I'm not hungry")
Perl6
use v6;
my Bool $hungry = True ;
if $hungry {
    say "I'm hungry" ;
}

$hungry = False ;
if $hungry {
    say "I'm hungry" ;
}
else {
    say "I'm not hungry" ;
}

for文

Python3
for i in [1, 2, 3]:
    print(i)
Perl6
use v6;
for 1, 2, 3 -> $i {
    say $i ;
}

余談ですが、Perl5 では以下のように書いてました。

Perl5
use v5;
for my $i (1, 2, 3) {
    print $i . "\n" ;
}

for文に関しては Perl6 より Python3 の方が Perl5 に似てる感。

関数

Python3
def hello():
    print("Hello World!")

hello() #=> Hello World!

def hello2(object):
    print("Hello " + object + "!")

hello2("Neighbor") #=> Hello Neighbor!

( これ、 object が文字列型じゃなかったら文字列連結でエラーになるのではないだろうか )

Perl6
use v6;
my sub hello {
    say "Hello World!" ;
}

hello() #=> Hello World!

my sub hello2(Str $object) {
    say "Hello " ~ $object ~ "!" ;
}

hello2("Neighbor") #=> Hello Neighbor!

引数は文字列型に限定しています。

クラス

Python3
class Man:
    def __init__(self, name):
        self.name = name
        print("Initialized!")

    def hello(self):
        print("Hello " + self.name + "!")

    def goodbye(self):
        print("Good-bye " + self.name + "!")

m = Man("Alice")
m.hello()
m.goodbye()
Perl6
use v6;
my class Man {
  has Str $.name is readonly;

  method new(Str $name){
      say "Initialized!" ;
      return self.bless(:$name) ;
  }

  method hello {
      say "Hello " ~ self.name ~ "!" ;
  }

  method goodbye {
      say "Good-bye " ~ self.name ~ "!" ;
  }
}

my $m = Man.new("Alice") ;
$m.hello ;
$m.goodbye ;

上記では引数の指定方法をPython版に合わせるためにコンストラクタを再定義しましたが、普通はこんな感じで書くかもしれません。

Perl6
use v6;
my class Man {
  has Str $.name is required;

  method hello {
      say "Hello " ~ self.name ~ "!" ;
  }

  method goodbye {
      say "Good-bye " ~ self.name ~ "!" ;
  }
}

my Man $m .= new(name => "Alice") ;
$m.hello ;
$m.goodbye ;

おわり

他の言語と並べてみると、似ているところとか、逆にものすごくPerl6独特なところがあって面白いですね:camel:

参考と注釈


  1. 昨年のアドベントカレンダーでInline::Perl5ネタ書こうと思ったらインストールに失敗した…という思い出がよみがえりました。 

  2. Pythonのコードは ゼロから作るDeep Learning1章 Python入門を参考にしました。 

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away