mark-gerarts/perfect-fifth

[Question] ts2fable on p5.ts

Closed this issue · 5 comments

anpin commented

Hi @mark-gerarts, thank you for your effort, glad I'm not the only one who looks into using f# for some "creative coding". I'm curious if you have tried to use ts2fable on p5.ts to eliminate manual labor from making the interop?

I'm glad as well!

I originally started out by researching ts2fable, but ultimately decided against it for a few reasons.

First off, ts2fable doesn't work out-of-the-box on the p5js TypeScript bindings. There is some manual labour needed, as explained in this wonderful response on an issue I opened.

Secondly, p5js functions use a lot of optional and nullable variables, and variables that can have multiple types. A few years ago, @aolney created a demo project that was based on a ts2fable conversion (it was the inspiration for this project actually!). As you can see in the basic template, there are a lot of extra things going on, e.g.

  • p.mouseIsPressed |> unbox<bool>
  • p.fill(0.0 |> U4.Case1)
  • p.rect(...) |> ignore

Manually creating the bindings results in somewhat "cleaner" code, without unboxing, ignoring, and unnamed unions.

For example, to create a point in p5js, you have a single function with the following options:

  • point(x, y, [z])
  • point(coordinate_vector)

Which I chose to implement as 3 separate functions wihtout nullable arguments: point, point3D, and pointFromVector.

In the same vein, lastly, the manual process allows for some more functional alternatives where possible. Color functions (e.g. fill) can be called in a lot of different ways in p5js, again by overloading the parameters. The can be represented with a union type instead:

type Color =
    | RGB of r: float * g: float * b: float
    | RGBA of r: float * g: float * b: float * a: float
    | Grayscale of intensity: float
    | GrayscaleA of intensity: float * alpha: float
    | Name of string
    | Values of float seq
    | P5Color of P5Color

I have to concede that creating the bindings manually is a lot of work, and not something that I can finish quickly since my time is limited until the summer. So if there are alternative solutions, I'd definitely be happy to hear them!

anpin commented

Thank you for thorough explanation. I will start playing with this project then. In case I find this approach entertaining and will stumble upon uncovered API would you be open to PR's?

On a side note, I'm very curious if it would be possible to combine fable repl with this library to achieve "creative coding ide for f#" in a static webpage. Similar to how p5 web editor works.

Any PRs or even just remarks/suggestions are very welcome! Keep in mind that you best clone this repository, as the version on nuget is outdated. I haven't done any research yet to check if nuget updates can be pushed automatically, so for now it'll only get updated sporadically.

A Fable repl with this package is a really nice idea indeed. I think it would be pretty straightforward to fork the repl project and add a dependency. The harder part would be to host it somewhere. Food for thought once the implementation work is done.

anpin commented

Already made a fork, ported it to net7/fable4 and started a boilerplate project with vite server which updates very fast, will keep tinkering. thanks for your effort again!

I look forward to the PR('s) then 🙂 Definitely also interested in the boilerplate project