Hacker News new | past | comments | ask | show | jobs | submit | _28jh's comments login

SVG is still a stupid format. Who wants to send image data through XML? It would be like sending a raster image through a big JSON array.


Who wants to send image data through XML?

SVGs aren't image data. They're a set of instructions for recreating image data using a structured language. XML is very good for data like that.


Text-based formats like XML and JSON are good if most of your data is strings, but storing numeric data in decimal strings is both inefficient and inaccurate. That's why I think that HTML is an appropriate use of XML-like markup but perhaps vector images would need a true binary version.

However I agree with saagarjha that it is very easy to write code to emit SVG, which is nice.


And their text format is exceedingly useful if you're writing code to generate them.


I don't think it would really be any more difficult if it were binary. The only real reason to use XML is better integration with HTML, CSS and JavaScript, which is admittedly a compelling reason.

But I think he's right - it would be nice if there was a "proper" binary vector format that was widely supported.


I mean, I can write a line of Python that goes

  print(f"""<rect x="{x}" y="{y}" width="{w}" height="{h}"/>""")
I find this eminently easier than working with a binary format.


That's a pretty error prone way of writing SVGs though. In well written code you would use a strongly typed API and that API would be exactly the same for a binary format.

Think about how you write Protobuf files for example.


In the circumstances where I actually cared I would use a strongly typed language with nice wrappers, of course ;) The reason why I love SVGs is you can just belt them out from scripts and it's the easiest thing in the world. Same reason why I love GraphViz and Netpbm.


SVG is vector. So basically XML is suitable for that task.


One could conceivably make a binary format based on Messagepack or Flatbuffers for vector data, which would be much more efficient and eliminate rounding problems of converting between floats and decimal numbers in text representations.


>There are two main solutions: Use an option or maybe type or Use a nullable type

I don't get it. These are literally all exactly the same thing, all slightly varying in ergonomics and compiler support. They may differ slightly but to call them two different categories of solution is just creating a false dichotomy for yourself.

> However, the type system is a little more flexible than with option types. The type system understands that a union type is a supertype of its branches. In other words, int is a subtype of int?. That means we can pass a definitely-present-integer to something that expects a maybe-present-integer since that’s safe to do.

You can do that in Swift, despite being placed as an example of "Solution 1".

> The short answer is that, yes, it is entirely possible to live without null, and languages like Rust do.

If you can call say that Swift has "null", then you can equally say that Rust has "null"--it's called "None". The only way "None" and "null" from other languages differ is in built-in compiler support.


They're not the same. The difference is that what the article calls "nullable types" are based on commutative unions, while option types are based on non-commutative unions.

In haskell, Either a (Either b c) is distinct from Either (Either a b) c. In typescript, a | (b | c) is identical to (a | b) | c. And further, x | x is identical to x in typescript.

The upshot is that Haskell (using Either instead of Maybe for clarity) lets you have Either (Either a ()) () as distinct from Either a (), but the equivalent typescript is (a | null) | null, which is equivalent to a | (null | null) which is further equivalent to a | null.

So nullable types are less powerful than option types. I'm not certain that they're worse, because dealing with nested option types can get confusing, and maybe making them impossible to express would encourage API design that requires less thinking, but unfortunately I think it's more likely that it would lead to API design with more footguns.


> So nullable types are less powerful than option types.

They are differently powerful. Option types nest, while nullable types flatten. But nullable types subtype while option types do not.

Otherwise, I think your comment is an excellent summary of the differences.


They touch on why they're different a bit, but it's kinda subtle.

    foo(int? i) {
      if (i != null) {
        print(i + 1);
      }
    }
In that block, you can see that the compiler can understand that the null check on `i` means that it's safe to use `i` as an int within. Likewise, I can call `foo(int? i)` with `var something = 1`. `something` is an `int` and all `int`s are also `int?`s (but `int?`s aren't `int`s without guarding against nulls). By contrast, if a method takes `Optional<Integer>` then you have to wrap every `Integer` you have to call that method (with something like `Optional.of(something)`).

