List.Range and Svg

Hi folks!

I am using Elm for a new project. THANK YOU for this wonderful language! I just wanted to give you a quick feedback on a few things that may (or may not) improve the language.

  1. Should List.range : Int -> Int -> List Int be List.range : number -> number -> List number instead? Because we often want to do computations with this sample of numbers.

  2. The elm/svg is ok, we can build stuff, but the api is a bit rough. All the Svg.Attributes take String as a parameter, but it’s often not the most practical type. For example, when working with viewBox/width/height, we really want a number 99% of the time.

  3. The Svg.Attributes is bloated with stuff (see: https://package.elm-lang.org/packages/elm/svg/latest/Svg-Attributes). Maybe it could make more sense to use a different package structure. For example, Svg.Circle exposing (circle, cx, cy, r). The current Html api works really well, but Svg is a different beast.

  4. xlink:href is deprecated: https://css-tricks.com/on-xlinkhref-being-deprecated-in-svg/

So here is my humble feedback. I am just trying to be constructive and to report what I felt was not so smooth working with Elm.

1 Like

Hi @jonohovon! I think you’re absolutely right that the current elm/svg package is a bit awkward to work with, but as discussed in the package description:

This package should only change to account for new SVG tags and attributes.

Just like elm/html , this package is designed to be predictable. Every node takes two arguments (a list of attributes and a list of children) even though in many cases it is possible to do something nicer. So if you want nice helpers for simple shapes (for example) I recommend creating a separate package that builds upon this one.

There are indeed packages that build on elm/svg to provide a nicer, more type-safe interface, the main one probably being elm-community/typed-svg. (There’s also my own ianmackenzie/elm-geometry-svg, and several others if you search the package web site.)

How would this work? For example, what would List.range 0.1 0.5 return? For non-integers you need to specify something like a maximum step size to take between numbers, or the total number of steps to take; I’ve taken the latter approach in my elm-float-extra package, which has a range function with the signature

range : { start : Float, end : Float, steps : Int } -> List Float

For example:

Float.Extra.range { start = 2, end = 3, steps = 5 }
--> [ 2, 2.2, 2.4, 2.6, 2.8, 3 ]
2 Likes

Thanks for your message @ianmackenzie!

Sorry, List.range : number -> number -> List number was a weird idea. :cold_sweat: What I really wanted to do: List.range : Int -> Int -> List number, so I can for example: List.range 1 10 |> List.map ((*) 0.5) without having to |> List.map toFloat.

Thanks for telling me about alternatives to the standard Svg package. Still I think it would be cool to have a nicer api built in (like elm/html that sometimes uses Int or Bool and not String everywhere), but I understand that some folks find the current api just fine and predictable. :slightly_smiling_face:

1 Like

Functional composition keeps it pretty compact though if you want to create a list of floats:

List.range 1 10 |> List.map (toFloat >> (*) 0.5)

2 Likes

There is an issue already open in the library: https://github.com/elm/svg/issues/22 , according to the latest comment the deprecated property is still applicable for Safari, if there is any update on this matter, sharing it on the issue would be helpful.

This is not possible (as Int -> number is not possible). But what might be of interest to you is something like List.range 1 10 |> List.map (toFloat >> (*) 0.5)

1 Like

SVG is a big API for sure, and it is not really obvious how best to turn it into something nicer.

With reference to @ianmackenzie’s reply above about elm-community/typed-svg and ianmackenzie/elm-geometry combined with ianmackenzie/elm-geometry-svg

I find it hard to decide if less big packages or more small packages makes a better API in Elm. Lots of small ones seems to require more maintenance of your imports, one big one can be convenient but overwhelming.

The typed-svg package aims to provide a typed SVG API that otherwise reflects the warts-and-all nature of SVG. The modules are split into Attributes, Events and a root package for all the different SVG node constructors - like how elm/html is arranged.

Ian’s elm-geometry is split into modules that are specialised to particular geometric shapes like lines, circles, arcs and so on. I think you may have a better experience using this package.

import Html exposing (..) makes sense, but Svg is more like a toolbox where you pick what you need and what you know, like in Photoshop or Illustrator (it could be helpful to look at how things are organized in graphics editors), but most of the time you just need a subset of the api, something like import Html.Line exposing (line, x1, y1, x2, y2).

Some obvious sub-packages:

  • Rectangle
  • Circle
  • Ellipse
  • Line
  • Polyline
  • Polygon
  • Path
  • Text
  • Filters
  • Gradients
  • And so.

Yes, it’s not easy to find a nice package structure (we often tend to over-design things).

But when working with the current api, you need to rely heavily on the SVG specs to make sure you do the right thing, because you can easily mismatch attributes, like import Svg.Attributes exposing (x, y, r) then circle [ x "1", y "1", r "1" ] [], but circle needed cx, cy and not x, y.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.