-
Notifications
You must be signed in to change notification settings - Fork 16
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
Implement arrayok types #24
Conversation
Think it goes in a good direction, there are still missing use cases.
exposing all features of JS which are built on flexibility of types, and maintaining type safety are very hard to reconcile. We could introduce structs, with additional arrays with pointers to enable nil, and then while marshalling we could retrieve the value of elements which are set. That said, this all seems to me like trying to fit a square peg in a round hole. |
What do you thing about the generics approach? You can define the type for anything you want and use it the same way it uses strings and float64. |
I added another case with a custom color struct , again, just as an example of what it can be done |
And last but not least, a case to reflect null values |
@MetalBlueberry HTML: <head>
<!-- Plotly.js -->
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id="myDiv"><!-- Plotly chart will be drawn inside this DIV --></div>
<script>
<!-- JAVASCRIPT CODE GOES HERE -->
</script>
</body> JS: var trace1 = {
x: [1, 2, 3, 4, 5, 6, 7, 8],
y: [10, 15, null, 17, 14, 12, 10, null, 15],
mode: 'lines+markers',
connectgaps: true
};
var trace2 = {
x: [1, 2, 3, 4, 5, 6, 7, 8],
y: [16, null, 13, 10, 8, null, 11, 12],
mode: 'lines',
connectgaps: true
};
var trace3 = {
x: [1, 2, 3, null, null, 6, 7, 8],
y: [2, 2, 2, 1, 1, 3, 3, 4],
mode: 'lines',
};
var data = [trace1, trace2, trace3];
var layout = {
title: 'Connect the Gaps Between Data',
showlegend: false
};
Plotly.newPlot('myDiv', data, layout, {showSendToCloud: true}); I'm still unsure how to achieve this. |
Damm, I will think about this |
One idea is package main
import (
"github.com/MetalBlueberry/go-plotly/graph_objects"
"github.com/MetalBlueberry/go-plotly/offline"
"github.com/MetalBlueberry/go-plotly/types"
)
func main() {
trace1 := &graph_objects.Scatter{
X: types.ArrayOK{Array: []interface{}{1, 2, 3, 4, 5, 6, 7, 8}},
Y: types.ArrayOK{Array: []interface{}{10, 15, nil, 17, 14, 12, 10, nil, 15}},
Mode: graph_objects.ScatterModeEnum.LinesMarkers,
Connectgaps: true,
}
trace2 := &graph_objects.Scatter{
X: types.ArrayOK{Array: []interface{}{1, 2, 3, 4, 5, 6, 7, 8}},
Y: types.ArrayOK{Array: []interface{}{16, nil, 13, 10, 8, nil, 11, 12}},
Mode: graph_objects.ScatterModeEnum.Lines,
Connectgaps: true,
}
trace3 := &graph_objects.Scatter{
X: types.ArrayOK{Array: []interface{}{1, 2, 3, nil, nil, 6, 7, 8}},
Y: types.ArrayOK{Array: []interface{}{2, 2, 2, 1, 1, 3, 3, 4}},
Mode: graph_objects.ScatterModeEnum.Lines,
}
data := []graph_objects.Trace{trace1, trace2, trace3}
layout := &graph_objects.Layout{
Title: graph_objects.LayoutTitle.Text("Connect the Gaps Between Data"),
Showlegend: false,
}
plot := offline.NewPlot(data, layout, offline.ShowLink(false), offline.LinkText(""), offline.ScrollZoom(true))
plot.SaveAsHTML("myDiv")
} But it requires interface{}. which I dont' really like So another idea is package main
import (
"github.com/MetalBlueberry/go-plotly/graph_objects"
"github.com/MetalBlueberry/go-plotly/offline"
"github.com/MetalBlueberry/go-plotly/types"
)
func main() {
x1 := []int{1, 2, 3, 4, 5, 6, 7, 8}
y1 := []*int{intPtr(10), intPtr(15), nil, intPtr(17), intPtr(14), intPtr(12), intPtr(10), nil, intPtr(15)}
trace1 := &graph_objects.Scatter{
X: types.ArrayOK{Array: x1},
Y: types.ArrayOK{Array: y1},
Mode: graph_objects.ScatterModeEnum.LinesMarkers,
Connectgaps: true,
}
x2 := []int{1, 2, 3, 4, 5, 6, 7, 8}
y2 := []*int{intPtr(16), nil, intPtr(13), intPtr(10), intPtr(8), nil, intPtr(11), intPtr(12)}
trace2 := &graph_objects.Scatter{
X: types.ArrayOK{Array: x2},
Y: types.ArrayOK{Array: y2},
Mode: graph_objects.ScatterModeEnum.Lines,
Connectgaps: true,
}
x3 := []*int{intPtr(1), intPtr(2), intPtr(3), nil, nil, intPtr(6), intPtr(7), intPtr(8)}
y3 := []int{2, 2, 2, 1, 1, 3, 3, 4}
trace3 := &graph_objects.Scatter{
X: types.ArrayOK{Array: x3},
Y: types.ArrayOK{Array: y3},
Mode: graph_objects.ScatterModeEnum.Lines,
}
data := []graph_objects.Trace{trace1, trace2, trace3}
layout := &graph_objects.Layout{
Title: graph_objects.LayoutTitle.Text("Connect the Gaps Between Data"),
Showlegend: false,
}
plot := offline.NewPlot(data, layout, offline.ShowLink(false), offline.LinkText(""), offline.ScrollZoom(true))
plot.SaveAsHTML("myDiv")
}
func intPtr(i int) *int {
return &i
} But it is horrible to read. Check the test cases for other examples |
maybe something along these lines: package main
import (
"bytes"
"encoding/json"
"fmt"
)
type Nullable interface {
isNullable()
}
type NullableFloat float64
func (g *NullableFloat) isNullable() {}
type NullableString string
func (g *NullableString) isNullable() {}
var nullables []Nullable
func main() {
num1 := NullableFloat(1)
text1 := NullableString("1")
nullables = append(nullables, nil, &num1, &text1)
buf := bytes.NewBuffer(make([]byte, 0))
enc := json.NewEncoder(buf)
err := enc.Encode(nullables)
if err != nil {
panic(err)
}
fmt.Println("nullables:", buf)
} Output:
I put it in a golang playground: |
Well, it has been a while. But i finally found time and inspiration to finish this PR. I think the arrayOK implementation meets the requirements you had when you first open the PR without loosing too much readibility and comfort. I recommend you to take a look to the examples directory to see how the arrayok type affects the schema. Thank you for opening the PR ❤️ |
Also I realised the ArrayOK is not used for X and Y values. those are data_arrays that will require a difirent implementation |
this is an attempt to implement arrayok types. This example just covers float64, but it should be easy to extrapolate to any other type.
The idea is that if the
Array
is defined, it will use that to create the json file and otherwise it will use theValue
.When using this to write code, it just introduces a small indirection with the advantage of keeping the type safety.