HN user

joe-user

72 karma
Posts0
Comments34
View on HN
No posts found.

I think the misunderstanding is about iterators "not relying on concrete types". Rather, iterators are the concrete type. Consider the example transformation from the transducers page:

  (def xf
    (comp
      (filter odd?)
      (map inc)
      (take 5)))
You'll see there's no notion of a concrete type that the transformation operates on. It can work with vectors, seqs, core.async channels, etc. Now consider how that could be written in JavaScript such that it works on arrays, sets, generators, iterators, etc. without having to first convert to another type (such as an iterator). That is what's meant about transducers not being tied to a concrete type.
Rust is just a tool 5 months ago

I can see some interest in Fil-C, but some will still be against it due to the overhead it imposes (1.5x-4x worse performance, less deterministic since there's a GC), as well as the program will simply crash on arbitrary memory reinterpretation, use-after-free, and reading uninitialized memory. This is certainly better than it continuing, but certainly not as good as it could be.

CHERI has different characteristics in that it will crash for buffer overflows, but crashing on use-after-free is opt-in, it can only detect double-frees sometimes, it does nothing about uninitialized memory access, etc. It also requires adopting new hardware, which may be a hard sell.

In all I've mentioned above, I haven't even touched thread safety or integer safety which these do nothing about.

So with that being said, do as you please, but understand that simply adopting these is a different level of safety (program will not be exploitable but will crash) compared to something like Rust (program is not exploitable and will not crash because these issues are mostly* compile-time errors).

* "Mostly" since I mentioned integer safety which will be a runtime crash like the C safeguards, you can use unsafe, etc.

You can write portable software… and then compile it for each platform to get the best performance and functionality.

Perhaps not what you intended, but I believe this is that exactly what Cosmopolitan is doing: - They are writing portable software in that it can run on various architectures and operating systems - They compile it for each platform, even if the output is a single binary - For the best performance and functionality, they mention several examples of how Cosmopolitan outperforms the native alternatives

I'm sure there are plenty of rebuttals ("Emacs on Windows is a port", "Cygwin isn't portable", "they could make the native version of $WHATEVER more performant", "Cosmopolitan isn't always faster", etc.), all of which are well and good, but would be missing the bigger picture, which is that there are reasons for both approaches (among others!) to exist, an idea that far transcends software.

Joins can certainly work in a data format like YAML. For an example, see Honey SQL from the Clojure community [0] (though without something to contrast strings like Clojure's keywords, you miss out on the automatic parameterization).

You mentioned moving JOINs around, so I'll mention that if represented as structured data, you can move any of the top level components around, so you could more closely follow the "true order of SQL" [1]. For example, I would love to be able to put FROM before SELECT in all or almost all cases. There's also being able to share and add to something like a complicated WHERE clause, where essentially all programming languages have built-in facilities for robustly manipulating ordered and associative data compared to string manipulation, which is not well-suited for the task.

Now don't get me wrong, I don't particularly care for YAML (though it doesn't bother me that much), but as someone who's done their fair share of programmatic SQL creation and manipulation in strings, not having a native way to represent SQL as data is a mistake in my opinion.

0: https://github.com/seancorfield/honeysql#big-complicated-exa... 1: https://blog.jooq.org/a-beginners-guide-to-the-true-order-of...

Why guess when there are installation instructions for various platforms on the README at https://github.com/ggreer/the_silver_searcher#installing?

Also, although it may not be easy to remember, is this really a problem in practice given the installation count in most contexts is one? If there's a context where it's installed regularly, that's a one-time addition to an install script, Dockerfile, etc. in my experience. Do you have a situation that isn't amenable to that?

That's true, but the argument being made was one where "packages" and "packages" was the point of contention. While they're not versions as in numbers, there's plenty of existing work that have similar names, which accomplishes the same goal such as `venv`, `virtualenv`, `python-virtualenv`, `pyenv`, etc. in the Python community.

To consider that the only option is rather reductionist. For example, simply add a version, and to use the original title instead of inventing one:

99% of top Python packages are now on version 2

I have no idea how he's successful in tech, judging from what I saw there.

I think judging only from what you saw there is the issue. If you look somewhere like Wikipedia [0], you'll see he was the first person to jailbreak the iPhone, the first person to achieve hypervisor access to the PS3's CPU, he took first place in several notable CTFs (at least one time as a one-person team), he worked on Google's Project Zero team (and created a debugger called QIRA while he was there), creating comma.ai, and the list goes on.

[0] https://en.wikipedia.org/wiki/George_Hotz

REBL 3 years ago

1. It's functional!

As someone who writes more Python than Clojure these days, Python's limited lambdas are a regular source of frustration. Additionally, Clojure's first-class data structures are sorely missed in Python.

2. REPL-driven development!

The huge drawback IMHO that rarely gets discussed is the ability to change modules in Python's interactive interpreter (Clojure's analog is the namespace). For example, in the context of a web app, adding a new view in some views module, then swapping to the routes module and adding the adding a new route to wire up the view. Additionally, there's no built-in way to connect to the interpreter, as manually typing in a REPL is not the usual flow. To me this makes Python's interpreter unusable for anything but toy examples.

3. Macros!

Clojure is less macro-dependent than other lisps, but in most projects I use, there are one or two that really help clean things up. If you look to other modern languages that have macros (for example, Rust), I think the same idea applies.

Clojure can fit quite well into Spring Boot-centric environments!

I've added Clojure to several legacy Spring Boot apps, and the fact that it can be introduced as "just a library" made that portion a snap. If you're not trying to access resources related to Spring Boot's dependency injection, it's pretty straightforward to call into Clojure from Java. If you _do_ want access to DI resources, there's a small amount of code required to wire things up, though it took me a while to find out what that code was, mostly because it requires access to portions of Spring Boot that are not typically user-facing.

Since I had hooked Clojure up to the Spring apps, I also set things up so I could SSH onto application servers, then get a REPL via a socket server into the applications themselves. Being able to check and sometimes change the state of the application live at runtime was like a superpower. This proved extremely valuable, often for debugging errors in the Java portions of the code, but also for situations like final design tweaks live with a client in a development environment. Client asks to bump a font size or change a color or adjust a border or change some copy, then I make the change in my editor, send it over the socket REPL, tell the client to refresh, and repeat. When done, I would simply save, commit, and would be confident that it's what the client was after. The only downside is that I'm no longer at a shop that uses Clojure, and feedback loops for production debugging or letting clients see their decisions are measured in days or weeks when possible at all, not seconds or minutes.

I will admit that connecting to a running application is dangerous, but so is what many surgeons do, and we are certainly not going to ask them to turn in their scalpels. By being conscious of the "great power; great responsibility" bit, I was able to come out mishap-free.

On the other hand, when I had to create new projects where I thought Clojure would be a good fit, I just went all-in with the Clojure ecosystem rather than start with Spring Boot and add Clojure, and I found going all-in with Clojure to be incredibly productive. With that being said, I made the decisions with a decent understanding of both Spring Boot and Clojure, so my experience would likely vary from that of someone who is experienced with Spring Boot and knows nothing of Clojure.

For your setup-- if I do original CD -> accrual's rip -> burned CD, does burned CD == original CD for all values of original CD?

I was curious about this as well, and the answer was "no". I meticulously followed EAC setup guides for three drives in EAC, I used the recommended gap settings, the results were completely verified by AccurateRip, I was storing the results as a CUE sheet and single WAVE file, all drives would produce the same file, I was using EAC to burn the CUE sheet and WAVE file back to new Verbatim CD-Rs, re-ripping was done with the same setup in EAC, and the files still didn't match. I've been meaning to dig deeper and compare the files in binary, but haven't gotten around to it.

State of CSS 4 years ago

I think you should re-read my comment. Fyi I already knew that Safari now supports vp9 webm. As a web dev I keep up with this stuff. In my comment I said that they are so behind.

Your comment:

Safari is so behind in terms of lack of support for free media formats/codecs like webm, webp, and av1. You can't even switch browsers to view them, since it's all webkit

Maybe you do keep up with this stuff, and you did say they are so behind, but you also said "You can't even switch browsers to view them", which is not true.

I do not want to make a change in a core API and have my program build without me addressing all of the places that would be affected by that. This is where types shine, and this is where I think types are important.

This is also where tests shine, which are far more expressive than the type systems we have today. Tests are usually not as convenient as types though, but it's another parameter to consider when choosing the right solution for a given scenario.

But I will not give up that ability to make a refactor in core code and then turn be able to address all of the places that that change breaks things.

This will be less satisfying since it's anecdotal, but I'll offer up my experience anyhow: I rarely find myself refactoring. When I do refactor, it's almost always in the "changing the factoring" sense, in that callers are none the wiser to changes since the interface is the same, which limits the fear of breakage. That's not to say that it always turns out this way, but churning regularly on interface boundaries would be a "smell" to me.

To further beat the drum from above, I'd additionally expect the tests to help prevent breakage whether the program's dynamically or statically-typed. I review plenty of code, much of it in Scala, which puts a heavy emphasis on its strong typing. When there aren't tests, I request them or write them myself, and that uncovers bugs more often than not despite the programs passing the type checker.

I watched the talk last week, so perhaps my memory's a bit off, but "move fast and break things" was not the takeaway that I got. I thought of it more of "problems are going to happen, being able to debug them is important, and there are better tools available for dealing with that than what's common".

Additionally, I don't recall if he said it in the talk, but it's been my experience that type-based bugs often surface early and are generally incredibly cheap compared to other classes of bugs (functional bugs, logic bugs, security bugs, etc.).

This library doesn't wrap the AWS SDK, explicitly calls out existing Clojure wrappers that do in the README, and none of his commits seem to conflict with the referenced Tweet. Am I missing something?

Click 5 years ago

The forEach isn't returning it in your example, the line after it is returning. Try again without acc and I believe that's what was meant.

You can implement any of them in terms of the others, but only if you break convention and introduce side effects. Follow convention and try to implement (for example) reduce with map and you'll find that it's not possible.

I've worked at plenty of places with free snacks/drinks (some even considered enterprise), but never a place that had ping pong tables or relaxation pods, so casually introducing those to the argument is a tough sell and changes the context enough so that I don't think the rest of your point still stands. What are your thoughts on a more fitting comparison, such as snacks/drinks provided vs. BYO/vending machine/go to the store?

Pity he hadn't heard of Armed Bear Common Lisp (http://abcl.org/), which runs on the JVM.

He was certainly aware of SBCL. He had a number of reasons for not wanting to use it. [1]

I don't mind mutable state, since the real world is not functional:

I hear this argument often, but the "real world" is not linked lists or hash maps or mutable or 0s and 1s either, but they are all useful representations.

real programs are all about side effects

Clojure has plenty of facilities for side effects, and without having to resort to monads (though you could if you wanted).

[1] https://www.youtube.com/watch?v=cPNkH-7PRTk

Immutable data structures were part of it, but not the whole story. From the article:

"But Lisp had a bunch of things that needed to be fixed in my opinion. It was built on concretions, you know, a lot of the design of more abstractions and CLOS and stuff like that came after the underpinnings. The underpinnings didn't take advantage of them so if you want polymorphism at the bottom, you have to retrofit it. If you want immutability at the core, you just need to, you need something different to, you know, from the ground up. And that's why Clojure was worth doing as opposed to trying to do Clojure as a library for Common Lisp. The Lisps were functional kind of, mostly by convention. But the other data structures were not, you had to switch gears to go from, you know, assoc with lists to, you know, a proper hash table. And lists are crappy data structures, sorry, they just are. They're very weak, and there's no reason to use them as a fundamental primitive for programming. Also packages and interning were very complex there."

I don't know of any formal research, but in Clojure, where HAMTs are a fundamental part of the language, the philosophy is more oriented towards paying for things (such as thread safety) with memory and CPU first, benchmarking to find bottlenecks second, and if there are any bottlenecks, optimizing accordingly. It was written with this in mind, which is why it requires world-class VMs like the JVM, CLR, and V8/JSC/SpiderMonkey/etc. that can deal with the GC and (in many cases) make runtime optimizations.

Also, I'm fairly certain synchronizing isn't an issue because there's nothing to synchronize on since the data structures are immutable. Am I understanding you correctly?

This doesn't answer your question, but I just wanted to make clear that the posts below certainly do not show, trivially or otherwise, how to use "no string literals" and "pure data" in Postgres.

I'm not sure I follow. I don't find "2000-line functions whose branches ..." to be a requirement for polymorphism.

I'm also not against static typing, but I am against thinking it's a silver bullet. Consider this: `function inc(x: number): number { return x - 1; }`. It passes the type checker, but the blow torch still burned you.

I've worked with functions in JavaScript that change functionality radically depending on whether you pass an integer or an object. I thought this was the way of the world until I got deeper into typed languages, where you learn why not doing that is good. Type envy still stings though.

This is just polymorphism, isn't it? Why is this not a good thing?

you get a sub-par editing experience [in Clojure]

Paredit and vim-sexp have no problem doing structural editing. I don't use it myself, but Parinfer was created with Clojure in mind and people seem incredibly happy with it.

diminished readability [in Clojure]

If you watched the talk that you lifted "complected" from, you'd know that this is subjective. Is German unreadable because I don't know German?

Clojure syntax is a "complected" derivative of Lisp :-)

Complected in some ways sure, but far less so than many lisps, and certainly less so than Common Lisp. It seems your familiarity is complected with your reasoning.

Foolproof HTML 9 years ago

Although the HTML he (lisper) gave is different in that it has the closing </p> tag, I'm failing to see any case where this is bad or would result in different behavior from your example. To be clear, he seems to be talking about rendering HTML only, not parsing it. Wouldn't both your example and his have the same parsed DOM? Am I missing something?