Closed timotheecour closed 3 years ago
Even if this works, I would prefer the core language to be implemented in the compiler and not through macros (for better compile times and sane error messages), at least unless and until the macros are mapped to compiler plugins which should improve the performance of macros significantly (see v2 milestone),
D ranges is still the superior abstraction, offering better composition and support for 0-cost lazy functional programming
It's still worse as there is no ownership system so you're left with a tracing GC or more-expensive-than-you-think-it-is reference counted slice type which diverges quite a bit from the naive (ptr, len) pair implementation. Plus writing the code required to support these ranges is much harder to write than using a yield
statement.
I'd like a report on CPS, what was tried, what is missing so far so that we can evaluate this RFC with its most obvious alternative (besides what is implemented today).
The initial CPS impl in master
represents an untyped
macro. The tests and demos work.
The typed
version (I think it's in a typed
branch), solves several performance and ergonomic warts but doesn't work yet due to apparent compiler bugs, at least one of which requires a breaking fix. I think it's in 1.4, but I'm honestly unsure.
What remains to be implemented (or demonstrated, at least):
continuation()
or whateverlet foo = continuation[]
or whateverMaybe @zevv has some clearer ideas about what's missing; this is just the stuff off the top of my head.
I personally really want properly bulletproof concepts so I can play with some ideas for CSP; the abstraction over CPS where we'll implement go-channel/clojure-core.async-type machinery.
Right, @disruptek kind of tells it all. The Nim CPS project is basically an implementation of the mechanics described in the paper "Continuation-Passing C - Compiling threads to events through continuations". Linear Nim code is transformed into a number of separate procs that pass continuation objects among them. What used to live on the stack is now in the continuations, which allows non-linear code flow.
On top of Disruptek's CPS work I prototyped some basic constructs like:
From a technical point of view, this all works, although the syntax is sometimes lacking or plain weird, still.
We are stuck for some time on motivation and a compiler bug, although I'm not even sure at this time what exactly the bug was (something sym vs ident, I believe). I think the goal was to prove this was all feasible and usable, but we already know that a definitive implementation should probably do the transformations in the compiler instead of using macros.
Can you share any relevant link? EDIT: links were now added above
TBH: I'm not sure if the above links actually compile with the current state of CPS - stuff was very much in flux, we had a few days of hacking frenzy but broke API's on the way a few times. But I'm sure the above snippets show the gist of what we were trying to do.
There are two forms of bug that I consider blockers:
in https://github.com/disruptek/cps/blob/master/stash/iterator.nim instead of:
var a = counter(3, 7)
# Resume the iterator a bunch of times
var v = a.produce()
echo "produced ", a.produce()
echo "produced ", a.produce()
can you use ForLoopStmt
as I did in https://github.com/nim-lang/Nim/pull/15655 to enable the more idiomatic for
syntax for the common case, which would then allow writing:
for v in cps counter(3, 7):
echo "produced ", v.produce()
when user doesn't need more fine grained iteration
[EDIT] can that code snippet be modified to support working with yield types other than int (and without having to specify the type excplicitly)? see again https://github.com/nim-lang/Nim/pull/15655 for how i did that
Hmm, it's all some time ago, so I'd have to get back into all that to tell, but I think with the for loop macro that should work...
This is not an RFC, this is an interesting question.
It's not just an "interesting question", the suggestion is that maybe the language can be simplified by mapping (via syntax sugar enabled by the compiler) the existing iterators to a pure library implementation, also fixing https://github.com/nim-lang/Nim/pull/15818 (vm + js not supported) and support for recursion (https://forum.nim-lang.org/t/7020#44149) in the process.
Sure but an RFC is what you write after you have established that it's possible and a good idea. Then you write an RFC to convince others that we should change Nim.
see https://github.com/nim-lang/Nim/pull/15655 for a simple macro that allows defining something that acts very similar to an iterator:
Not only that but it solves major long existing limitations with iterators, eg:
this is not a complete 1:1 replacement (see limitations below) but could become one. This could potentially be a basis for replacing iterators with regular procs + syntax sugar, which would simplify nim language by removing all custom compiler code handling iterators.
example 1
(EDIT) example 2: recursion
see example showing recursion works in https://forum.nim-lang.org/t/7020#44149
note
{.closure.}
iterators only, but with alias PR (https://github.com/nim-lang/Nim/pull/11992), we should also be able to map{.inline.}
iterators just as well (since we'd be able to forward a template (instead of a proc) inside theiterate
macro); I can provide more details if this is unclearlimitations
finished
,next
.typeof(block: (for ai in iterate a: ai))
which currently doesn't work; and hence would enabletoSeq
for ai in iterate a
could be written asfor ai in a
; likewise, iterator definition could be mapped to a proc as defined above.EDIT
continue
andbreak
, see PR