st = dict(a=None, xs=[dict(id='p')], constructor=1)
assert _at(st, 'a') is None and _at(st, 'xs.0.id') == 'p'
assert _at(st, 'b') is _NONE and _at(st, 'xs.1') is _NONE and _at(st, 'constructor') is _NONEpoll
A presenter can ask a room the question of a demo gate. of_gate makes a choice question from the gate, with no model call. public keeps the part of a question that the room sees.
abhyasa and Leela share this module. abhyasa had the same contract first, as abhyasa.talk.ask_from_gate and public_ask.
A path in the state
_at reads a path such as fused.0.id in the state. A path that is not in the state gives _NONE, so a value of None is not the same as no value. It reads own keys only, as the runtime does: __proto__, prototype and constructor give _NONE.
A path reads into lists, and a missing key gives _NONE:
A question from a gate
The options of a gate are a list, or {"from": path} in the state of the spec. The answer is {"is": value}, or a path in the state. of_gate reads the state of the spec and does not run derive. A path that needs derive gives None. Fewer than 2 or more than 6 options give None, and so does an answer that is not an option. The prompt gets the values of the state. A {name} with no value stays as it is.
of_gate
def of_gate(
spec:dict, gate:str
)->dict | None:A choice question from the gate gate of spec, with the index of the right option; None when the gate can not be a room question.
The gallery gates with fixed options and a fixed answer give a question. The gates that need derive give None, and so does an unknown gate.
g = gallery()
assert of_gate(g['parabola-vertex'], 'move') == dict(kind='choice', q='b goes from 0 to 2. Where does the lowest point move?',
options=['Left and down', 'Right and down', 'Straight up', 'It stays'], answer=0)
assert of_gate(g['reciprocal-rank-fusion'], 'win') is None # the answer needs derive
assert of_gate(g['vowel-sandhi'], 'join') is None # the options need derive
assert of_gate(g['softmax-temperature'], 'nope') is NoneA gate in a row, with its options and its answer in the state:
spec = dict(state=dict(k=60, opts=['x', 'y'], best='y'), blocks=[dict(type='row', blocks=[dict(type='gate', id='g', prompt='With k = {k} and {m}?',
options={'from': 'opts'}, answer='best')])])
assert of_gate(spec, 'g') == dict(kind='choice', q='With k = 60 and {m}?', options=['x', 'y'], answer=1)The prompt and the options show values as the demo shows them in the browser. 2.0 shows as 2, null shows as nothing, and a minus sign is a true minus:
spec = dict(state=dict(b=2.0, t=0.1, x=-1.5, z=-0.0, n=None, ok=True, p=1/3), blocks=[dict(type='gate', id='g', prompt='{b} {t} {x} {z} {n} {ok} {p} {p:2}',
options=[2.0, 0.1, 1.5, True], answer={'is': 2.0})])
test_eq(of_gate(spec, 'g'), dict(kind='choice', q='2 0.1 −1.5 0 true 0.3333 0.33', options=['2', '0.1', '1.5', 'true'], answer=0))The part the room sees
public keeps the kind, the question, the options, and most (the most characters of a words answer). It drops the answer and the source.
public
def public(
p:dict | None
)->dict | None:The part of question p that the room sees: no answer and no source.
abhyasa adds src to a question from a gate. public drops it, and the answer:
a = dict(of_gate(g['softmax-temperature'], 'hot'), src=dict(demo='softmax-temperature', gate='hot'))
assert a == dict(kind='choice', q='T goes from 1 to 2. What happens to the share of Paris?',
options=['It rises', 'It falls', 'It stays the same'], answer=1, src=dict(demo='softmax-temperature', gate='hot'))
assert public(a) == dict(kind='choice', q='T goes from 1 to 2. What happens to the share of Paris?', options=['It rises', 'It falls', 'It stays the same'])
assert public(dict(kind='words', q='Say why.', most=80)) == dict(kind='words', q='Say why.', most=80)
assert public(None) is None