| 1 | type ProcedureHandler = fn () !string |
| 2 | |
| 3 | struct Procedure[T, U] { |
| 4 | value T |
| 5 | function fn (T) !U = unsafe { nil } |
| 6 | } |
| 7 | |
| 8 | fn (p Procedure[T, U]) handle() !string { |
| 9 | result := p.function(p.value) or { return err } |
| 10 | return encode[U](result) |
| 11 | } |
| 12 | |
| 13 | fn encode[T](value T) string { |
| 14 | $if T is Dog { |
| 15 | return 'dog:${value.name}' |
| 16 | } |
| 17 | $if T is Cat { |
| 18 | return 'cat:${value.name}' |
| 19 | } |
| 20 | return 'unknown' |
| 21 | } |
| 22 | |
| 23 | struct Dog { |
| 24 | name string |
| 25 | } |
| 26 | |
| 27 | struct NewDog { |
| 28 | name string |
| 29 | } |
| 30 | |
| 31 | fn make_dog(value NewDog) !Dog { |
| 32 | return Dog{ |
| 33 | name: value.name |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | struct Cat { |
| 38 | name string |
| 39 | } |
| 40 | |
| 41 | struct NewCat { |
| 42 | name string |
| 43 | } |
| 44 | |
| 45 | fn make_cat(value NewCat) !Cat { |
| 46 | return Cat{ |
| 47 | name: value.name |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | fn test_generic_fn_field_multi_instance_specialization() { |
| 52 | dog := Procedure[NewDog, Dog]{ |
| 53 | value: NewDog{'leo'} |
| 54 | function: make_dog |
| 55 | } |
| 56 | cat := Procedure[NewCat, Cat]{ |
| 57 | value: NewCat{'milo'} |
| 58 | function: make_cat |
| 59 | } |
| 60 | handlers := [ProcedureHandler(dog.handle), ProcedureHandler(cat.handle)] |
| 61 | assert (handlers[0]() or { panic(err) }) == 'dog:leo' |
| 62 | assert (handlers[1]() or { panic(err) }) == 'cat:milo' |
| 63 | } |
| 64 | |