The author might be wrong about Swift being an example of Solution 1 (looking at Swift's nullability syntax).

But the point is that nullable types provide a bit more power because they're not just a data-structure, but a language feature. If you look at the source of `Option` in Rust, it's an enum like `Result` or (kinda) anything you could write rather than a language feature. Rust has built-in some things like the `?` "try" operator for special enums like `Option` and `Result` to unwrap them (or error), but it isn't quite the same as the null-guards in Dart/Kotlin and you still need to wrap them for functions like `Some(myVar)` rather than being able to pass `myVar` directly for an `Option<T>` parameter.

Again, they are almost the same, but they do talk about reasons for choosing Solution 2 over Solution 1. In Rust, you pattern-match like `match myVar { Some => x(); None => y() }` which is very functional, but they wanted something that felt like traditional null checks with conditionals. They note that nullable types are basically erased at runtime - an `int?` at runtime is either something like `7` or `null`. At compile time, you've checked that you're never assigning a `null` to an `int`, but the runtime doesn't need to know anything about it because the compiler has checked everything. Rust's enums aren't just a single special case, but something that you could make more complicated. Maybe you want a `SchrodingersResult` which could have `Success`, `Err`, or `Huh`. Ultimately, something like `Option` is an algebraic data type that you can compute off of - ex. pattern-match. The runtime needs to know that it's an `Option` because you can write code for that.

It is almost the same. The question is whether you create a one-off language feature for nullability and get advantages like knowing that any `int` can be assigned to an `int?` without needing to wrap it or whether you decide to create a type that works like any other type in your system like Java's `Optional`. Both are reasonable ways to go, but they have subtle differences and the article outlines a lot of those differences.


No, this is valid in languages with nullable types:

String s = null;

But this is not legal in languages without them:

String s = None;

In those languages, in order to have a value of None, it must be of type Option<String> (or whatever the syntax is), and in order to get a value of type String, you must assert its presence.

This is a fundamental difference with many ramifications. It really isn't just "the same but with better compile support".


    String s = null;
That's not possible with nullable types. The whole point of nullable types is to mark types that can be null. So this is possible:

    String? s = null;
But now it's not much different than this:

    Option<String> s = None;
My point is that these are fundamentally the same thing. The only difference is syntax, ergonomics, and compiler support.


That is legal in languages with poor null support. That statement would not be valid in Kotlin for example.


    String s = null;
This is a compile error in Dart now. We added nullable types in order to make all other types not nullable. So unless you explicitly opt in to nullability by putting "?" on the type, you can a type that does not permit null.


> No, this is valid in languages with nullable types:

> String s = null;

Only in languages with default-nullable types, (where the non-nullable form, if it exists at all, would be something like “String s!”); in languages with explicity billable types, the above is not allowed, because you would need to explictly opt-in to nullability:

  String s? = null


This comment is misleading. They may appear to be the same but they are not because in certain languages (like Rust) you are forced to handle the `Option` case when a value is `None` which guides a programmer's thinking in the direction of what to do in that situation.

Without these higher level types runtime null pointer exceptions are very common, using `Option` or `Maybe` creates a situation where these sorts of errors are a lot less likely.


> They may appear to be the same but they are not because in certain languages (like Rust) you are forced to handle the `Option` case when a value is `None` which guides a programmer's thinking in the direction of what to do in that situation.

Languages with nullable types are equally strict:

    int? maybeInt;
    maybeInt + 3; // <-- Compile error.


They're not the same, and the biggest difference is explained in the Map<int, Option<String>> example: union types merge different uses of null that you usually don't want merged.


> I don't get it. These are literally all exactly the same thing, all slightly varying in ergonomics and compiler support. They may differ slightly but to call them two different categories of solution is just creating a false dichotomy for yourself.

Option types can be nested, nullable types cannot.


That's why I laugh when I see that a language "doesn't have null."

It's more like newer languages make it hard to accidentally have a null reference error.

Nullable versus Option just seems like a semantics argument. The discussion makes sense when designing a language, but when choosing a language, it's more important to just look for "compiler makes it possible to enforce that a value isn't null."

BTW:

In Rust, calling unwrap() on an Option can panic. It's just that the compiler will prevent you from passing None to a function that expects a value.

C# has nullable scalars: (int? char? float?, ect.) They compile to a Nullable<T> struct, so you can do a lot of generalizing like you can with Option<T>.


What a waste of domain space (yes, I know they're abundant, but still.) areweaudioyet.com says nothing about its contents. areweasyncyet.rs had the right idea with the .rs domain name, but anyways, I feel like all of these would be better organized on one wiki, with one list for each category. Easier to search, edit, and hyperlink.


Who cares? There’s virtually infinite opportunities for domain names - unless you think there are better, more legitimate uses for the phrase “are we audio yet?” And it’s not like domain abandonment isn’t already handled by ICANN.


When I click a link, I want to know where I'm going. Where do you think "arewesmoothyet.com" will take you? If you guessed some Mozilla related thing purely from context, well you're also wrong. It's actually some WFH/affiliate marketing course. This was my point; domains are expensive and temporary for people who don't care. Because of this stupid joke, people actually interested in "Firefox Nightly hang telemetry visualization" or whatever have nowhere to go. One wiki, one page per topic, is all you need.


Also about half of the domains are down at this point...the smart one hoated itself on github.


The Republic of Serbia is probably async enough already…


Most would agree with you. This is not pleasant.


areweconsolidatedyet is clearly missing from the list


AreWeMetaYet however is there.


The top pattern is extremely common so comments are somewhat unnecessary since everyone would know what you're doing. In the second one, comments would be less necessary with a type annotation and perhaps a better name. Maybe "next_ptr" instead of "indirect"---all pointers are indirection, so that name is redundant. But the comments are necessary, to me at least.


All pointers are pointers too, so I don't see much of a difference between "indirect" and "next_ptr", other than the "next" part. In similar situations at my job, I've drawn a small ASCII diagram in the comments, and named the variable something like "splice_point", with a corresponding label in the diagram.


Well "next_ptr" is also a bad name, I agree, but I'm trying to name it something that indicates "this is a pointer to the 'next' pointer in the linked list".


How about next_node?


auto in function signatures is just really, really stupid.


I'm not so sure about that. Surely it would take longer to parse both branches of an if-constexpr then it would for the preprocessor to see the #if and discard half of it.


I should clarify. My comment is a statement about the ability for the compiler to reliably cache compiled object files in an incrementally compiling situation.


I wish more languages gave us a "|>" operator. Too many languages settle with dot notation, which confuses encapsulation/method calling with syntactical convenience.


This, along with inferior metaprogramming affordances, is the biggest reason pandas will never be as productive an analyst tool as R's dplyr. In R you can pipe anything into anything. In pandas you're stuck with the methods pandas gives you.

This is also why pandas API is so bloated. A lot of pandas special-case functionality, like dropping duplicate rows, can be replicated in R by chaining together more flexible and orthogonal primitives.


As someone who is now bouncing back & forth between Python and R on a weekly basis, I've been surprised (after making fun of R sometimes) how much I miss the piping when I leave R for Python. Pandas seems so inflexible by comparison, so nitpicky for little gain. I've been surprised again and again how much dplyr supports near-effortless fluency and productivity.

Never really thought I'd be writing that in a public forum.


Personally, I think R as a language is absolutely beautiful. The libraries have tons of warts, and many different styles. And there are perhaps too many object orientation systems built on it. But that you could even build multiple object oriented systems points to how powerful the language is.

I think it's functional orientation and the way that for loops are neglected make it seem completely insane to many people. But this is a far smaller fraction of people today than it was in 2000. back then, Java and C++ didn't even have lambdas. Since then, procedural languages have gained a lot the "mind-breaking" functional features of Lisp-derived languages. Python and JavaScript have become far more common. All the things that made the language of R "weird" and unusable to the Java/C++ crowd have been adopted elsewhere.


I'm not an R user, but you should try Julia for data analysis. It seems as flexibility (maybe more) than R, while also having blazing performance.

I do like Pandas concept of row indices, which I know Julia (and I believe, R) lack.


You should try using R; the real world performance is actually better than Julia in every way that matters. Yes, Julia has a better data frame object; that's why we use data.tables().

Also Wes probably got the idea for row indeces from R.


The idea for row indices 100% comes from R, as it's been in S for longer than I've been alive ;)


Tbh R's performance is only an issue when you deal with really big datasets. Most of the time R does just fine, and has a lot more libraries that Julia can ever hope to have.


I have used Julia a bit and really enjoyed it. The only reason I do not use it for work is lack of libraries. I know I could 'be the change I want to see in the world' and contribute, but given the pace of things at work I cannot fit that in on the company dime at this time...


Could you describe what kind of libraries you found lacking in Julia? I did get a feeling that lots of long-tail stuff was missing, when I was looking through Julia packages some time ago, but only in a vague "this doesn't seem that exhaustive" sense. Knowing what specifically has been found lacking would be useful.


I think the obvious limitations of Python is a big reason, but probably not the main reason why Pandas isn't orthogonal. The reason why Pandas is such an ungodly mess is because it must be, in order to be even halfway efficient. When you do try to compose things, or even have the audacity to use a python lambda or an if statement or whatever, you suddenly suffer a 100x slowdown in performance.

Julia doesn't have these problems, and I've found it so much nicer to use for data analysis. You can even call Python libs, if you really have to.


Pandas does have the .pipe() method [0], which allows you to put an arbitrary callable in a method chain, but it is a bit more cumbersome than in R.

[0] https://pandas.pydata.org/pandas-docs/stable/reference/api/p...


Except you can't actually use it, because it will kill the performance of your program.


I remember implementing the comment collapsing thing without JS, you have the "[-]" be a label for a checkbox button, and then you just use CSS to hide the sections for which the checkbox is checked.


That's true, it's more like naming your language "BlockchainScript". I could totally see someone doing that today.


"Scrypto"


I just checked and bitcoinscript.org seems to be owned by a domain parker.


Bitcoin already has a script (it's what transactions are made of) so that's not unexpected.


Oh come on, don't be pedantic. There is a term for non-physically-based rendered, it's called "rasterization". Just because it's technically incorrect doesn't mean it's any less of a colloquial term. To ignore this is to ignore how language actually works. Even the wikipedia page for Rasterization compares it with ray tracing.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: