Closed leonoel closed 3 years ago
I like the current naming scheme and would smuggle amb
in with another symbol (+
), but that's a personal taste. IIUC the amb
we're discussing isn't exactly the same amb
SICP shows since it backtracks and returns the first satisfying value, allowing to continue the search with the try-again
keyword. The amb
here is a forking operator.
If you dislike the symbols:
?
says in the docstring "Runs given task" and run
would indeed be a nice and short name!
could be check
? No bright ideas hereI know you said you're OK with the single operators, just throwing out ideas.
The flow suffixes are short and meaningful to me. Maybe 1
, 0
and n
would make sense to me as well,
1
meaning the flows are run 1 by one, sequentially0
meaning the latest value is always used (not the brightest choice, I agree)n
meaning there's n
flows running concurrentlyThese at least wouldn't interfere with current clojure conventions where a trailing ?
is typically used for predicates and !
for side effects.
As a side-note, is there a case where ??
and friends are used without an accompanying enumerate
? I'd rather write (m/?? (range 10))
.
IIUC the amb we're discussing isn't exactly the same amb SICP shows since it backtracks and returns the first satisfying value, allowing to continue the search with the try-again keyword. The amb here is a forking operator.
The semantic difference is not obvious to me.
I haven't seen a function in missionary that would allow consuming only part of a flow, somehow I imagined the flow needs to be fully consumed. The example you posted makes things clearer to me, thanks, learning something interesting about this library every day!
Forgive my question on enumerate
, I now understand it turns a collection into a flow. I'd still like a shorter name like enum
, walk
, from
or iter
.
Here's a suffix scheme I would prefer.
??
with ?>
(mnemonic : the child takes priority over the parent)?!
with ?<
(mnemonic : the parent takes priority over the child)?=
(mnemonic : same priority for parent and child)I like how >
<
and =
belong to the same lexical field of comparison. Another benefit : sequential amb would become amb>
so it doesn't look like a predicate anymore.
What do you think ?
I haven't seen a function in missionary that would allow consuming only part of a flow, somehow I imagined the flow needs to be fully consumed.
transform
, integrate
and aggregate
support early termination with reduced
(and consequently take
and drop
transducers work as expected). Does it cover what you have in mind ?
If my mental model is correct
I don't like the fact that <
is a reverse of >
in a mathematical context ((< 4 5)
is same as (> 5 4)
) while here the reversal of the incoming flow wouldn't mean the same ((m/?> flow)
isn't the same as (m/?< reversed-flow)
). I'm comparing this because it seems intuitive to me (subjectively of course).
Still, I like the suffixes and could see myself getting used to them with your mnemonics.
transform, integrate and aggregate support early termination with reduced (and consequently take and drop transducers work as expected). Does it cover what you have in mind ?
I have no objections towards the API, I just had a misguided mental model of what a flow is.\
Any progress on this? I'd be OK with the <=>
trio.
Would you be open to other, non-operator name discussions as well? I like short names and think we could find some for enumerate
, transform
, aggregate
and maybe integrate
. They are used frequently and take up a lot of screen width.
Sure, shorter names sound better to me too.
I like the current naming scheme, I like short names too, but what I find useful are full explicit names + short versions aliases. Such that you can write readable explicit code for examples and teaching, then shorten it for seasoned readers.
I'll brainstorm some ideas to see what sticks.
enumerate
- how about a ->flow
function backed by a protocol? It could potentially turn other things into flows.
aggregate
- the docs say it reduces into a value, so how about reduce
? It is familiar to clojurians from core and aggregate
is basically the same thing in the missionary world.
If we just discuss shorter names, here are some alternatives:
enumerate
- from
, seed
, fill
, ingest
transform
- view
, alter
, swap
, change
, edit
aggregate
- combine
, mix
, unite
, blend
integrate
- include
, add
what I find useful are full explicit names + short versions aliases. Such that you can write readable explicit code for examples and teaching, then shorten it for seasoned readers.
I used to have a similar opinion but nowadays I find this a burden. Having 2 names means there will be 2 usages in the source code and I'll need to remember both in order to read source code, especially foreign. Also, for newcomers shorter names are usually not the problem.
reduce
feels right. I used to be concerned about name conflicts with clojure.core
, but in practice alias prefixes just works. I was also concerned about clojure.core/reduce
's slightly different behavior when initial value is not supplied, but in practice nobody relies on that. I don't see a strong enough argument against reusing reduce
, same name for same concept is just less confusing and less cognitive load for newcomers. If we play this game, then for consistency integrate
must be reductions
and transform
must be eduction
(with varargs, no big deal). It's not a significant gain in screen real estate, but I still think it's worth it.
Yes, I thought about those too but for some reason I thought they don't map well because they return a flow. I'm not sure why I thought that would be a problem, it was probably too late in the night :) If you can flesh out these new names, the amb operators, the new <=>
operator names and perhaps the cp
macro, you could release a new version and announce it in the usual clojure channels.
Regarding enumerate
- I don't like the coercion protocol approach, although I'm not sure to be able to explain why. I'd like to avoid names with too broad meaning (e.g from
), my preference currently goes to seed
.
I'm fine with seed
. If there will be a need for a coercion protocol the question can be revisited.
Will you keep the old names around for a simpler upgrade path?
So here is the recap of changes. Old name | New name |
---|---|
?! |
?< |
?? |
?> |
enumerate |
seed |
transform |
eduction |
integrate |
reductions |
aggregate |
reduce |
Will you keep the old names around for a simpler upgrade path?
That makes sense, we can release a first version where old names still work with a deprecation warning. The plan is to actually remove them when we reach non-breaking release policy.
I think @ggeoffrey's concern about cryptic operators (?
?=
etc) is legit, and I don't mind having both sigils and beginner-friendly aliases. However it can be addressed later and would not be a breaking change so I suggest we stick with sigils for now and tackle the issue separately.
released b.19
Discussion about operator naming in order to come up with a better scheme while breaking changes are still tolerated. I think the current scheme is needlessly obscure and could be made more consistent.
The reasoning behind current naming is :
?
wait for a result that is non-deterministic and not immediately available!
check for interruptionForking operators share with
?
the properties of non-determinism and lack of immediate availability, that's why they start with?
as well, and because multiple results are produced an extra character is added. The second character gives information about how the flow is consumed.?
because conceptually we wait for the entire child flow to be completed before pulling the next value.!
because the child flow should expect to be interrupted if it's too slow=
because it introduces parallelism27
amb
operators should reuse suffixes?
and=
for consistency.I think
?
and!
make sense as single operators, but reusing them as fork suffixes was probably not a good idea, the link is not really obvious and rather confusing.