imagej / imagej/imagej-ops

Improve usability of op built-in methods

Open
#502 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
94
Forks
44
PR merge metrics
No merged PRs in 30d

Description

We actually have four scenarios:

1. Run an op type-safely.
2. Run an op type-flexibly.
3. Match an op type-safely.
4. Match an op type-flexibly.

Right now, the built-in method signatures cover case (1) above. And the `OpService`'s `op` method covers (4). We also partially/limitedly cover (3) and (4) via the `Functions`, `Computers`, `Inplaces` and `Hybrids` utility class methods.

I want to improve the API and/or architecture to make all four scenarios above easy.

-----

What follows are some now-stale notes I wrote while thinking about this problem. I have other thoughts too, but no time to write them down at this moment. Please note that the ideas below do not necessarily represent current thinking—I just want to keep them preserved somewhere so they are not totally lost. I will return to this issue as I stumble across other ideas, topic branches, etc. The gist of this issue is simply to fulfill the requirements outlined above.. somehow!

* Split built-in type-safe methods out of `OpEnvironment`. This is long overdue; the `OpEnvironment` should not be compile-time entangled with the entire core ops library.
* `TOps` object has a `TOpEnvironment` referencing typed `Namespace` objects and typed method signatures.
* Should this be generated at compile time? Or at runtime? Probably want to generate at compile time, so that code completion works in IDEs.
* `UOps` object has a `UOpEnvironment` referencing untyped namespaces and `Object...` method signatures.
* Should this be generated at compile time? Or at runtime? Probably want to generate at runtime, so that scripts are 100% extensible.

-----
```groovy
//
// 1. Run an op type-safely.
// Need to ensure there are aliases for all op namespaces.
//

// @CreateKernelNamespace kernel
k = kernel.gauss(...typed...)

// -- LONGER --
// @CreateNamespace create
k = create.kernel().gauss(...typed...)

// -- LONGEST --
// @OpService ops
k = ops().create().kernel().gauss(...typed...)
```

-----

```groovy
//
// 2. Run an op type-flexibly.
// A new interface hierarchy?
//

// @Ops.Create.Kernel kernel
k = kernel.gauss(...any...)

// -- LONGER --

// @Ops.Create create
k = create.kernel().gauss(...any...)

// -- LONGEST --

// @OpService ops
k = ops.create().kernel().gauss(...any...)
```

-----

```groovy
//
// 3. Match an op type-safely.
// A new interface hierarchy?
//

// @Ops ops
// @Ops.Create create
// @Ops.Create.Kernel kernel

op = kernel.gaussOp(...any...)
// also OK, but longer:
op = create.kernel().gaussOp(...any...)
// and longer still:
op = ops.create().kernel().gaussOp(...any...)
```

-----

```groovy
//
// 4. Match an op type-flexibly.
//

k = gauss.run(...any...)
// also OK, but longer:
k = kernel.gauss.run(...typed...)
// and longer still:
```

-----

Idea from @gab1one:

```python
# @OpService ops
# @OpGetService opgs
# @OpRunService oprs

img = ops.create().img(300,300)

add = opgs.math().add(int, int)

out = oprs.map(add, img)
out = ops.map().map(add, img)
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading the existing OpEnvironment, OpService, Functions, Computers, Inplaces, and Hybrids APIs mentioned in the issue. Compare how they currently support the four type-safe and type-flexible run and match scenarios. The issue is complete only when the API or architecture makes all four scenarios easy, but it does not define a specific design or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, developer-experience
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.