Jaktは、メモリセーフなシステムプログラミング言語です。
現在、C++に移行しています。
注:この言語は開発が進んでいます。
C++への変換には。が必要
clangです。それがインストールされていることを確認してください。
jakt file.jakt ./build/file
メモリの安全性を実現するために、次の戦略が採用されています。
Jaktには、次の3つのポインタタイプがあります。
T。)
T。ポインタが破壊されると空になります。)
Tでのみ使用可能。)
unsafe
セーフモードではnullポインターは使用できませんが、ポインターは
Optional、つまり
Optional<T>、または
T?略してラップすることができます。
弱いポインタは常にでラップする必要があることに注意してください
Optional。弱いTはなく、弱いTだけですか?。
int。すべてのキャストは明示的である必要があります。
サイレント整数オーバーフローが必要な場合は、この機能を提供する明示的な関数があります。
コードを書くよりも読むことにはるかに多くの時間が費やされます。そのため、Jaktは読みやすさを重視しています。
より読みやすいプログラムを促進する機能のいくつか:
object.function(width: 10, height: 5))
enumスコープ。
Foo(の代わりに言うことができます
MyEnum::Foo)。
match。
foo?.bar?.baz(間違いのない)および
foo!.bar!.baz(間違いのない))
foo ?? bar生成され、そうでない場合は生成されます)
foo
foo
bar
deferステートメント。
.(決して
->)で逆参照されます
ErrorOr<T>[]リターンタイプと専用
try/
mustキーワードによるエラー伝播。
関数を呼び出すときは、渡すときに各引数の名前を指定する必要があります。
rect.set_size(width: 640, height: 480)
これには2つの例外があります。
anon、引数ラベルを省略できます。
Jaktで構造を宣言する主な方法は2つあります:
structと
class。
struct
基本構文:
struct Point {
x: i64
y: i64
}
Jaktの構造体には値のセマンティクスがあります:
struct、常にディープコピーが作成されます。
let a = Point(x: 10, y: 5)
let b = a
// "b" is a deep copy of "a", they do not refer to the same Point
Jaktは、構造体のデフォルトコンストラクターを生成します。すべてのフィールドを名前で取得します。上記の
Point
構造体の場合、次のようになります。
Point(x: i64, y: i64)
構造体メンバーはデフォルトで公開されています。
class
Superタイプ
Selfタイプ
と同じ基本構文
struct:
class Size { width: i64 height: i64 public function area(this) => .width * .height }
Jaktのクラスには参照セマンティクスがあります:
classインスタンス(別名「オブジェクト」)をコピーすると、オブジェクトへの参照がコピーされます。
クラスのメンバーはデフォルトでプライベートです。
構造体とクラスの両方がメンバー関数を持つことができます。
メンバー関数には次の3種類があります。
静的メンバー関数は、呼び出すオブジェクトを必要としません。
thisパラメータはありません。
class Foo {
function func() => println("Hello!")
}
// Foo::func() can be called without an object.
Foo::func()
非変更メンバー関数では、オブジェクトを呼び出す必要がありますが、オブジェクトを変更することはできません。最初のパラメータは
this
です。
class Foo {
function func(this) => println("Hello!")
}
// Foo::func() can only be called on an instance of Foo.
let x = Foo()
x.func()
メンバー関数を変更するには、オブジェクトを呼び出す必要があり、オブジェクトを変更する場合があります。最初のパラメータは
mut this
です。
class Foo {
x: i64
function set(mut this, anon x: i64) {
this.x = x
}
}
// Foo::set() can only be called on a mut Foo:
mut foo = Foo(x: 3)
foo.set(9)
メンバー変数にアクセスするための省略形メソッドで繰り返さ
this.
れるスパムを減らすために、省略形.foo
はに展開されthis.foo
ます。
配列動的配列は、組み込み型を介して提供され
Array<T>
ます。それらは実行時に拡大および縮小できます。
Array
メモリセーフですか:
Array自動参照カウントを介して基になるデータを存続させます。
// Function that takes an Array<i64> and returns an Array<String>
function foo(numbers: [i64]) -> [String] {
...
}
配列を作成するための省略形// Array<i64> with 256 elements, all initialized to 0.
let values = [0; 256]
// Array<String> with 3 elements: "foo", "bar" and "baz".
let values = ["foo", "bar", "baz"]
辞書
function main() {
let dict = ["a": 1, "b": 2]
println("{}", dict["a"])
}
辞書の宣言// Function that takes a Dictionary<i64, String> and returns an Dictionary<String, bool>
function foo(numbers: [i64:String]) -> [String:bool] {
...
}
辞書を作成するための省略形// Dictionary<String, i64> with 3 entries.
let values = ["foo": 500, "bar": 600, "baz": 700]
セット
function main() {
let set = {1, 2, 3}
println("{}", set.contains(1))
println("{}", set.contains(5))
}
タプル
function main() { let x = ("a", 2, true) println("{}", x.1) }
match式
matchアーム内の列挙型スコープ推論
matchパターン
match[]パターンとしての特性
?[] 、
??および
!演算子との相互運用のサポート
enum MyOptional<T> {
Some(T)
None
}
function value_or_default<T>(anon x: MyOptional<T>, default: T) -> T {
return match x {
Some(value) => {
let stuff = maybe_do_stuff_with(value)
let more_stuff = stuff.do_some_more_processing()
yield more_stuff
}
None => default
}
}
enum Foo {
StructLikeThingy (
field_a: i32
field_b: i32
)
}
function look_at_foo(anon x: Foo) -> i32 {
match x {
StructLikeThingy(field_a: a, field_b) => {
return a + field_b
}
}
}
enum AlertDescription: i8 {
CloseNotify = 0
UnexpectedMessage = 10
BadRecordMAC = 20
// etc
}
// Use in match:
function do_nothing_in_particular() => match AlertDescription::CloseNotify {
CloseNotify => { ... }
UnexpectedMessage => { ... }
BadRecordMAC => { ... }
}
ジェネリック
Jaktは、一般的な構造と一般的な関数の両方をサポートしています。
function id<T>(anon x: T) -> T {
return x
}
function main() {
let y = id(3)
println("{}", y + 1000)
}
struct Foo<T> {
x: T
}
function main() {
let f = Foo(x: 100)
println("{}", f.x)
}
名前空間
namespace Greeters { function greet() { println("Well, hello friends") } } function main() { Greeters::greet() }
Jaktには2つの組み込みのキャスト演算子があります。
as? T:
Optional<T>ソース値がに変換できない場合は、空のを返します
T。
as! T:を返し
T、ソース値がに変換できない場合はプログラムを中止します
T。
キャストはこれらの
asことを行うことができます(実装はまだ同意していない可能性があることに注意してください):
truefor any value except 0, which is
false.
false -> 0and
true -> 1, even for floats.
Twill increment the reference count as expected; that's the preferred way of creating a strong reference from a weak reference. A cast from and to
raw Tis unsafe.
Additional casts are available in the standard library. Two important ones are
as_saturatedand
as_truncated, which cast integral values while saturating to the boundaries or truncating bits, respectively.
(Not yet implemented)
To make generics a bit more powerful and expressive, you can add additional information to them:
trait Hashable {
function hash(self) -> i128
}
class Foo implements Hashable {
function hash(self) => 42
}
type i64 implements Hashable {
function hash(self) => 100
}
The intention is that generics use traits to limit what is passed into a generic parameter, and also to grant that variable more capabilities in the body. It's not really intended to do vtable types of things (for that, just use a subclass)
Safety analysis(Not yet implemented)
To keep things safe, there are a few kinds of analysis we'd like to do (non-exhaustive):
Functions that can fail with an error instead of returning normally are marked with the
throwskeyword:
function task_that_might_fail() throws -> usize {
if problem {
throw Error::from_errno(EPROBLEM)
}
...
return result
}
function task_that_cannot_fail() -> usize {
...
return result
}
Unlike languages like C++ and Java, errors don't unwind the call stack automatically. Instead, they bubble up to the nearest caller.
If nothing else is specified, calling a function that
throws
from within a function that throws
will implicitly bubble errors.
Syntax for catching errorsIf you want to catch errors locally instead of letting them bubble up to the caller, use a
try
/catch
construct like this:
try {
task_that_might_fail()
} catch error {
println("Caught error: {}", error)
}
短い形式もあります:
try task_that_might_fail() catch error {
println("Caught error: {}", error)
}
エラーの再スロー(まだ実装されていません)
インラインC++既存のC++コードとの相互運用性を向上させるため、およびブロック内のJakt
unsafe
の機能が十分に強力でない状況では、インラインC++コードをプログラムに埋め込む可能性がcpp
ブロックの形式で存在します。
mut x = 0
unsafe {
cpp {
"x = (i64)&x;"
}
}
println("{}", x)
参考文献値とオブジェクトは、安全であることが証明されている状況では、参照によって渡すことができます。
参照は不変(デフォルト)または可変のいずれかです。
参照型の構文
&Tタイプの値への不変の参照
Tです。
&mut Tタイプの値への可変参照
Tです。
&foo変数への不変の参照を作成します
foo。
&mut foo変数への可変参照を作成します
foo。
*参照から「値を取得」するには、演算子を使用して逆参照する必要があります。
function sum(a: &i64, b: &i64) -> i64 {
return *a + *b
}
構造体への可変参照の場合、フィールドアクセスを行うには、逆参照を括弧で囲む必要があります。
struct Foo {
x: i64
}
function zero_out(foo: &mut Foo) {
(*foo).x = 0
}
参照(最初のバージョン)機能リスト:
&fooと使用しない場合
&mut foo
foo
unsafe)参照と生のポインタは双方向に変換可能