あいさつ
こんにちは、開発者になりたいkarumaruです
今日もやっていきます
1.並列処理
これは簡単に書かせたい
task タスク名(引数1, 引数2):
並列処理させたいタスク
ifとか、loopとか、変数作成とか、
send 保存する変数
sendした変数以外全部捨てます!
そしてasです、これはコードの省略とか、if分岐の時で変数定義とか、まあいろんなことに使えます
// 使用例
fn divide(a, b):
if b == 0:
send Err("ゼロ除算エラー") as DivisionError
else:
send a / b as result
2.関数について追記
fn example():
local_var = 100
result = local_var * 2
send result
print(local_var) // エラーになる
print(result) // 200が出力される
// 一応書いておきます
task process_data():
temp_data = getData()
processed = temp_data.transform()
send processed
引数について
関数とタスクは引数を取ることができます。引数はカンマ区切りで変数名のみを書きます。
// 関数に引数
fn add(a, b):
send a + b
// タスクに引数
task calculate(x, y, z):
result = x * y * z
send result
// 呼び出し
add(5, 3)
calculate(2, 3, 4)
デフォルト引数、名前付き引数、可変長引数はサポートしません。シンプルに引数名だけを書きます。
実行フローについて
Err関連は全くやっていませんが次セクションで解説しているので一回読んでみてください
task A():
send 10 as dataA
task B():
send 0 as dataB
task Divide():
if dataB == 0:
send Err(ゼロ除算) as divError
else:
send dataA / dataB as result
task C():
if err.divError == Err:
send Err(Divide失敗) as finalError
else:
send result * 2 as finalResult
実行の順番
[開始]
│
├─ [ワーカー1] task A ──▶ send dataA = 10
│
├─ [ワーカー2] task B ──▶ send dataB = 0
│
├─ [ワーカー3] task Divide (依存: dataA, dataB)
│ └─ dataB == 0 → send Err(ゼロ除算) as divError
│
├─ [ワーカー4] task C (依存: divError)
│ └─ err.divError == Err → send Err(Divide失敗) as finalError
│
└─ [メインプログラム]
dataA = 10
dataB = 0
divError = Err(ゼロ除算)
finalError = Err(Divide失敗)
3.エラーハンドリング
これはね、私のこだわりが全部詰まってます、
実行フローについてのところのコードを一つずつ解説していきます
(task A、task Bは省略)
task Divide():
if dataB == 0:
send Err(ゼロ除算) as divError
else:
send dataA / dataB as result
もしdataBの値が0だった場合、グローバル変数として、Errを定義し、エラー内容にゼロ除算を記入、asでErrにdivErrorという変数名を付ける、その値はerrクラスへ入る
もしそうでないならdataA割るdateBを実行し、その値にresultという変数名を付け、グローバル変数とする
task C():
if err.divError == Err:
send Err(Divide失敗) as finalError
else:
send result * 2 as finalResult
もし、err.divErrorを問い合わせた際、Errで合ったなら、グローバル変数として、Errを定義し、エラー内容にDivide失敗を記入、asでErrにfinalErrorという変数名を付ける、その値はerrクラスへ入るもしそうでないならresult掛け2を実行し、その値にfinalResultという変数名を付け、グローバル変数とする、
- errクラス
↳Errを定義したらこのクラスの傘下になる、Errか確認する際このクラスに問い合わせる、errクラスの継承は不可 - Err型
↳これはErr専用の型です、エラーメッセージと、エラーであることが記載されていいます
4.コレクション型
Map型
// さすがにMapは波括弧を使います
// mapを作成
speed_map = {
"C": 3.23,
"Fortran": 4.99,
"Python": 5.93,
"Haskell": 13.91,
}
// mapからデータを取り出す
speed_Py = speed_map["Python"]
print("Pythonのスピードは" + speed_Py + "秒")
// ペアを作成
points_map new ["Java": 8.18]
// 値を更新
points_map ["Haskell"] = 13.16
// キーが存在するか
existC = points_map in C
// forで取り出す
for speed_map:
print(key + "の速度は" + value)
enum型
// enumを作成
enum Weekday {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
}
// 変数にenumの値を代入
today = Weekday.Friday
// 条件分岐で使ってみる
if today == Weekday.Friday:
print("華金じゃあああ!")
elif today == Weekday.Saturday:
print("休みーーー!")
elif today == Weekday.Sunday:
print("月曜怖い...")
else:
print("平日!仕事や学校頑張ってー!")
list型
// リストを作成
scores = [90, 85, 95, 100]
// 最初の要素を取得
first_scores = scores[0]
print(first_scores) // 出力: 90
// 更新
scores[2] = 98
// 特定の値を削除
scores del 1 // 1番目の要素を削除
// 特定の要素を含むものを削除
scores remov 100 // 100を含む要素を取り除く
// 要素を追加
scores new [97] // 最後に追加
scores new [98] to 2 // 二番目に追加
5.Match式
これね、すんごく便利なんで、使えるようにしちゃおー
コレクション型とErr型との相性が良いし、
普通のMatch式
// Enum Weekday が定義済みと仮定
today = Weekday.Saturday
// todayがどのcaseでtrueになるかをチェック
activity = match today {
// case の後に、一致させたい値(パターン)を記述
case Weekday.Saturday:
"今日は最高!遊びに行くぞ!"
case Weekday.Sunday:
"ゆっくり休むか、来週の準備だ..."
case Weekday.Friday:
"華金の夜は長い!"
// どの case にも当てはまらない場合
case else:
"平日。仕事頑張ろう。"
}
print("今日の予定: " + activity)
Not Match
user_input_name = "admin"
// 禁止されているユーザー名リスト
banned_names = ["admin", "root", "guest", "system"]
// user_input_name が banned_names リストのパターンに当てはまらないかチェック
validation_result = notmatch user_input_name {
// ユーザー名が禁止リストの中に「含まれている」パターン
// Listをパターンとして受け入れる拡張が必要だぜ!
case banned_names:
"その名前は使えません!"
// 禁止リストに当てはまらない(使ってもOK)場合
case else:
"ユーザー名登録完了!"
}
print(validation_result) // 出力: その名前は使えません!
ちょっと拡張
if scores == 5 to 10:
print("Nice!")
こんな感じで5to10のように書くと5以上10以下のように記述できます、便利でしょ?
6.Empty型とnullの話
Hyper-Novaにはnullは存在しません!10億ドルの失敗とはおさらば!
代わりにEmpty型を使います。Emptyは「値がない」状態を安全に表現します。
Empty型の基本
// Emptyを代入
x = Empty // x は Empty型
// 比較はできる
if x == Empty:
print("値がない")
// でも演算はできない(コンパイルエラー)
y = x + 5 // Empty型とint型は演算できないのでエラー
// 表示もできない(コンパイルエラー)
print(x) // Emptyは表示できないのでエラー
Empty型と再代入
x = Empty // x は Empty型
x = 10 // x は int型に変わる
x = "hi" // x は string型に変わる
// 型を明示した場合はEmptyを入れられない
int: y = Empty // コンパイルエラー
int: y = 0 // これならOK
関数でEmptyを返す
fn find_user(id):
if id > 0:
send "User" + id
else:
send Empty
// 使う側
user = find_user(0)
// matchで安全に使う
match user {
case Empty:
print("ユーザーが見つかりません")
case else:
print("ユーザー: " + user)
}
EmptyとErrの使い分け
- Empty: 値がない、見つからない(正常な状態)
- Err: エラーが発生した(異常な状態)
fn get_optional_field(user):
if user.has_nickname():
send user.nickname
else:
send Empty // ニックネームがない(正常)
fn read_file(path):
if file_exists(path):
send file_content
else:
send Err("ファイルが見つかりません") // エラー!
7.sendの重要ルール
関数とタスクは必ずsendで値を返さないといけない、すべての実行パスでsendが必要だヨ!
正しい例
fn divide(a, b):
if b == 0:
send Err("ゼロ除算")
else:
send a / b
// どちらのパスでもsendがある
危険な例
fn bad_example(x):
if x > 0:
send "positive"
// x <= 0 の場合sendがない!
// → 実行時にパニック!
// こんな危ないコード書くなよ!
アセンブリ
インラインアセンブリ
asm(xor r12, r12)
こんな感じで書く
アセンブリ記述
asm:
global _start
_start: mov rbp, 1
L: xor r12, r12
mov rax, rbp
mov bl, 3
div bl
test ah, ah
jnz C5
mov rsi, F
mov dx, 4
call W
inc r12
; FizzBuzz書いたけどフルで書くと長いしめんどくさいので最初の少しだけ
これもこんな感じで、書きやすい...のかな?
今日はおしまい
nullをなくしてEmpty型を導入し、引数の仕様も確定しました!
次回は正規表現について書きたいと思います、記号ばかりでしんどそう、、、
Part 3もお楽しみに!