
// use optional without ? or an or block in places where it is not allowed

fn foo() ? {
	println('foo is called')
}

fn bar<T>(v T) ?T {
	return none
}

const (
	const_value = bar(0)
)

struct Data {
	f fn (int)
mut:
	value int = bar(0)
	opt   ?int = bar(0)
}

fn (mut v Data) add(n int) {
	v.value += n
}

fn twice(n int) int {
	return n * 2
}

fn main() {
	// call fn
	foo()
	_ := bar(0)
	println(twice(bar(0)))

	// anon fn
	fn (_ int) {}(bar(0))

	// assert
	assert bar(true)

	// struct
	mut v := Data{
		f: fn (_ int) {},
		value: bar(0),
		opt: bar(0),
	}
	v.add(bar(0)) // call method
	v.f(bar(0)) // call fn field

	// array
	mut arr := [1, 2]
	arr << bar(0)
	// init
	_ := [bar(0)]
	_ := []int{init: bar(0)}
	_ := [bar(0)]!
	_ := [1]int{init: bar(0)}
	// index
	println(arr[bar(0)])
	// array builtin methods
	arr.insert(0, bar(0))
	arr.prepend(bar(0))
	arr.contains(bar(0))
	arr.index(bar(0))
	println(arr.map(bar(0)))
	println(arr.filter(bar(true)))
	println(arr.any(bar(true)))
	println(arr.all(bar(true)))

	match bar(0) {
		0 { }
		else { }
	}
}
