<_xvilka_>
seems the problem in python part of it - __import__() doesn't work properly
Pierpa has quit [Quit: Page closed]
zmzm has quit [Quit: zmzm]
<whoman>
whats python
_xvilka_ has quit [Changing host]
_xvilka_ has joined #ocaml
<_xvilka_>
whoman: py 3.6
<whoman>
less chars and more numbers help me sarcastically to clarify my question? =p
<whoman>
what is the exact error or are you guessing ? maybe it cant find the 'module'
<whoman>
so-called
<rgr[m]>
companion_cube: join the dark side
<_xvilka_>
whoman: it does import the module, if I modify that lymp.py to print module name after __import__(mod) it prints ok. But if you dir(mod) in that python script (lymp.py), is shows only standard stubs, without my arguments - e.g. simple function "def some(): return \"some\""
<_xvilka_>
whoman: if I do same __import__(mod), dir(mod) in regular python3 REPL - everything works
<whoman>
hmm that is strange. i dont know too much python, only from blender scripts. i cant guess what could be going on, unless the dir() is changed after __import__ somehow
<flux[m]>
Drup: well, yes.. the performance way better with thunk lists then I guess?
<Drup>
flux[m]: oh yeah
<Drup>
like, one order of magnitude
<Drup>
for transient transformations, which is most of the use cases for iterators, lazylists are so bad it's not even worth it
<Drup>
you might as well use normal lists
sh0t has joined #ocaml
shinnya has quit [Ping timeout: 256 seconds]
dhil has joined #ocaml
<Drup>
rgr[m]: having recently writen functions doing fairly delicate stream manipulations, I assure you, you don't want to write them with Core's sequence
<companion_cube>
that reminds me I should update the `product` combinator…
<Drup>
(and even if gen is faster, you *really* don't want to write them with that easier, it's too painful)
<companion_cube>
heh :D
<companion_cube>
either*
<companion_cube>
I wrote many combinators with gen, and it was ugly indeed
<rgr[m]>
what's wrong with it?
<Drup>
rgr[m]: it's painful
<Drup>
you have to constantly deal with the current state of the iterator manually
<Drup>
every time you would recurse in a non-tail-rec ways, you have to use a stack instead, etc
<Drup>
god forbid if you want non-linear walks
<rgr[m]>
Yes, Sequence.Generator cleans up a lot messes
<rgr[m]>
Why "have"? Only if you're using the constructors. You can use it like a normal stream and never worry about the state
<Drup>
rgr[m]: I was talking about "Gen"
kuwze has joined #ocaml
<Drup>
rgr[m]: the question is "can you define your own walks easily"
<Drup>
ie, the case where the provided functions are not sufficient
<rgr[m]>
oh yeah, Gen's awful I agree
<companion_cube>
how is it different, though? It's the same as base.sequence with the state in a ref, isn't it?
<companion_cube>
(the weird thing is how fast it is nonetheless…)
<rgr[m]>
Sure, why not? At least I don't see how oseq has the advantage there
<rgr[m]>
Isn't recursion a problem for the inliner? Also, doing it with a ref introduces the write barrier, doesn't it?
<Drup>
rgr[m]: defining a walk over oseq/iter is very easy: it's almost like for lists, except you sparkle with thunks where the typer tells you
<Drup>
same for lazylists
<rgr[m]>
Drup: same for Sequence. Use Sequence.next and it's basically oseq
<Drup>
defining a walk over Base.Sequence.t doesn't seem easy at all
<companion_cube>
rgr[m]: I'd like to know more about how the inliner works, honestly
<Drup>
rgr[m]: that's only for construction, not deconstruction
<companion_cube>
I'd hope it gets better on seq if seq become standard
<Drup>
err, for deconstruction, not construction
malc_ has left #ocaml ["ERC (IRC client for Emacs 27.0.50)"]
<Drup>
for construction, I guess you are supposed to use Base.Sequence.Generator and a monadic API ? so yeah, not nearly as easy
<Drup>
and the perfs are very similar anyway ...
<companion_cube>
does Base.Sequence.Generator incur perf overhead?
<rgr[m]>
well you have `shift_right` for `cons`
<rgr[m]>
but yeah, I'd recommend using Sequence.Generator
<Drup>
wait, what's the semantics of >>= for generator ?
<Drup>
because, if that's just a depth-first, let rec traverse_bst = function | Empty -> return () |Branch (left, value, right) -> Oseq.append (traverse_bst left) @@ OSeq.cons value (traverse_bst right)
<Drup>
there is nothing interesting about this
<Drup>
You don't need a monadic interface or anything, you only need append
<companion_cube>
Drup: except for perf
<companion_cube>
append is a bit more expensive I think
<companion_cube>
which is why I use a stack in the stdlib's PR
<Drup>
companion_cube: compared to the Generator version ? That seems unlikely
<Drup>
As we say: [reference needed]
<companion_cube>
yeah, I don't know
<rgr[m]>
Not only that but your example isn't as lazy. You have more traverse_bst calls than necessary just to yield 1 element
<Drup>
by real, I mean "the one I posted, but that actually typechecks)
<rgr[m]>
Btw Drup it's definitely slower than >>= and yield. As those are constant time in Sequence.Generator.
<Drup>
rgr[m]: but run isn't, isn't it ?
<rgr[m]>
But there's no magic, I'm sure your'e paying for it elsewhere
<Drup>
yeah, you are paying it all in run
<rgr[m]>
Still, what you're doing looks fishier
Pierpa has quit [Ping timeout: 260 seconds]
<rgr[m]>
I wonder if you're getting quadratic behavior from the recursive append
<Drup>
No you don't =')
<Drup>
That's the point of using lazy streams
<rgr[m]>
Btw, still Sequence.Generator will be faster if you consume the stream partially
<companion_cube>
I also wonder though, there are nested `append`
<rgr[m]>
I don't think you will pay for `run` in the elements that you don't consume
<Drup>
rgr[m]: but append is constant time as well
<companion_cube>
you must pay for them somehow, rgr[m]
<rgr[m]>
companion_cube: why? if you don't consume them you simply let the closure gc
gtrak has quit [Ping timeout: 256 seconds]
<rgr[m]>
Drup: ah yes, that's true
<companion_cube>
with Drup's version you should pay upfront for the traversal of the left branch of the tree, or something like that
<Drup>
rgr[m]: I mean, if you were to give me *any* generator, I would use append/cons as well
<Drup>
generator/iterator
<rgr[m]>
companion_cube: nah sequence also traverses left eagerly
<Drup>
depth-first tree traversal is a bit of a 101 thing ...
<companion_cube>
rgr[m]: wait, how is it possible?
<Drup>
companion_cube: if you do `take 1` it's going to unfold the left traversal
<rgr[m]>
Drup: we can do something more coomplicated :P. I've written enough python generators
<companion_cube>
ah yeah ok
<companion_cube>
got to go to work
<Drup>
rgr[m]: my point is the following: 1) perfs are so close that it doesn't matter (even tho oseq is not so well optimized) 2) OSeq's traversal are much easier to write, because you can write the naive list code with some additional "()", and in 90% of the cases, it's the right one
<Drup>
no monad and other things
<Drup>
you also have better control of where the lazyness lies, thanks to the thunks
<Drup>
(and OSeq is *much* simpler)
<rgr[m]>
Drup: Sequence has the same primtives
<rgr[m]>
shift_right = cons, append = append
<rgr[m]>
knock yourself out either way
<Drup>
rgr[m]: I'm not talking about bst traversal, I'm talking in general
<Drup>
if append/cons are all that you need, companion_cube's Sequence is going to blow everyone else ;)
<companion_cube>
heh
<rgr[m]>
Hmm, but why do you think the difference is so great? I actually think the 2 approaches are very similar
<rgr[m]>
As companion_cube said, it's a matter of keeping the state in a ref or in your type
<rgr[m]>
keeping it in your type seems to have practical advantages
<rgr[m]>
I don't think the 2 approaches have any fundamental differences
<Drup>
rgr[m]: eh, practical experience ? Manipulating state in the midle of multi-way traversals is ... not nice