8 ms·
I understand the desire for it but I think this design creates problems of understandability and affordness, concentrating the syntax as much as it is done here
by throwaway4good 4y ago
I understand the desire for it but I think this design creates problems of understandability and affordness, concentrating the syntax as much as it is done here. ('Affordness' meaning the language ability to show the programmer exactly what can be constructed.)
For example, this piece of code is very short and packs a lot of functionality:
path*3 {
fill: none;
d: @pn(M 5 10 Q 5 5 8 1,
M 5 10 Q 4 5 2 4,
M 5 10 Q 6 6 8 4);
}
circle*3 {
fill: @pn(yellow, blueviolet, deeppink);
cx, cy: @pn(8 1, 2 4, 8 4);
r: .5;
}
But unless you know it by hand. The constructs @pn(...), *3, the codes 8 1, 2 4 ... or M 5 10 Q 5 5 8 1. Are not remotely obvious or intuitive. And it is not obvious what M and Q means? And what can I as programmer write instead?
I realize that some of these problems comes from SVG however they are problems none the less.
- aidos 4y agoM (MoveTo) and Q (Quadratic Bézier Curve) are part of the svg spec. They’re drawing commands. I’d agree that pn seems a little obtuse, but I guess I can see what it’s doing. Having worked with svg a lot (we build something sort of in the cad space) I can definitely see the desire for something less terse when you’re defining svgs. We end up generating svg fragments using react, for the most part, which works fairly well.
- throwaway4good 4y agoYes. Those codes are from the SVG spec as is the space vs. comma syntax. But it is really good way to program? Or is something that is done as a compromise between being able to program by hand, and have a format for drawing programs to save their files in without them being silly big.
- aidos 4y agoWell, like it or not that stuff is a) here to stay and b) familiar for people working with this tooling. Personally I find that graphics part pretty easy to read. For comparison here's a sample of a graphics stream from a PDF: Q 9469 1441 m 9549 1433 l 9549 1433 9549 1483 9469 1441 c S q In this context Q means push/save the graphics state and q is pop, but again, it's all very similar.
- throwaway4good 4y agoSure. But if you are designing something new it is fair to question whether to continue the style. An alternative is to have two representations; a binary format to be used by computers and a textual format for humans (programmers) designed for readability, maintainabilty etc.
- josefx 4y ago> In this context Q means push/save the graphics state and q is pop, but again, it's all very similar. is there a point in saving one or two letters on each command? Shld w ll g bck t th gd ld dys f C nd drp rndm lttrs?
- throwaway4good 4y agoYou will save space and make the language suitable as a format for computer programs to work directly with (saving in, sending to printer etc.). However compared to a binary version, this format probably uses 3 times as much space.
- scythe 4y agoI would imagine that any syntax transformation can't be much better (if at all) than a simple text compression algorithm, so I don't think disk size should be a design endpoint. But the amount of information that fits on one screen without scrolling is also part of readability, because understanding why something is there can be as important as understanding its literal meaning.
- samatman 4y agoBy analogy, what you're asking for is the ability to type `delete3words` instead of `d3w` in Vim. You might think you want that, what you actually want is to take an index card and write the SVG path abbreviations next to their long names, and put it by your keyboard while you work. Won't need it for long.
- quink 4y agoconst color = ["yellow", "blueviolet", "deeppink"]; const path = ["M 5 10 Q 5 5 8 1", "M 5 10 Q 4 5 2 4", "M 5 10 Q 6 6 8 4"]; const endPoint = [[8, 1], [2, 4], [8, 4]]; const BallPath = ({ n }) => ( <> <path fill="none" d={path[n]} /> <circle fill={color[n]} cx={endPoint[n][0]} cy={endPoint[n][1]} r={0.5} /> </> ); export default () => ( <svg viewBox="0 0 10 10" stroke="#000" strokeWidth=".1"> {[0, 1, 2].map((n) => (<BallPath n={n} />))} </svg> ); React yay. Combine with TypeScript for best results.
- masklinn 4y agoAt this point you might as well use closure & hiccup, it’ll be clearer and more uniform.
- quink 4y agoEverybody already knows and uses React and I had to repeat a tag name once only (barring the hidden React.Fragment). Sure it'll be clearer and more uniform, yet somehow you're typing this in English instead of Esperanto, Volapük or Toki Pona. https://hnhiring.com/search?q=hiccup https://hnhiring.com/search?q=hiccup "0 jobs found"
- samatman 4y agoIt's fine that you don't understand how the Clojure ecosystem works, but you don't. No one would bother listing hiccup, which is very little more than a convention for representing HTML. https://hnhiring.com/search?q=Clojure https://hnhiring.com/search?q=Clojure give seven hits, and I doubt HN is in the top five ways Clojurians find employment.
- quink 4y agoOK, fair enough, a search for JSX doesn't give any results either. To step back a bit though, there's 1 job with Clojure listed on my country's biggest job board. React? 3200. My whole point was trying to prove that you don't have to have something new and obscure to enable something but it's already there in something that almost everyone is using already. And then you replied that you can do it cleaner in something objectively vastly more obscure. Yes, yes you can. I'm sure you can.
- pasquinelli 4y agoi don't know it is a problem that if you don't know a language then you'll find it hard to read or write it.
- usrusr 4y agoThe path data won't be readable to the uninitiated no matter how verbose you make it. The encoding is not the mental bottleneck for reading or writing, it's the math. You'll be familiar with that encoding long before you can actually make sense of the numbers.
- vesinisa 4y agoOP should really extend his syntax with an optional verbose version of the SVG path language. It was always the reason I found typing / reading SVG files so difficult.
- usrusr 4y agoI'd actually love some alternative approaches to path description, that are translated into the common SVG path representation by a compiler. E.g. something turtle-like, where the "cursor" also has a heading and you could describe a curve like "10 degrees left, radius 50" and distances by outcome "straight on until we hit absolute y==100" (in a terse syntax of course). But a more verbose version of e.g. the arc-a? Not interested at all: those seven parameters (+2 from the implicit cursor) would not be particularly palatable even if they were all explicitly named.
- samatman 4y agoTry Pikchr! https://pikchr.org/home/doc/trunk/homepage.md https://pikchr.org/home/doc/trunk/homepage.md I'm working on a fork of it which allows classes to be added, and turns labels into <g> elements with an id attribute. Pretty great as-is, does more-or-less exactly what you want.
- usrusr 4y agoNot quite what I had in mind (seems to be more like a diagram DSL?), I'd rather stay within SVG, just with an improved experience. But thanks for sharing anyways, never heard of this and I should have. Even the name alone is awesome! (speaking of SVG experience, I've been fantasizing about an SVG editor that would, in a mouseover on path numbers, preview what would change if that value would wiggle a little up and down. Does anything like this exist?)
- maegul 4y agoI was thinking the same thing as I was reading the code but realised that I'd worked out what it was doing pretty much as I was critiquing it. Not sure about the "pn" in "@pn" though ... does it come from something I'm not familiar with? And as others have said, I knew the M .. Q stuff was SVG anyhow (not that I know it off the top of my head) ... generally the syntax seems nice TBH
- layer8 4y ago> affordness I believe you mean affordance.
- padolsey 4y ago> they are problems none the less I think this depends a lot on who the syntax is tailored towards. This compact stuff reminds me of APL and aspects of Perl. There's nothing wrong with highly specialised brevity. I personally love this syntax, coming from a place of moderate SVG knowledge and CSS fluency. Looks really cool and quick for prototypes. And even the example you posted feels mostly parseable on the first few scans. Nothing insurmountable, and in tune with most other news syntaxes and abstractions in this space tbh.
- specialist 4y agoThe @pn(...) construct is very interesting, compelling, worth chewing on. I too have a pet DSL project for graphs. Think JSON, QML, etc. A central design problem is divining a single syntax for both "groves" (nested objects decorated with key/value pairs) and tabular data. Asked another way: How would you inline CSV snippets within JSON? Parenthesis are used for function parameters. Curly brackets are used for composition: parent { child { key value, key value } } Square brackets are used for arrays: parent { array [1 2 3] }} How to simply encode tables (matrices)? Nested arrays? Like: table [ [1 2 3] [4 5 6] ] Is there another character or lexeme to use? Maybe delimit rows with pipe char? Like [ 1 2 3 | 4 5 6 ]
- samatman 4y agoI'd suggest not painting yourself into a corner where your map has to be either key/value or an array. Lua got this right, most other languages didn't. It's an anti-feature, especially from a data modeling perspective. Treating indices as implicit is good, pretending integer indices are special, and must be separated from all other sorts of mapping, is not. Consider that Lua can express XML without making up a fake key for children: {tag = xml, attr = {...}, child1, child2, child3}
- specialist 4y agoTotally agree. In my hobby DSL, those inlined childX are syntactic sugar for parent{ children=[child1, child2, child3]}. More generally, I remain uncomfortably undecided about named params (pairs) and indexed params. Esp wrt constructors. IIRC, I spotted a (hobby?) language that permitted both indexed params (matched in order per method signature) and named params, plus default values. So given "method( int a=10, int b=20)" you could invoke as "method( 1, 2 )", out of order like "method( b: 2, a: 1)" or partially like "method( b: 2 )". Riffing a bit, this could then allow passing a map of params to a method. Code construction wise, that looks like passing around a context object. I'll look at Lua again. (It's been a minute.) Thanks.
- samatman 4y agoIf one is writing SVG by hand, there's no alternative to learning the path language. It's the primitive, everything else is based on it. It could be made longer, but then a week later you would want it to be shorter, which it already is.
- jerf 4y agoI think the real question for this whole thread is, how many SVG files are there that operate solely on integers, or could plausibly be reconstructed as such? Once my SVG file is full of 6.829347908723890's, who cares if it is an M or a Move in terms of being human-writable? And being a vector-based format, there is indeed a real difference between 6.83 and 6.829347908723890 so there isn't a great escape from numbers that a human will find excessively precise. Honestly even the two digits is already getting up there when you see it in a big table with a thousand other numbers. XML is verbose enough to add significant verbosity to the SVG file even in the presence of floating point numbers rendered as strings, but these sort of cute little "M 5 10 Q 5 5 8 1," go too far the other way. SVG files don't look like that. SVGs aren't human-writable at any sort of scale anyhow. (Here, "at scale" means in the general case. Sure, you can construct an SVG by hand if you like, but that will never be the way they are primarily generated. They will be primarily generated in tools.) If you conclude from that that using a serialization format optimized for human readability was sort of silly... I agree! But it isn't XML's verbosity making SVGs human unwritable at scale, it's the problem space itself. Nobody wants to be typing in all these numbers. Even if you reduce the cost of the non-number stuff to literally zero and stipulate literal mind reading from the rest of the spec, it would still be impractical to hand-write SVGs in the general case.