Callables et lambdas
Six opérations rangées dans un tableau comme Callables, cinq lambdas et une méthode avec bind, chacune confiée à Array.map sur les mêmes nombres.
L'éditeur ci-dessus fait tourner ce projet. Changez une ligne et il se recharge.
Classes Godot utilisées
CallableCallable.bindArray.map
Le code
scripts/main.gd
extends Node
const SOURCE: Array = [3, 8, 1, 6, 9, 4, 7, 2]
const TICK: float = 0.45
var operations: Array = []
var rows: Array = []
var buttons: Array = []
var status: Label
var elapsed: float = 0.0
var active: int = 0
func _ready() -> void:
operations = [
{name = 'double', fn = func(value: int) -> int: return value * 2},
{name = 'square', fn = func(value: int) -> int: return value * value},
{name = 'halve', fn = func(value: int) -> int: return roundi(value * 0.5)},
{name = 'mirror', fn = func(value: int) -> int: return 10 - value},
{name = 'cap at five', fn = func(value: int) -> int: return mini(value, 5)},
{name = 'add bonus, bound', fn = _add_bonus.bind(12)},
]
var row: HBoxContainer = _root()
_menu(row)
_table(row)
_apply(0)
print('every entry in the list is a Callable, five lambdas and one method with bind')
func _process(delta: float) -> void:
elapsed += delta
if elapsed < TICK:
return
elapsed = 0.0
_apply((active + 1) % operations.size())
func _add_bonus(value: int, bonus: int) -> int:
return value + bonus
func _apply(index: int) -> void:
active = index
var operation: Dictionary = operations[index]
var result: Array = SOURCE.map(operation.fn)
var ceiling: int = maxi(int(result.max()), 1)
for i in SOURCE.size():
var line: Dictionary = rows[i]
line.result.text = str(result[i])
line.bar.max_value = ceiling
line.bar.value = result[i]
for i in buttons.size():
buttons[i].add_theme_color_override('font_color', Color('#8eef97') if i == index else Color('#8a90a0'))
status.text = 'SOURCE.map(operations[%d].fn) gave %s' % [index, str(result)]
func _menu(row: HBoxContainer) -> void:
var column: VBoxContainer = VBoxContainer.new()
column.custom_minimum_size = Vector2(300, 0)
column.add_theme_constant_override('separation', 8)
row.add_child(column)
var title: Label = Label.new()
title.text = 'the list of Callables'
title.add_theme_font_size_override('font_size', 22)
title.add_theme_color_override('font_color', Color('#8da5f3'))
column.add_child(title)
for i in operations.size():
var button: Button = Button.new()
button.text = operations[i].name
button.pressed.connect(_apply.bind(i))
column.add_child(button)
buttons.append(button)
func _table(row: HBoxContainer) -> void:
var column: VBoxContainer = VBoxContainer.new()
column.custom_minimum_size = Vector2(660, 0)
column.add_theme_constant_override('separation', 8)
row.add_child(column)
var title: Label = Label.new()
title.text = 'the same eight numbers, mapped'
title.add_theme_font_size_override('font_size', 22)
title.add_theme_color_override('font_color', Color('#8eef97'))
column.add_child(title)
for value in SOURCE:
var line: HBoxContainer = HBoxContainer.new()
line.add_theme_constant_override('separation', 14)
column.add_child(line)
var source: Label = Label.new()
source.text = str(value)
source.custom_minimum_size = Vector2(34, 0)
source.add_theme_color_override('font_color', Color('#8a90a0'))
line.add_child(source)
var arrow: Label = Label.new()
arrow.text = '->'
arrow.add_theme_color_override('font_color', Color('#8a90a0'))
line.add_child(arrow)
var result: Label = Label.new()
result.custom_minimum_size = Vector2(48, 0)
result.add_theme_font_size_override('font_size', 20)
line.add_child(result)
var bar: ProgressBar = ProgressBar.new()
bar.show_percentage = false
bar.custom_minimum_size = Vector2(440, 18)
bar.add_theme_stylebox_override('background', _bar_style(Color('#2a2f3d')))
bar.add_theme_stylebox_override('fill', _bar_style(Color('#8da5f3')))
line.add_child(bar)
rows.append({result = result, bar = bar})
func _bar_style(color: Color) -> StyleBoxFlat:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = color
style.set_corner_radius_all(5)
return style
func _root() -> HBoxContainer:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var margin: MarginContainer = MarginContainer.new()
for side in ['margin_left', 'margin_right', 'margin_top', 'margin_bottom']:
margin.add_theme_constant_override(side, 48)
add_child(margin)
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var column: VBoxContainer = VBoxContainer.new()
column.add_theme_constant_override('separation', 16)
margin.add_child(column)
var title: Label = Label.new()
title.text = 'A function kept in a variable'
title.add_theme_font_size_override('font_size', 28)
column.add_child(title)
var hint: Label = Label.new()
hint.text = 'Nothing below knows what the operation is. It receives a Callable and hands it to Array.map.'
hint.add_theme_color_override('font_color', Color('#8a90a0'))
column.add_child(hint)
var row: HBoxContainer = HBoxContainer.new()
row.add_theme_constant_override('separation', 36)
column.add_child(row)
status = Label.new()
status.add_theme_font_size_override('font_size', 18)
status.add_theme_color_override('font_color', Color('#8eef97'))
column.add_child(status)
return row