Skip to content

Instantly share code, notes, and snippets.

@ileasile
Last active April 19, 2024 09:17
Show Gist options
  • Save ileasile/1016cf09608df8f9b7f4cfe2d64625f6 to your computer and use it in GitHub Desktop.
Save ileasile/1016cf09608df8f9b7f4cfe2d64625f6 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2024-04-17T16:15:24.704973Z",
"start_time": "2024-04-17T16:15:24.636159Z"
}
},
"source": [
"import java.util.UUID\n",
"\n",
"fun generateId() = UUID.randomUUID().toString()"
],
"outputs": [],
"execution_count": 1
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-04-17T16:15:25.246042Z",
"start_time": "2024-04-17T16:15:24.795237Z"
}
},
"cell_type": "code",
"source": [
"import kotlin.time.Duration\n",
"\n",
"class Frame(\n",
" val delayBefore: Duration,\n",
" val content: Any,\n",
")\n",
"\n",
"fun ANIMATE(frames: Iterator<Frame>) {\n",
" val displayId = generateId()\n",
"\n",
" if (!frames.hasNext()) return\n",
"\n",
" val firstFrame = frames.next()\n",
" Thread.sleep(firstFrame.delayBefore.inWholeMilliseconds)\n",
" DISPLAY(firstFrame.content, displayId)\n",
"\n",
" while (frames.hasNext()) {\n",
" val frame = frames.next()\n",
" Thread.sleep(frame.delayBefore.inWholeMilliseconds)\n",
" UPDATE_DISPLAY(frame.content, displayId)\n",
" }\n",
"}\n",
"\n",
"fun ANIMATE(sequence: Sequence<Frame>) {\n",
" ANIMATE(sequence.iterator())\n",
"}\n",
"\n",
"fun ANIMATE(iterable: Iterable<Frame>) {\n",
" ANIMATE(iterable.iterator())\n",
"}\n",
"\n",
"fun ANIMATE(firstFrame: Frame, nextFrame: (Frame) -> Frame?) {\n",
" ANIMATE(generateSequence(firstFrame, nextFrame))\n",
"}\n",
"\n",
"fun ANIMATE(nextFrame: () -> Frame?) {\n",
" ANIMATE(generateSequence(nextFrame))\n",
"}\n",
"\n",
"fun ANIMATE(delay: Duration, iterator: Iterator<Any>) {\n",
" var isFirst = true\n",
" ANIMATE(object: Iterator<Frame> {\n",
" override fun hasNext(): Boolean {\n",
" return iterator.hasNext()\n",
" }\n",
"\n",
" override fun next(): Frame {\n",
" val content = iterator.next()\n",
" return Frame(if (isFirst) Duration.ZERO else delay, content).also {\n",
" isFirst = false\n",
" }\n",
" }\n",
" })\n",
"}\n",
"\n",
"fun ANIMATE(delay: Duration, sequence: Sequence<Any>) {\n",
" ANIMATE(delay, sequence.iterator())\n",
"}\n",
"\n",
"fun ANIMATE(delay: Duration, seedValue: Any?, nextValue: (Any) -> Any?) {\n",
" ANIMATE(delay, generateSequence(seedValue, nextValue))\n",
"}\n",
"\n",
"fun ANIMATE(delay: Duration, iterable: Iterable<Any>) {\n",
" ANIMATE(delay, iterable.iterator())\n",
"}\n",
"\n",
"fun ANIMATE(framesCount: Int, delay: Duration, frameByIndex: (index: Int) -> Any) {\n",
" ANIMATE(delay, sequence {\n",
" repeat(framesCount) { frameIndex ->\n",
" yield(frameByIndex(frameIndex))\n",
" }\n",
" })\n",
"}"
],
"outputs": [],
"execution_count": 2
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-04-17T16:15:35.407139Z",
"start_time": "2024-04-17T16:15:25.248531Z"
}
},
"cell_type": "code",
"source": [
"import kotlin.time.Duration.Companion.seconds\n",
"\n",
"ANIMATE(Frame(5.seconds, 1L)) { frame ->\n",
" val ind = (frame.content as Long)\n",
" if (ind >= 100_000_000L) null\n",
" else Frame(frame.delayBefore.div(2), ind * 2L)\n",
"}"
],
"outputs": [
{
"data": {
"text/plain": [
"134217728"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"execution_count": 3
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-04-17T16:15:38.476720Z",
"start_time": "2024-04-17T16:15:35.408519Z"
}
},
"cell_type": "code",
"source": "ANIMATE(1.seconds, listOf(2, 6, \"9\", 12))",
"outputs": [
{
"data": {
"text/plain": [
"12"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"execution_count": 4
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-04-17T16:15:41.205564Z",
"start_time": "2024-04-17T16:15:38.478526Z"
}
},
"cell_type": "code",
"source": [
"import kotlin.time.Duration.Companion.milliseconds\n",
"\n",
"ANIMATE(50, 50.milliseconds) { it }"
],
"outputs": [
{
"data": {
"text/plain": [
"49"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"execution_count": 5
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-04-17T16:15:45.964156Z",
"start_time": "2024-04-17T16:15:41.208417Z"
}
},
"cell_type": "code",
"source": "%use kandy",
"outputs": [],
"execution_count": 6
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-04-17T16:15:46.179870Z",
"start_time": "2024-04-17T16:15:45.965886Z"
}
},
"cell_type": "code",
"source": [
"val ptsCount = 100\n",
"val interval = -5.0 ..5.0\n",
"\n",
"val xs = buildList<Double> {\n",
" for (i in 0 .. ptsCount) {\n",
" val pt = interval.start + (interval.endInclusive - interval.start) * i / ptsCount\n",
" add(pt)\n",
" }\n",
"}\n",
"\n",
"fun plotF(color: Color, f: (Double) -> Double) = plot {\n",
" line {\n",
" x(xs)\n",
" y(xs.map(f))\n",
" this.color = color\n",
" }\n",
"}"
],
"outputs": [],
"execution_count": 7
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-04-17T16:15:50.524152Z",
"start_time": "2024-04-17T16:15:46.180848Z"
}
},
"cell_type": "code",
"source": [
"ANIMATE(50, 70.milliseconds) { frameId ->\n",
" plotF(Color.rgb(5 * frameId, 0, 0)) { Math.abs(it * it - 0.1 * frameId) }\n",
"}"
],
"outputs": [
{
"data": {
"text/html": [
" <iframe src='about:blank' style='border:none !important;' width='600' height='400' srcdoc=\"&lt;html lang=&quot;en&quot;>\n",
" &lt;head>\n",
" &lt;meta charset=&quot;UTF-8&quot;>\n",
" &lt;style> html, body { margin: 0; overflow: hidden; } &lt;/style>\n",
" &lt;script type=&quot;text/javascript&quot; data-lets-plot-script=&quot;library&quot; src=&quot;https://cdn.jsdelivr.net/gh/JetBrains/lets-plot@v4.2.0/js-package/distr/lets-plot.min.js&quot;>&lt;/script>\n",
" &lt;/head>\n",
" &lt;body>\n",
" &lt;div id=&quot;SVbpkZ&quot;>&lt;/div>\n",
" &lt;script type=&quot;text/javascript&quot; data-lets-plot-script=&quot;plot&quot;>\n",
" var plotSpec={\n",
"&quot;mapping&quot;:{\n",
"},\n",
"&quot;data&quot;:{\n",
"},\n",
"&quot;kind&quot;:&quot;plot&quot;,\n",
"&quot;scales&quot;:[{\n",
"&quot;aesthetic&quot;:&quot;x&quot;,\n",
"&quot;limits&quot;:[null,null]\n",
"},{\n",
"&quot;aesthetic&quot;:&quot;y&quot;,\n",
"&quot;limits&quot;:[null,null]\n",
"}],\n",
"&quot;layers&quot;:[{\n",
"&quot;mapping&quot;:{\n",
"&quot;x&quot;:&quot;x&quot;,\n",
"&quot;y&quot;:&quot;y&quot;\n",
"},\n",
"&quot;stat&quot;:&quot;identity&quot;,\n",
"&quot;data&quot;:{\n",
"&quot;x&quot;:[-5.0,-4.9,-4.8,-4.7,-4.6,-4.5,-4.4,-4.3,-4.2,-4.1,-4.0,-3.9,-3.8,-3.7,-3.6,-3.5,-3.4,-3.3,-3.2,-3.1,-3.0,-2.9,-2.8,-2.7,-2.6,-2.5,-2.4,-2.3,-2.2,-2.1,-2.0,-1.9,-1.7999999999999998,-1.7000000000000002,-1.6,-1.5,-1.4,-1.2999999999999998,-1.2000000000000002,-1.1,-1.0,-0.9000000000000004,-0.7999999999999998,-0.7000000000000002,-0.5999999999999996,-0.5,-0.40000000000000036,-0.2999999999999998,-0.20000000000000018,-0.09999999999999964,0.0,0.09999999999999964,0.20000000000000018,0.2999999999999998,0.40000000000000036,0.5,0.5999999999999996,0.7000000000000002,0.7999999999999998,0.9000000000000004,1.0,1.0999999999999996,1.2000000000000002,1.2999999999999998,1.4000000000000004,1.5,1.5999999999999996,1.7000000000000002,1.7999999999999998,1.9000000000000004,2.0,2.0999999999999996,2.2,2.3,2.4000000000000004,2.5,2.5999999999999996,2.7,2.8,2.9000000000000004,3.0,3.0999999999999996,3.1999999999999993,3.3000000000000007,3.4000000000000004,3.5,3.5999999999999996,3.6999999999999993,3.8000000000000007,3.9000000000000004,4.0,4.1,4.199999999999999,4.300000000000001,4.4,4.5,4.6,4.699999999999999,4.800000000000001,4.9,5.0],\n",
"&quot;y&quot;:[20.1,19.110000000000007,18.14,17.190000000000005,16.259999999999998,15.35,14.460000000000003,13.589999999999998,12.74,11.909999999999998,11.1,10.309999999999999,9.54,8.790000000000001,8.06,7.35,6.659999999999998,5.989999999999998,5.340000000000002,4.710000000000001,4.1,3.51,2.9399999999999986,2.3900000000000006,1.8600000000000003,1.3499999999999996,0.8599999999999994,0.3899999999999988,0.05999999999999961,0.4900000000000002,0.9000000000000004,1.2900000000000005,1.660000000000001,2.01,2.34,2.6500000000000004,2.9400000000000004,3.210000000000001,3.46,3.6900000000000004,3.9000000000000004,4.09,4.260000000000001,4.41,4.540000000000001,4.65,4.74,4.8100000000000005,4.86,4.890000000000001,4.9,4.890000000000001,4.86,4.8100000000000005,4.74,4.65,4.540000000000001,4.41,4.260000000000001,4.09,3.9000000000000004,3.6900000000000013,3.46,3.210000000000001,2.9399999999999995,2.6500000000000004,2.3400000000000016,2.01,1.660000000000001,1.2899999999999991,0.9000000000000004,0.490000000000002,0.05999999999999961,0.3899999999999988,0.8600000000000012,1.3499999999999996,1.8599999999999977,2.3900000000000006,2.9399999999999986,3.5100000000000016,4.1,4.709999999999997,5.3399999999999945,5.990000000000004,6.660000000000002,7.35,8.059999999999997,8.789999999999994,9.540000000000004,10.310000000000002,11.1,11.909999999999998,12.739999999999993,13.590000000000005,14.460000000000003,15.35,16.259999999999998,17.18999999999999,18.140000000000008,19.110000000000007,20.1]\n",
"},\n",
"&quot;color&quot;:&quot;#F50000&quot;,\n",
"&quot;sampling&quot;:&quot;none&quot;,\n",
"&quot;position&quot;:&quot;identity&quot;,\n",
"&quot;geom&quot;:&quot;line&quot;\n",
"}]\n",
"};\n",
" var plotContainer = document.getElementById(&quot;SVbpkZ&quot;);\n",
" LetsPlot.buildPlotFromProcessedSpecs(plotSpec, -1, -1, plotContainer);\n",
" &lt;/script>\n",
" &lt;/body>\n",
"&lt;/html>\"></iframe> <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" class=\"plt-container\" id=5fea2552-2435-4a78-a8a7-4aee2f306a93 width=\"100%\" height=\"100%\" style=\"max-width: 600.0px; max-height: 400.0px;\" viewBox=\"0 0 600.0 400.0\" preserveAspectRatio=\"xMinYMin meet\">\n",
" <style type=\"text/css\">\n",
" .plt-container {\n",
" font-family: Lucida Grande, sans-serif;\n",
" user-select: none;\n",
" -webkit-user-select: none;\n",
" -moz-user-select: none;\n",
" -ms-user-select: none;\n",
"}\n",
"text {\n",
" text-rendering: optimizeLegibility;\n",
"}\n",
"#peZ5DAq .plot-title {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 16.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .plot-subtitle {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 15.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .plot-caption {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .legend-title {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 15.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .legend-item {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .axis-title-x {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 15.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .axis-text-x {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#dKDKS4s .axis-tooltip-text-x {\n",
" fill: #ffffff;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .axis-title-y {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 15.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .axis-text-y {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#dKDKS4s .axis-tooltip-text-y {\n",
" fill: #ffffff;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .facet-strip-text-x {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#peZ5DAq .facet-strip-text-y {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#dKDKS4s .tooltip-text {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: normal;\n",
" font-style: normal; \n",
"}\n",
"#dKDKS4s .tooltip-title {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: bold;\n",
" font-style: normal; \n",
"}\n",
"#dKDKS4s .tooltip-label {\n",
" fill: #474747;\n",
" font-family: Lucida Grande, sans-serif;\n",
" font-size: 13.0px;\n",
" font-weight: bold;\n",
" font-style: normal; \n",
"}\n",
"\n",
" </style>\n",
" <g id=\"peZ5DAq\">\n",
" <path fill-rule=\"evenodd\" fill=\"rgb(255,255,255)\" fill-opacity=\"1.0\" d=\"M0.0 0.0 L0.0 400.0 L600.0 400.0 L600.0 0.0 Z\">\n",
" </path>\n",
" <g transform=\"translate(23.0 10.0 ) \">\n",
" <g transform=\"translate(21.961210910936405 0.0 ) \">\n",
" <line x1=\"74.32347123941776\" y1=\"344.0\" x2=\"74.32347123941776\" y2=\"-5.6843418860808015E-14\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"173.42143289197477\" y1=\"344.0\" x2=\"173.42143289197477\" y2=\"-5.6843418860808015E-14\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"272.5193945445318\" y1=\"344.0\" x2=\"272.5193945445318\" y2=\"-5.6843418860808015E-14\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"371.61735619708884\" y1=\"344.0\" x2=\"371.61735619708884\" y2=\"-5.6843418860808015E-14\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"470.7153178496458\" y1=\"344.0\" x2=\"470.7153178496458\" y2=\"-5.6843418860808015E-14\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" </g>\n",
" <g transform=\"translate(21.961210910936405 344.0 ) \">\n",
" <g transform=\"translate(74.32347123941776 0.0 ) \">\n",
" <line stroke-width=\"1.0\" stroke=\"rgb(71,71,71)\" stroke-opacity=\"1.0\" x2=\"0.0\" y2=\"4.0\">\n",
" </line>\n",
" <g transform=\"translate(0.0 7.0 ) \">\n",
" <text class=\"axis-text-x\" text-anchor=\"middle\" dy=\"0.7em\">\n",
" <tspan>-4</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(173.42143289197477 0.0 ) \">\n",
" <line stroke-width=\"1.0\" stroke=\"rgb(71,71,71)\" stroke-opacity=\"1.0\" x2=\"0.0\" y2=\"4.0\">\n",
" </line>\n",
" <g transform=\"translate(0.0 7.0 ) \">\n",
" <text class=\"axis-text-x\" text-anchor=\"middle\" dy=\"0.7em\">\n",
" <tspan>-2</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(272.5193945445318 0.0 ) \">\n",
" <line stroke-width=\"1.0\" stroke=\"rgb(71,71,71)\" stroke-opacity=\"1.0\" x2=\"0.0\" y2=\"4.0\">\n",
" </line>\n",
" <g transform=\"translate(0.0 7.0 ) \">\n",
" <text class=\"axis-text-x\" text-anchor=\"middle\" dy=\"0.7em\">\n",
" <tspan>0</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(371.61735619708884 0.0 ) \">\n",
" <line stroke-width=\"1.0\" stroke=\"rgb(71,71,71)\" stroke-opacity=\"1.0\" x2=\"0.0\" y2=\"4.0\">\n",
" </line>\n",
" <g transform=\"translate(0.0 7.0 ) \">\n",
" <text class=\"axis-text-x\" text-anchor=\"middle\" dy=\"0.7em\">\n",
" <tspan>2</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(470.7153178496458 0.0 ) \">\n",
" <line stroke-width=\"1.0\" stroke=\"rgb(71,71,71)\" stroke-opacity=\"1.0\" x2=\"0.0\" y2=\"4.0\">\n",
" </line>\n",
" <g transform=\"translate(0.0 7.0 ) \">\n",
" <text class=\"axis-text-x\" text-anchor=\"middle\" dy=\"0.7em\">\n",
" <tspan>4</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <line x1=\"0.0\" y1=\"0.0\" x2=\"545.0387890890636\" y2=\"0.0\" stroke-width=\"1.0\" stroke=\"rgb(71,71,71)\" stroke-opacity=\"1.0\">\n",
" </line>\n",
" </g>\n",
" <g transform=\"translate(21.961210910936405 0.0 ) \">\n",
" <line x1=\"0.0\" y1=\"329.2999455634186\" x2=\"545.0387890890636\" y2=\"329.2999455634186\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"0.0\" y1=\"251.27417891489745\" x2=\"545.0387890890636\" y2=\"251.27417891489745\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"0.0\" y1=\"173.2484122663763\" x2=\"545.0387890890636\" y2=\"173.2484122663763\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"0.0\" y1=\"95.22264561785516\" x2=\"545.0387890890636\" y2=\"95.22264561785516\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" <line x1=\"0.0\" y1=\"17.196878969334023\" x2=\"545.0387890890636\" y2=\"17.196878969334023\" stroke=\"rgb(233,233,233)\" stroke-opacity=\"1.0\" stroke-width=\"1.0\" fill=\"none\">\n",
" </line>\n",
" </g>\n",
" <g transform=\"translate(21.961210910936405 0.0 ) \">\n",
" <g transform=\"translate(0.0 329.2999455634186 ) \">\n",
" <g transform=\"translate(-3.0 0.0 ) \">\n",
" <text class=\"axis-text-y\" text-anchor=\"end\" dy=\"0.35em\">\n",
" <tspan>0</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(0.0 251.27417891489745 ) \">\n",
" <g transform=\"translate(-3.0 0.0 ) \">\n",
" <text class=\"axis-text-y\" text-anchor=\"end\" dy=\"0.35em\">\n",
" <tspan>5</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(0.0 173.2484122663763 ) \">\n",
" <g transform=\"translate(-3.0 0.0 ) \">\n",
" <text class=\"axis-text-y\" text-anchor=\"end\" dy=\"0.35em\">\n",
" <tspan>10</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(0.0 95.22264561785516 ) \">\n",
" <g transform=\"translate(-3.0 0.0 ) \">\n",
" <text class=\"axis-text-y\" text-anchor=\"end\" dy=\"0.35em\">\n",
" <tspan>15</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(0.0 17.196878969334023 ) \">\n",
" <g transform=\"translate(-3.0 0.0 ) \">\n",
" <text class=\"axis-text-y\" text-anchor=\"end\" dy=\"0.35em\">\n",
" <tspan>20</tspan>\n",
" </text>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(21.961210910936405 0.0 ) \" clip-path=\"url(#c7fYb3C)\" clip-bounds-jfx=\"[rect (0.0, 0.0), (545.0387890890636, 344.0)]\">\n",
" <defs>\n",
" <clipPath id=\"c7fYb3C\">\n",
" <rect x=\"0.0\" y=\"0.0\" width=\"545.0387890890636\" height=\"344.0\">\n",
" </rect>\n",
" </clipPath>\n",
" </defs>\n",
" <g>\n",
" <path d=\"M24.774490413139233 15.63636363636357 L24.774490413139233 15.63636363636357 L29.72938849576707 31.085465432770718 L34.68428657839496 46.22246416258389 L39.639184661022796 61.04735982580286 L44.59408274365066 75.56015242242788 L49.548980826278495 89.76084195245869 L54.50387890890633 103.64942841589541 L59.45877699153422 117.22591181273816 L64.41367507416206 130.49029214298673 L69.36857315678992 143.44256940664127 L74.32347123941776 156.08274360370166 L79.27836932204562 168.410814734168 L84.23326740467346 180.42678279804028 L89.18816548730129 192.13064779531842 L94.14306356992915 203.5224097260025 L99.09796165255702 214.60206859009253 L104.05285973518485 225.36962438758846 L109.00775781781272 235.8250771184903 L113.96265590044055 245.968426782798 L118.91755398306842 255.79967338051165 L123.87245206569628 265.31881691163125 L128.82735014832411 274.52585737615675 L133.78224823095198 283.42079477408817 L138.7371463135798 292.0036291054255 L143.69204439620768 300.2743603701687 L148.6469424788355 308.23298856831786 L153.60184056146338 315.879513699873 L158.55673864409124 323.21393576483393 L163.51163672671908 328.3636363636363 L168.4665348093469 321.65342043186354 L173.42143289197477 315.2553075666848 L178.37633097460264 309.16929776810014 L183.33122905723047 303.3953910361096 L188.2861271398583 297.9335873707131 L193.24102522248617 292.7838867719107 L198.19592330511404 287.94628923970237 L203.15082138774187 283.42079477408817 L208.10571947036973 279.207403375068 L213.06061755299757 275.306115042642 L218.01551563562543 271.71692977681 L222.97041371825327 268.4398475775721 L227.9253118008811 265.4748684449283 L232.880209883509 262.8219923788786 L237.83510796613683 260.48121937942295 L242.7900060487647 258.45254944656136 L247.74490413139253 256.7359825802939 L252.69980221402037 255.33151878062054 L257.65470029664823 254.23915804754125 L262.60959837927606 253.45890038105603 L267.56449646190396 252.9907457811649 L272.5193945445318 252.83469424786787 L277.4742926271596 252.9907457811649 L282.4291907097875 253.45890038105603 L287.38408879241535 254.23915804754125 L292.3389868750432 255.33151878062054 L297.293884957671 256.7359825802939 L302.24878304029886 258.45254944656136 L307.20368112292675 260.48121937942295 L312.1585792055546 262.8219923788786 L317.1134772881825 265.4748684449283 L322.0683753708103 268.4398475775721 L327.02327345343815 271.71692977681 L331.97817153606604 275.306115042642 L336.9330696186938 279.207403375068 L341.8879677013217 283.42079477408817 L346.84286578394955 287.94628923970237 L351.7977638665774 292.78388677191066 L356.7526619492053 297.9335873707131 L361.7075600318331 303.3953910361096 L366.66245811446095 309.16929776810014 L371.61735619708884 315.2553075666848 L376.5722542797166 321.6534204318635 L381.5271523623445 328.3636363636363 L386.48205044497234 323.21393576483393 L391.43694852760024 315.8795136998729 L396.3918466102281 308.23298856831786 L401.3467446928559 300.2743603701688 L406.30164277548374 292.0036291054255 L411.25654085811163 283.42079477408817 L416.2114389407395 274.52585737615675 L421.1663370233673 265.31881691163125 L426.12123510599514 255.7996733805117 L431.076133188623 245.96842678279808 L436.03103127125087 235.82507711849019 L440.98592935387876 225.3696243875884 L445.94082743650654 214.60206859009253 L450.89572551913443 203.52240972600256 L455.8506236017622 192.1306477953185 L460.80552168439016 180.4267827980402 L465.760419767018 168.41081473416796 L470.7153178496458 156.08274360370166 L475.67021593227366 143.44256940664127 L480.6251140149015 130.49029214298685 L485.58001209752945 117.22591181273805 L490.5349101801572 103.64942841589541 L495.4898082627851 89.76084195245869 L500.4447063454129 75.56015242242788 L505.3996044280408 61.047359825803085 L510.3545025106687 46.222464162583776 L515.3094005932965 31.085465432770718 L520.2642986759244 15.63636363636357 \" fill=\"none\" stroke-width=\"1.6500000000000001\" stroke=\"rgb(245,0,0)\" stroke-opacity=\"1.0\">\n",
" </path>\n",
" </g>\n",
" </g>\n",
" </g>\n",
" <g transform=\"translate(14.5 182.0 ) rotate(-90.0 ) \">\n",
" <text class=\"axis-title-y\" y=\"0.0\" text-anchor=\"middle\">\n",
" <tspan>y</tspan>\n",
" </text>\n",
" </g>\n",
" <g transform=\"translate(317.4806054554682 391.5 ) \">\n",
" <text class=\"axis-title-x\" y=\"0.0\" text-anchor=\"middle\">\n",
" <tspan>x</tspan>\n",
" </text>\n",
" </g>\n",
" <path fill=\"rgb(0,0,0)\" fill-opacity=\"0.0\" stroke=\"rgb(71,71,71)\" stroke-opacity=\"1.0\" stroke-width=\"0.0\" d=\"M0.0 0.0 L0.0 400.0 L600.0 400.0 L600.0 0.0 Z\">\n",
" </path>\n",
" </g>\n",
" <g id=\"dKDKS4s\">\n",
" </g>\n",
"</svg>\n",
" <script>document.getElementById(\"5fea2552-2435-4a78-a8a7-4aee2f306a93\").style.display = \"none\";</script>"
],
"application/plot+json": {
"output_type": "lets_plot_spec",
"output": {
"mapping": {},
"data": {},
"kind": "plot",
"scales": [
{
"aesthetic": "x",
"limits": [
null,
null
]
},
{
"aesthetic": "y",
"limits": [
null,
null
]
}
],
"layers": [
{
"mapping": {
"x": "x",
"y": "y"
},
"stat": "identity",
"data": {
"x": [
-5.0,
-4.9,
-4.8,
-4.7,
-4.6,
-4.5,
-4.4,
-4.3,
-4.2,
-4.1,
-4.0,
-3.9,
-3.8,
-3.7,
-3.6,
-3.5,
-3.4,
-3.3,
-3.2,
-3.1,
-3.0,
-2.9,
-2.8,
-2.7,
-2.6,
-2.5,
-2.4,
-2.3,
-2.2,
-2.1,
-2.0,
-1.9,
-1.8,
-1.7,
-1.6,
-1.5,
-1.4,
-1.3,
-1.2,
-1.1,
-1.0,
-0.9,
-0.8,
-0.7,
-0.6,
-0.5,
-0.4,
-0.3,
-0.2,
-0.1,
0.0,
0.1,
0.2,
0.3,
0.4,
0.5,
0.6,
0.7,
0.8,
0.9,
1.0,
1.1,
1.2,
1.3,
1.4,
1.5,
1.6,
1.7,
1.8,
1.9,
2.0,
2.1,
2.2,
2.3,
2.4,
2.5,
2.6,
2.7,
2.8,
2.9,
3.0,
3.1,
3.2,
3.3,
3.4,
3.5,
3.6,
3.7,
3.8,
3.9,
4.0,
4.1,
4.2,
4.3,
4.4,
4.5,
4.6,
4.7,
4.8,
4.9,
5.0
],
"y": [
20.1,
19.11,
18.14,
17.19,
16.26,
15.35,
14.46,
13.59,
12.74,
11.91,
11.1,
10.31,
9.54,
8.79,
8.06,
7.35,
6.66,
5.99,
5.34,
4.71,
4.1,
3.51,
2.94,
2.39,
1.86,
1.35,
0.86,
0.39,
0.06,
0.49,
0.9,
1.29,
1.66,
2.01,
2.34,
2.65,
2.94,
3.21,
3.46,
3.69,
3.9,
4.09,
4.26,
4.41,
4.54,
4.65,
4.74,
4.81,
4.86,
4.89,
4.9,
4.89,
4.86,
4.81,
4.74,
4.65,
4.54,
4.41,
4.26,
4.09,
3.9,
3.69,
3.46,
3.21,
2.94,
2.65,
2.34,
2.01,
1.66,
1.29,
0.9,
0.49,
0.06,
0.39,
0.86,
1.35,
1.86,
2.39,
2.94,
3.51,
4.1,
4.71,
5.34,
5.99,
6.66,
7.35,
8.06,
8.79,
9.54,
10.31,
11.1,
11.91,
12.74,
13.59,
14.46,
15.35,
16.26,
17.19,
18.14,
19.11,
20.1
]
},
"color": "#F50000",
"sampling": "none",
"position": "identity",
"geom": "line"
}
]
},
"apply_color_scheme": true,
"swing_enabled": true
}
},
"metadata": {},
"output_type": "display_data"
}
],
"execution_count": 8
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"source": ""
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"name": "kotlin",
"version": "1.9.23",
"mimetype": "text/x-kotlin",
"file_extension": ".kt",
"pygments_lexer": "kotlin",
"codemirror_mode": "text/x-kotlin",
"nbconvert_exporter": ""
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@ileasile
Copy link
Author

The API I currently suggest is

fun animateIterator(delayMs: Long, iterator: Iterator<Any>)
fun animateSequence(delayMs: Long, sequence: Sequence<Any>)
fun animateIterable(delayMs: Long, iterable: Iterable<Any>)
fun animate(framesCount: Int, delayMs: Long, frameFactory: (id: Int) -> Any)

Probably these should be overloads of a same function?

fun animate(delayMs: Long, iterator: Iterator<Any>)
fun animate(delayMs: Long, sequence: Sequence<Any>)
fun animate(delayMs: Long, iterable: Iterable<Any>)
fun animate(framesCount: Int, delayMs: Long, frameFactory: (id: Int) -> Any)

Probably the name itself should be different?

@belovrv
Copy link

belovrv commented Apr 14, 2024

I thought we had a convention to name such kind of functions with CAPITAL letters

@cmelchior
Copy link

cmelchior commented Apr 15, 2024

My comments:

  • I am not a big fan of using animateX. It feels unnecessary when the type is also in the argument.
  • Would it make more sense to use Duration instead of Long for the delay. That way we encode it more directly in the type, plus make it easier to define delays at different granularities like seconds.
  • frameFactory argument naming looks off. Shouldn't id be index or frameIndex?

So something like:

fun animate(delay: Duration, iterator: Iterator<Any>)
fun animate(delay: Duration, sequence: Sequence<Any>)
fun animate(delay: Duration, iterable: Iterable<Any>)
fun animate(framesCount: Int, delay: Duration, frameFactory: (index: Int) -> Any)

// or if these are capitalized pr. Romans comment

fun ANIMATE(delay: Duration, iterator: Iterator<Any>)
fun ANIMATE(delay: Duration, sequence: Sequence<Any>)
fun ANIMATE(delay: Duration, iterable: Iterable<Any>)
fun ANIMATE(framesCount: Int, delay: Duration, frameFactory: (index: Int) -> Any)

@ark-1
Copy link

ark-1 commented Apr 15, 2024

another idea:

fun <T> animate(delayMs: Long, iterable: Iterable<T>, frameFactory: (element: T) -> Any) {
    animateSequence(delayMs, sequence {
        iterable.forEach { element ->
            yield(frameFactory(element))
        }
    })
}

animate(delayMs = 50, 1..50) { it }
animate(delayMs = 50, mySnapshots) { snapshotPlot(it) }

@devcrocod
Copy link

I agree with some points from Christian:

  • add functions with Duration to existing ones
  • the name for the variable frameFactory looks strange for me

Also, we are reserving quite common name animate

@Jolanrensen
Copy link

Probably put the thing you want to animate at the first place. You maybe could even provide a default duration of 1 second or something.
Makes more sense to have ANIMATE(what, how) instead of ANIMATE(how, what). The lambda overload being the notable exception of course. The rest looks good to me!

One thing that comes to mind is making an extension function to animate an iterable... But a part of me doesn't like the idea of having TOP_LEVEL() extension functions, so it's probably fine as it is.

@nikolay-egorov
Copy link

To add more convinience, I'd say we might add some defaults for this parameters framesCount: Int, delayMs: Long

Maybe we could also add a default way of animating things with the help of our libraries / integrations.
Couple of them comes to mind:
fun animate(framesCount: Int, delayMs: Long, frameFactory: Plot.(index: Int) -> {Plot})
fun animate(framesCount: Int, delayMs: Long, frameFactory: (index: Int) -> {BufferedImage})

@ileasile
Copy link
Author

ileasile commented Apr 17, 2024

Second version of the API, more consistent with what we have

import kotlin.time.Duration

class Frame(
    val delayBefore: Duration,
    val content: Any,
)

fun ANIMATE(frames: Iterator<Frame>)
fun ANIMATE(sequence: Sequence<Frame>)
fun ANIMATE(iterable: Iterable<Frame>)
fun ANIMATE(firstFrame: Frame, nextFrame: (Frame) -> Frame?)
fun ANIMATE(nextFrame: () -> Frame?)
fun ANIMATE(delay: Duration, iterator: Iterator<Any>)
fun ANIMATE(delay: Duration, sequence: Sequence<Any>)
fun ANIMATE(delay: Duration, seedValue: Any?, nextValue: (Any) -> Any?)
fun ANIMATE(delay: Duration, nextValue: () -> Any?)
fun ANIMATE(delay: Duration, iterable: Iterable<Any>)
fun ANIMATE(framesCount: Int, delay: Duration, frameByIndex: (index: Int) -> Any)

@ark-1
Copy link

ark-1 commented Apr 17, 2024

fun ANIMATE(delay: Duration, seedValue: Any?, nextValue: (Any) -> Any?)

I suggest to add a type parameter here:

fun <T : Any> ANIMATE(delay: Duration, seedValue: T?, nextValue: (T) -> T?)

This way the user won't need to write it as Long and such.

An extension of that idea would to be to make Frame parameterized:

class Frame<out T : Any>(
    val delayBefore: Duration,
    val content: T,
)

This way me may have this:

fun <T : Any> ANIMATE(firstFrame: Frame<T>, nextFrame: (Frame<T>) -> Frame<T>?)

And Frame<*> in all other overloads. But this may be a bit over-engineered.

@ileasile
Copy link
Author

Thanks! Parametrized version is below. It indeed makes some lambdas easier to write

import kotlin.time.Duration

class Frame<T>(
    val delayBefore: Duration,
    val content: T,
)

fun <T> ANIMATE(frames: Iterator<Frame<T>>)
fun <T> ANIMATE(sequence: Sequence<Frame<T>>)
fun <T> ANIMATE(iterable: Iterable<Frame<T>>)
fun <T> ANIMATE(firstFrame: Frame<T>, nextFrame: (Frame<T>) -> Frame<T>?)
fun <T> ANIMATE(nextFrame: () -> Frame<T>?)
fun <T> ANIMATE(delay: Duration, iterator: Iterator<T>)
fun <T> ANIMATE(delay: Duration, sequence: Sequence<T>)
fun <T: Any> ANIMATE(delay: Duration, nextValue: () -> T?)
fun <T: Any> ANIMATE(delay: Duration, seedValue: T?, nextValue: (T) -> T?)
fun <T> ANIMATE(delay: Duration, iterable: Iterable<T>)
fun <T> ANIMATE(framesCount: Int, delay: Duration, frameByIndex: (index: Int) -> T)

@nikolay-egorov
Copy link

Can one of them with functional parameters be with inline modifier? Since they only serve delegating role, it may redice them without warmup

@ark-1
Copy link

ark-1 commented Apr 19, 2024

We don't actually need type parameters in any of the overloads except (firstFrame,nextFrame) and (seedValue,nextValue). They will just cause unnecessary inference problems with unclear errors, if user types something wrong or too complex, and they provide no actual benefit. We can just use Frame<*>, Any? and Any.

Also, I suggest declaring Frame as class Frame<out T>(...).

@nikolay-egorov
Copy link

nikolay-egorov commented Apr 19, 2024

True, agree with the above. * and Any? looks right as a broadest spectre

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment