Repository navigation
9.1 The core for tap.python: what a method returns, as output; outlets from the hints; the audio option - #46
Merged
Merged
Conversation
… a symbol (9.1) Before plan 9.1 changes it — a last parameter hinted list[...] or np.ndarray is to take the remaining atoms — the test states today's behavior: one numeric atom arrives as the empty symbol, and more atoms than parameters are refused. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz
…om the hints; the audio option (9.1)
What docs/TAP-PYTHON-PLAN.md's "The core" asks of 9.1, host-independent and tested here:
- value.h: output_item (a selector and its atoms: a number, a list, or the message a selector
names) and output, what each outlet outputs from one call.
- processor::call_with_output() beside call(): the method's result converted by the output table
— None nothing; a bool, number or str one value (a str as `symbol <s>`, plan 9.0); a list,
unhinted tuple, range or 1-D array a list, or the message its first str names; a 0-d array its
value; a return hinted tuple[...] one value per outlet. What an outlet cannot carry — an
integer past 64 bits, a list holding None or a list, a dict, a 2-D array — is reported and
nothing is output. numpy's types are known by name, without importing numpy, and no CPython
data symbol is used (the delay-loaded Windows external).
- message_info::return_count and spreads, and outlet_count(): the widest return hint. The support
module's return_shape() splits a hint written as a string at its top level only (audit m4).
- The constructor's bind_audio: off (tap.python), process() and prepare() are messages like any
other; a tuple hint that does not say how many values is output as a list, and said once.
- A last parameter hinted list[...] or np.ndarray takes the atoms left after the others — for
tap.python~ too: a change to the class contract, pinned by the test first and recorded in
CHANGELOG.md (2.0.0) and the ReadMe.
- Announce-once per kind (audit M5): what depends on how an object binds the class — a name its
host reserves, process() and tuple returns — is said once per (save, kind), even when an object
of the other kind ran the file; the Loaded line stays once per save and says what that object
bound ("5 messages, 2 outlets").
test_output.cpp: the output table as one data-driven test over its edges (64-bit limits, NaN and
infinity, numpy scalars, 0-d and 2-D arrays, nested lists), tuple hints of each length against
results of the wrong length, outlet counts from object and string hints, both kinds on one file,
the list and array parameters, a raising method, and a call racing a reload. tap.python~'s battery
is unchanged and green (108/108).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz
…nown inputs (9.1) Three things Max users write by hand, as classes for the object without audio: a Euclidean rhythm from two attributes (a bang, a list out), a list scaled with numpy (a list in as one array, a list out), and a MIDI note's name from two outlets (tuple[str, int]). Each carries default.py's comment on why a method named int or list comes last. The core battery runs them on known inputs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz
…entence in the ReadMe's table (9.1) tap_python_bench also times processor::call_with_output() on an object without audio: a list of 64 numbers converted in and the returned list converted back out, for a class that returns it as it came (the bridge alone) and for scale.py (one numpy array), fastest of the rounds, in the JSON as "calls". scripts/update-perf-docs.py writes the sentence beside the process() table, so the ReadMe's performance claim for tap.python is measured. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz
…put() and the new examples Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz
…e is next regenerated Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plan item 9.1 (
docs/TAP-PYTHON-PLAN.md, "The core"). Everything thattap.python(a Python class as a Max object without audio) needs from the host-independent core lands here, with tests. There is no Max code change: the Max object is 9.3.tap.python~'s battery and glue test pass unchanged, with one deliberate exception: thelist[…]parameter change below.What's in it
What a method returns, as output (
value.h,processor.h)output_itemis one message for an outlet: a selector and its atoms. No selector means one number; the selectorlistmeans a list; any other selector is the message it names.outputis what each outlet emits from one call.processor::call_with_output()sits besidecall()and converts the result by the plan's output table:Noneoutputs nothing.stris one value. Astrissymbol <s>, as the 9.0 spike decided.rangeor 1-D array is a list; when its first element is astr, it's the message that names instead.tuple[…]gives one value per outlet.Noneor another list, adict, a 2-D array.Outlets
message_infogainsreturn_countandspreads, andoutlet_count()gives the widest return hint.'tuple[list[int], dict[str, int]]'counts 2 outlets, not 3 (audit m4).The audio option
bind_audio. With it off,process()andprepare()are ordinary messages,has_process()stays false, andprepare()does nothing.tuplehint that doesn't say how many values is output as a list from one outlet, and the console says so once.A last parameter hinted
list[…]ornp.ndarraytakes all the atoms left after the other parameters, as a list or as a float64 array. This applies totap.python~too.2.0.0 — unreleasedsection and in the ReadMe's Messages paragraph.Announcements per kind of object (audit M5)
process()'s binding, a keyword-only parameter, the tuple rules. These are now said once per (save, kind), so the audio and control kinds each say theirs even when the other kind's object ran the file.Loadedline says what that object bound, e.g.Loaded outputs.py: 5 messages, 2 outlets.Examples (
python/):euclid.py(a Euclidean rhythm: bang in, list out),scale.py(a list scaled with numpy: list in, list out) andnote_name.py(a MIDI note's name from two outlets,tuple[str, int]).Bench
tap_python_benchnow also times a message with a list of 64 numbers, converted in and back out. In Release on this Mac it costs 5.6 µs for the bridge alone and 15 µs forscale.py.update-perf-docs.pywrites that as a sentence beside theprocess()table. I did not regenerate the ReadMe here. With macOS's indexing running, every row came out 20–35% slower and noisier than the 30 September table.mainand this branch measured alike back to back, so it's the machine, not the change. Today's figures are in the plan; the table gets regenerated at the next idle measurement (9.6 at the latest).Tests
test_output.cpp, 10 scenarios and 396 assertions:bind_audiooff;test_examples.cppruns the three new examples on known inputs.On this Mac:
tap.python~'s glue test passes;style.yml) are clean.CI will run Linux (ASan/UBSan, TSan) and Windows.
Docs
CLAUDE.md: notes oncall_with_output()and the new examples.🤖 Generated with Claude Code
https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz