-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stream chaining with encore primitive type #416
Stream chaining with encore primitive type #416
Conversation
I reject this for the reasons we have discussed numerous times. The function |
end | ||
nexta = embed (Stream A) scons_next(encore_ctx(),(scons_t*)#{scons}); end | ||
in chain3args(nexta, nextb, f) | ||
in futa ~~>fscons |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The resulting future is never actually used. The code seems to be using future chaining for a side effect, rather than functionally, which seems very wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You want to write a function from scons<a>
to scons<b>
which
- Creates a new
scons<b>
object. - Checks whether the
scons<a>
element corresponds to the end-of-stream or not. - If it corresponds to the end of the stream, create an end-of-stream
scons<b>
and return it. - Otherwise:
- Applies
f
to the data in thescons<a>
object and stores that in thescons<b>
object. - Recursively does stream chaining on the
stream
element ofscons<a>
producing the stream element ofscons<b>
and stores that result in thescons<b>
object. - Returns the resulting
scons<b>
object.
And chain this function onto the head of the stream using future chaining and some under-the-hood type conversions.
I have been debugging the functional version, the bug is related to But the commit includes the def chainR(sa:Stream A, f:A->B) : Stream B {
let
futa = embed (Fut Scons<A>) (future_t*)#{sa}; end
sb = embed (Stream B) (stream_t*)stream_mk(encore_ctx()); end
fscons = \(scons:Scons<A>) ->
if (embed bool scons_eos(encore_ctx(),(struct scons*)#{scons}); end) then
embed Scons<B> (void*)scons_end(encore_ctx()); end
else
let va = embed A scons_element(encore_ctx(),(struct scons*)#{scons}).i; end in
let nexta = embed Stream A scons_next(encore_ctx(),(struct scons*)#{scons}); end in
let nextb = chain(nexta,f)
in
let currb = sb in
let vb = f(va) in
embed Scons<B>
struct scons* scons = scons_put_fut(encore_ctx(),#{nextb},#{currb},(encore_arg_t) {.d =#{vb}},ENCORE_PRIMITIVE);
(void*)scons;
end
futb = futa ~~> fscons
in (embed Stream B (stream_t*)#{futb}; end)
} |
In the code snippet above, |
I am very sorry for my premature code. The revised version still raises the same error as I posted in previous comment :( |
@PhucVH888 let
x = …
y = …
…
z = …
in {
…
} rather than: let x = … in
let y = … in
…
let z = … in {
…
} |
@TobiasWrigstad: There is also the midway:
(note the lack of |
@TobiasWrigstad Sometimes the variable
But I will try with your solution or at least the midway solution. |
@EliasC True! But I prefer the |
@PhucVH888 |
You have given me permission to reimplement a similar syntactic sugar on top of the new syntax :) |
Just as long as that syntax is I think? |
@TobiasWrigstad: +1 |
typedef A = int | ||
typedef B = real | ||
|
||
passive class Scons<t>{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@albertnetymk @EliasC I believe that if we have a parametric type that is not assigned to a field, then there won't be any generated tracing function for the parametric type t
. I believe that, in practice, this means that an Scons<a>
(or Scons<String>
) is not tracing the parametric type (or the String
). This could explain some of the GC crashes that you see @PhucVH888. Could @albertnetymk or @EliasC confirm this thought?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is a "hidden" field in the class, i.e. if the type is used to store some embedded thing, this will not be traced. It could definitely explain some crashes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I am fully following. A small failing example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the example is compiling @PhucVH888's code and realising that whatever he puts in the Scons
class is not going to be traced. You should copy paste the Encore code of this PR, generate C code and look at the Scons.encore.c
file. The Scons
generated class has an empty trace function. If @PhucVH888 puts something in the Scons
, it won't be traced
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This raises an issue. How does one talk about C data structures in Encore without messing up things like tracing.
Phuc's code manipulates a C data structure called scons
by creating an class SCons
to mask the underlying C pointer and allow it to be manipulated in Encore. But this seems to be the cause of the problem.
I have fixed the embedded type issue with embedded code to temporarily workaround. In addition, the commit is also passed all the tests with different sizes of input (5, 5.000, 1.000.000, 4.000.000) as well as the repeated tests in 100.000 times with 5.000 elements. |
scons; | ||
end; | ||
} | ||
-- futb = futa ~~> fscons |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove comment
The best thing is to redo this pull request after rebasing. |
In addition, all the testing code should be removed from the bundle implementing stream chaining, and put into a separate file. |
The commit has reflected all the comments aforementioned. |
ctx = pony_ctx(); | ||
struct scons *scons = scons_mk(ctx, NULL); | ||
scons->eos = true; | ||
// scons->next = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment can be removed.
|
||
typedef A = int | ||
typedef B = real | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps defining and using typedef SCons = embed struct scons* end
would make the rest of the code a little more readable. (It would also test out typedefs a little more.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you make the chain function work on int -> int
typed parameters rather than int -> real
, we will be able to create pipelines of stream transformers etc.
Thanks @supercooldave . The code has been revised. |
print(get sa1); | ||
sa1 = getNext sa1; | ||
}; | ||
if eos sa1 then print "EOS"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If statement is not required.
In building, the compiler complains Edit: How come CI builds? |
After removing |
@albertnetymk : It seems that did not happen to me. After clean up my branch, recompiling Encore shows some warnings such as |
It's normal to have the warnings related to |
This fails for me with streams of 5000 elements. Running with Encore compiled in I haven't investigated further. |
I found the reason. I would like to take it back, there is not any problem with It is because of the printing method call |
The commit has been tested with 5.000 elements and repeated tests in 100.000 times. |
The fact that updates to this were made that failed the tests suggests that a better testing strategy is required. Simply having a single file that you modify to test different cases is insufficient. For extended versions of this code, please improve how you do the testing. |
This implementation includes a chaining function with the signature
def chain(sa:Stream A, f:A->B) : Stream B
withA
andB
are type aliases oftypedef A = int
andtypedef B = real
.The
stream chaining
function basically takes advantage offuture chaining
to avoid usingget
that is related to blocking on a future.Stream chaining
attached the closuref:A->B
to thestream
to run when thestream
(orfuture scons
) is fulfilled.It immediately returns the
Stream B
that will store the result of applying closuref:A->B
. The commit works with primitive types as the baseline.