Clojure will affect the way you think about programming - <AUTHOR> http://eli.thegreenplace.net/2017/clojure-the-perfect-language-to-expand-your-brain/ <comment><USER7> Clojure is the language where LISP clicked for me. Can't recommend it enough, it's got all of it - immutable datastructures, convenient data literals, simple and composable concurrency primitives, very thin interface to host VM.

Just put enough effort to get beyond that "omg parenthesis" barrier and it will be a delight. It's like that Half-life joke: there are two kinds of people, those that finished Half-life many times and those that never got off the train (which as somebody will probably point out, is a variation on another joke, but you get the idea).

totally unaffiliated: [https://www.braveclojure.com/clojure-for-the-brave-and- true/](https://www.braveclojure.com/clojure-for-the-brave-and-true/)

<comment><USER8> There are many things to love in Clojure, like core.async, the lispyness, etc. But for me, their biggest breakthrough is with no doubt the data-structures.

Clojure default of immutable hash maps and vectors was really bold. They had to innovate by giving a twist to Bagwell's great research on data-structures, and they managed to build what in my opinion are the first set of general data-structures suitable of representing traditional hierarchical object-tree data-models immutably, at the scale of large interactive software.

Without these, the single-atom architecture that now is popular as ever with Redux, Elm, etc. would not be possible. The flourishing of functional programming for interactive software that followed shows to me that the biggest impediment before was not the lack of functional ways of expressing interactions (the Haskell people have devoted a lot of notable effort in the FRP camp). Instead, just having efficient data-structures to write persistent document models, escaping the rigidity of lists and rb-trees, allows you to write big interactive sofware in a functional manner even with the most dumb abstractions (which is a good thing, KISS!) and even stupid language (JavaScript!).

This has inspired me to work on a generic implementation in C++, which also has experimental Python and Guile bindings: [https://sinusoid.es/immer/](https://sinusoid.es/immer/) [https://github.com/arximboldi/immer/](https://github.com/arximboldi/immer/)

In the past I also did some other work on bringing Clojure Transducers to C++ ([https://www.youtube.com/watch?v=vohGJjGxtJQ&t=1614s](https://www.youtube.com/watch?v=vohGJjGxtJQ&t=1614s)) but I know consider it a much less important effort---without the data- structures the other parts of Clojure feel almost like just sugar.

EDIT1 -- Sorry for the shameless plug ;)

EDIT2 -- Grammar

<comment><USER9> Do you know of a good resource for reading about their data-structures, especially anything Haskell doesn't have?

<comment><USER10> Any book on clojure and website too will go over them. They are fundamental to using clojure.

I don't know enough about haskell to say what it does or doesn't have in relation to clojure. However, it's not simply the data structures, but how the language is built to interact with them from a programmers perspective.

From a user interface to the language point of view, I find the ways of interacting with maps to be very nice.

In particular the dual purpose of "keywords" to serve both as a good index/key in said hash maps, but also as callable look up function for the same key in a hash map leads to simplified code.

This, coupled with the extremely high usage of those maps in typical clojure code, makes a big difference.

To expand on that a little, "keywords" are symbols that begin with a colon, which I believe is the same as common lisp. :for :example :this :is :a :sentence :of :keywords. They are commonly used as the key in a map. Which has a literal syntax like (def map1 {:a 1 :b 2 :c "taco"}). To pull a value out, you can evaluate (:c map1) which will return "taco".

They are hash maps based on work by Philip Bagwell, and I think a lot of languages have versions of this now. At least scheme and Common Lisp do. But I don't believe they have the nice literal syntax and interaction syntax.

Many Lisp traditionalists are bothered by the use of curly braces for maps and square brackets for vectors, however I'm a fan. Without this bit of syntax, you have to add verbosity to the language to differentiate defining a map from doing a lookup, etc.

For resources, Clojure for the Brave and True is pretty popular. Also the online community is quite friendly, although I have noticed some trends toward "the one true way" of doing things that puts me off a little.

<comment><USER11> >Many Lisp traditionalists are bothered by the use of curly braces for maps and square brackets for vectors

I have definitely seen this. I'm not sure that I understand this sentiment. The only thing that Clojure is missing is the "system" feel that Common Lisp provides, with things like character macros, symbol macros, etc.

That being said, I definitely appreciate how thought through Clojure is, especially when compared to CL. Several things are missing/don't feel well thought out in CL (notion of a `calleable` type is gone, `nth` isn't defined on vectors or strings (but you can still `length` them!) nor is `first` and `rest`) That provides a great deal of friction.

<comment><USER12> Common Lisp had a lot thought put into it, but the design goals were different. One of the design goals was to support efficient compilation given various constraining dimensions: the need for speedy compilers vs. the need for delivery of applications on standard hardware. Thus a Lisp compiler should be able to generate fast code, even by using whole-program compilation. Thus the language has to take care of a wide range of possible implementations, not just one on a particular virtual machine.

Clojure OTOH has a relatively straight-forward compiler written in Java, only targetting the JVM in a standard way. The Java/JVM infrastructure for code generation (JIT), low-level optimizations (JIT), memory management, application building and delivery could be reused. With all its features and limitations (for example no TCO, fixed JVM instruction set, ...).

Common Lisp also not only provides some generic operators, but also lots of non-generic operators. One reason for that is the will for backwards compatibility (which was another goal in the Common Lisp design) and the idea that something like Common Lisp is also a low-level languages or provides at least a layer of low-level stuff, functions you would use to implement higher- level stuff.

Common Lisp is the next step in the evolution of Lisp I to Lisp 1.5 to Maclisp to Zetalisp. Thus it contains much of the core Lisp functions, stuff you can read about it the Lisp manuals from 1958 and 1960. People did not want to throw their code away, they wanted a modernized Maclisp. Thus one could port a 100kloc Lisp program from Maclisp or Zetalisp to Common Lisp without too much effort. The main operations were there.

Clojure OTOH has almost no backwards compatibility to earlier Lisp dialects. Programs can not be ported from Lisp to Clojure in a useful way. They have to be rewritten. But that was okay, since the main target were not Lisp developers, but people who wanted a language with Lisp influence in the Java/JVM eco-system (or possibly other eco-systems too).

Thus Common Lisp looks to you like it has less thought put in, where people actually struggled to be backwards compatible and modernize the language at the same time.

So Common Lisp has lots of non-generic functions, a layer of generic non- extensible functions (like the sequence layer) and a mechanism for extensible generic functions (CLOS). Something like CLOS is implemented on-top of the non-generic Lisp, with a few parts using implementation specific mechanims. One does not need to use the primitives of a different host language, because Common Lisp is already capable of hosting with its primitives.

</comment></comment></comment></comment></comment></comment><comment><USER13> Having spent some time programming in Clojure, for the purpose of expanding my brain, I suspect a better Lisp to start with might be one of the classics - Racket, Common Lisp, etc... One of the reasons I gave up on Clojure was the lack of documentation of libraries, the bad debugging experience (those stack traces!) and the fact that there's no avoiding the JVM. They're all distractions to the learning (that was 2 years ago, I'd be happy to hear that things have changed).

I think Clojure is a great language, but if you just want to expand your mind via a Lisp then I think you'll get more for your time with another implementation.

<comment><USER14> I agree. I read through Clojure for the Brave and True, and played with it a bit, but it was too much new stuff at once coming from an only Python background.

I'm reading Structure and Interpretation of Computer Programs right now and everything is clicking. I'm looking forward to going back to Clojure after I get through more of SICP.

<comment><USER10> Many people say that clojure is the one that clicked for them, but I suspect it's really not due to clojure itself, just that it's more recent and likely not to be the first lisp people have tried to learn.

I think the exposure of trying to learn different lisps is the key, and when you get to a point where one clicks, run with it!

</comment></comment></comment><comment><USER15> I don't like working with clojure.

Its basically modern perl. I've worked with both professionally, and the outstanding point with both has been:

\- programmers try to be clever in their code, write one giant file full of complicated specialized 'beautiful' code, forget everything they know about breaking big tasks into simple small ones.

\- code is a nightmare to maintain for non-author

\- non-authors working on code results in adhoc mess of styles

Play with, sure. Learn a few things and watch the videos, absolutely. Rich is a really thoughtful talker. I actually quite enjoyed clojure before I had to collaborate on a code base.

...but goodness me. I cannot strongly enough recommend against using it professionally.

<comment><USER16> Are we doing opinion threads now? Okay. I can do one too!

I do like working with clojure. It's my favorite dynamically typed programming language by an easy margin.

It's basically everything that was a good idea in Python and Ruby brought under the unifying role of a Lisp syntax, with a good Java FFI. This makes it slightly harder to learn (it's very difficult to learn Clojure if you don't at least know Java).

It has a very clean syntax for the most part. Parenthesis handling does need some automation (basically everyone copied paredit) but has the nice property that refactoring is a breeze and extremely predictable.

Except for rogue agents like me and a few others, very few programmers go crazy with defmacro, which makes Clojure often a lot more orderly and understandable than lots of Common Lisp code.

I've run a shop with 6 clojure developers collaborating with engineers in both mobile and web space, and in many places Clojure was such a delight that cljs began to creep into the web frontends. In many cases the mobile devs contributed API endpoint handlers to the codebase and they said in general it was easy to work with (although folks sometimes had problems with more complex map types; often because of leftover code from the Bad Old Days when :symbol-a and :symbol_a both got introduced into our codebase because of bugs in AWS bindings choking on -'s).

Clojure, like many dynamic languages, is ultimately limited by its lack of a type system. At some point systems become challenging to refactor. To combat this, a lot of discipline about testing and builds needs to happen.

I built a business around Clojure, sold it to a bank, and made lots of money and friends along the way (and just yesterday the bank announced they have decided to kill it because they don't like it, but that's got little to do with clojure and everything to do with <REDACTED>). We did stuff that VCs flat out claimed was impossible, to my face.

I'm much more interested in other languages now, but that's not because I think Clojure is bad. It's because I think that my development as a software engineer requires I put Clojure down for a few years and work with other concepts.

<comment><USER17> >> ...the bank announced they have decided to kill it because they don't like it, but that's got little to do with Clojure...

I think that had something to do with Clojure. The thing is, businesses usually follow best-practices and choosing a language like Clojure is certainly not a best-practice (even if developers had really good reasons to use it).

For example, who maintains the code? How many Clojurists (is that a word?) can you find to work on the project? The bank would be better off by sticking to Java/Python/C#/etc.

Just because you can do it, doesn't mean that you should. That's a bad habit I've seen from many developers (honestly, I understand the interest to learn more languages and use them at work, but that often results in short- sightedness when building a project).

<comment><USER16> > I think that had something to do with Clojure.

Were you on the Level team at Capital One? If so, oh hai and I hope all is well. Given all the changes there, you may want to be careful. You gotta know this is against policy if it goes much further. I know because I got in trouble over violating said policy once... If not: no. You're wrong. Headcount issues were largely unrelated to Clojure. Also, please stop pretending your best guess is some sort of calculus over complex corporate politics.

Staffing as a small startup bought by a big company is always a problem. Doubly so when you're on the leading edge of a corporate introduction into a new (and in many ways more fiercely competitive) labor market.

> can you find to work on the project? The bank would be better off by > sticking to Java/Python/C#/etc.

I had no problem recrutin good clojure developers once I worked with the recruting team to help get the job postings in the right places.

> Just because you can do it, doesn't mean that you should.

The converse of this that is equally true: Just because you don't feel capable of doing it doesn't mean I should not. This is no idle speculation, we _did_ it. We exited. We exited with a featherlight team, which turned a small and interesting project into a major opportunity for every employee.

<comment><USER17> > ... Also, please stop pretending your best guess is some sort of calculus > over complex corporate politics...

I think you should try to be more civil on HN. You can't just bash someone because of their _guess_.

> The converse of this that is equally true: Just because you don't feel > capable of doing it doesn't mean I should not.

I don't want to get into some argument with someone who feels he is the _only_ guy capable of achieving a failure.

<comment><USER16> > I think you should try to be more civil on HN. You can't just bash someone > because of their guess.

I asked politely, my friend. I'm suggesting your guess, leveled as an authoritative position, is misleading. Its you, taking my story away from me, asserting your narrative based strictly on preference. It's a narrative I disagree with, so I'm not inclined to let it slide.

It's crass to do this. There are many, MANY other ways you could have decided to open this subject. You could have related to YOUR experience, you could have asked for explanation of how these problems are perceived or surmounted. You could have simply expressed skepticism about the team size.

But you didn't. Here we are, on the wrong foot.

> I don't want to get into some argument with someone who feels he is the only > guy capable of achieving a failure.

Then worry not! I am not: a guy, the only one capable of achieving, nor do I consider the product that made me a millionaire a failure.

</comment></comment></comment></comment></comment></comment><comment><USER18> I have switched between many programming languages, and if you are considering Clojure I would highly recommend it. It is immutable first, which helps eliminate many classes of explicit bugs and non-obvious anti-patterns. It also works across Java / Javascript allowing for a common code base of business logic across all layers, and with React Native looks and performs well on iOS and Android.

<comment><USER19> When you say it works across Java/JavaScript - could you expand? Can I essentially write Clojure that compiles to JavaScript?

<comment><USER20> Clojure uses reader conditionals [https://clojure.org/guides/reader_conditionals](https://clojure.org/guides/reader_conditionals) that allow writing code that cross-compiles between different platforms, and generates platform specific code when necessary.

Many Clojure libraries cross-compile between Clojure and ClojureScript. You can see an example here [https://github.com/yogthos/json- html/blob/master/src/json_ht...](https://github.com/yogthos/json- html/blob/master/src/json_html/core.cljc)

</comment></comment></comment><comment><USER12> > Clojure is a dynamic language.

Dynamically typed. As a dynamic language Clojure is less capable than many other Lisp implementations/languages. See for example 'late binding'. In Clojure you either need to define a function before its use or need declare it. Not that 'dynamic'. In a typical Lisp dialect the order of definitions makes much less a difference, since functions can be called late-bound. For an interpreter-based implementation, it makes no difference at all.

> It promotes combinations of built-in data structures (lists, maps, vectors) > over objects

An aspect I don't like. This makes debugging of larger systems more difficult, since maps are maps. Whereas objects have a type tag built in, have a list of allowed fields, etc. etc. They simply have more more explicit and standardized structure to them.

> Some built-in features like reducers and transducers rely heavily on > composing higher order functions for transforming other functions.

Which makes code complex, since transducers are a mildly complex mechanism.

> It encourages REPL-based development

In relatively weak form. Basic features of Lisp need to be added to do simple tasks: like 'instrumenting' code to debug it, since it lacks an interpreter or more capable compiler support. REPLs with actual interactive error handling are not standard. Interactive Lisp compilers like the one from SBCL give much more information and warnings.

Thus the Lisp development features are at best only medium-level.

> Historically, Lisp programmers weren't the biggest proponents of OOP

Funky, people from the Lisp community helped to shape OOP and explored much of it. From guys like Hewitt who developed the actors paradigm in the early 70s, Minsky who developed the frame theory mid 70s and inspired a whole range of OO programming in Lisp, to Howard Cannon who developed Flavors in 1979 with flexible mixins and multiple inheritance used to implement the object-oriented operating system parts of the MIT Lisp Machine, to Lieberman who developed OOP with prototypes mid 80s, to Kiczales who worked a decade on OO in Lisp (LOOPS, CLOS, Meta-object Programming, Object-oriented Protocols, Meta-level architectures, early Aspect oriented programming, ...).

Actually objects in the early Lisp were simply symbols with their property lists. These property lists could hold both normal attributes and also functions.

<comment><USER21> > An aspect I don't like. This makes debugging of larger systems more > difficult, since maps are maps. Whereas objects have a type tag built in, > have a list of allowed fields, etc. etc. They simply have more more explicit > and standardized structure to them.

You can create explicit and standardised structures for maps in Clojure, or indeed any other data structure:

        (s/def :foo.student/name  string?)
        (s/def :foo.student/score nat-int?)
        (s/def :foo/student (s/keys :req [:foo.student/name :foo.student/score]))

        (def example-student
          #:foo.student{:name "Alice", :score 30})

However, Clojure takes a somewhat divergent philosophy, as it encourages writing schema for individual fields, rather than a schema for a grouping of fields (such as an object).

For example:

        {:foo.person/name "Alice"
         :foo.student/id  "xyz123456"}

The namespaces of each keyword are different, but they're grouped in the same map as they happen to refer to the same entity.

So rather than operating on a fixed type like `Student`, a function would request that it requires a data structure that has a person's name and a student ID:

        (s/fdef enrol
          :args (s/cat :student (s/keys :req [:foo.person/name :foo.student/id])))

We're still validating (albeit dynamically), but we can be more flexible in what data we ask for. This ties in with Clojure's idea of simplicity; a function shouldn't know about data it doesn't intend to use.

<comment><USER12> > standardised structures for maps

Then there are defstruct and deftype. So it has maps, struct-maps, records, deftypes, Java classes, ... a whole bunch.

'simplicity'?

> This ties in with Clojure's idea of simplicity; a function shouldn't know > about data it doesn't intend to use.

I would use a class for that, since something like CLOS supports multiple- inheritance and all the necessary mechanisms for mixins.

Finding these methods then is supported by the organization in generic functions and hierarchical classes.

<comment><USER21> > Then there are defstruct and deftype. So it has maps, struct-maps, records, > deftypes, Java classes, ... a whole bunch.

defstruct has been deprecated for years. deftype and Java classes are primarily for JVM interop and language extensions.

Outside of calling Java libraries there are just maps, which you're going to be using 95% of the time, and records, which are maps with efficient polymorphism.

> 'simplicity'?

In Clojure parlance, "simplicity" refers to interconnectedness. So a box of tools is "simple", because they're not connected, whereas a Swiss army knife would be "complex", even if it might be easier for a novice to use.

Having a bunch of similar tools isn't complex, from Clojure's point of view, as long as they're separate. It may make things more difficult to learn, but that's another problem entirely :)

> I would use a class for that, since something like CLOS supports multiple- > inheritance and all the necessary mechanisms for mixins.

Doesn't that mean you'd need a separate class for each way you access the data if you wanted to type that? My knowledge of CLOS is, I'm afraid, rudimentary, but can you say to a method: take as as argument an object that has the "id" field from the "Student" class, and the "email" field from the "User" class. Or would you have to explicitly pre-define mixins like HasStudentId and HasUserEmail?

<comment><USER12> > In Clojure parlance, "simplicity" refers to interconnectedness

Clojure tends to redefine words describing concepts with a new or restricted meaning. Typically a general concept like 'simplicity' would have more than one dimension.

> take as as argument an object that has the "id" field from the "Student" > class, and the "email" field from the "User" class. Or would you have to > explicitly pre-define mixins like HasStudentId and HasUserEmail?

I would not do this at all. Having slots or not are low-level artefacts and writing methods which are fine-grained to slots of an objects don't expose the domain-level.

I would use methods for domain level classes which have the necessary slots either local or inherited.

<comment><USER21> > Clojure tends to redefine words describing concepts with a new or restricted > meaning. Typically a general concept like 'simplicity' would have more than > one dimension.

Sure, but that happens all the time in programming. When we talk about "objects" we don't mean "a material thing that can be seen and touched".

> I would not do this at all. Having slots or not are low-level artefacts and > writing methods which are fine-grained to slots of an objects don't expose > the domain-level.

I guess because it's not at all idiomatic, even in an object system as rich as CLOS.

But in Clojure it _is_ idiomatic, and to my mind it leads to a more precise definition of what a function wants. We don't say, "this is a method that operates on a Student object"; we say, "this is a function that takes data that includes a student's email and enrolment date".

Again, I hasten to add that my experience with CLOS is virtually non-existent, but compared to the OOP languages I _am_ familiar with, Clojure has a far richer way of describing the structure of data.

<comment><USER12> I understand that, but as I said I don't like that at all. It binds methods to low-level adhoc features and not to class based domain ontologies. There are other pattern directed invocation systems, which also support that, but I usually prefer the more systematic approach of CLOS. In the tradition of symbolic programming I want to have symbolic classes as my anchors for functionality, not adhoc patterns.

<comment><USER21> You can still create class-like ontologies with Clojure specs, but usually you don't need to.

Clojure's specs, adhoc or otherwise, certainly might not be your cup of tea. Clojure really pushes the idea of separation and isolation, and in my view you need to buy into that philosophy to be at all comfortable with the language.

Where I disagree with you is your assertion that maps in Clojure are always less structured than objects. I'd claim that (at least when properly spec'ed out) they provide far _more_ structure than objects.

<comment><USER12> I'm not talking about what is possible or what _can_ be done. I'm talking about what is natural and promoted. See the message the article communicates:

> It promotes combinations of built-in data structures (lists, maps, vectors) > over objects

I would say that this is actually the case and this article is not the only one to say that.

<comment><USER21> Yes, but as I said, using data structures over objects doesn't mean the data is unstructured. You can use lists, maps and vectors and still have a well defined and validated structure.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER22> I started learning Clojure two years ago, and it has expanded my brain in many ways. I love Clojure for the pure joy it gives me on a daily basis.

In those two years, it thought me about:

      - Interactive programming
      - Persistent data structures
      - <USER2>
      - Code that writes code
      - Functional programming
      - Extendable polymorphism
      - Lazy evaluation
      - Eager evaluation
      - Parallel computing
      - Dynamic variable extent
      - <USER3>
      - Concurrent programming
      - Declarative programming
      - Aspect oriented programming
      - Logic programming
      - Code as data
      - Software transactional memory
      - Generative testing
      - Contracts guards
      - Optional type systems
      - Conditional restarts
      - <USER4>
      - Variant types
      - Collection abstractions
      - Array programming
      - Map Reduce
      - List comprehensions
      - Reactive programming
      - S-expressions
      - <USER5>
      - Pattern Matching
      - Prefix operators
      - <USER6>
      - Data literals
      - And more...

</comment><comment><USER23> If "expanding your brain" is really what we want to optimize, why not learn Haskell? Or for that matter, why not learn something even more strongly typed, like Agda or Idris? Or even a theorem prover like Lean?

Most of the reasons the author presents would either be expanded in one of those languages, or is immaterial to the goal of maximizing learning. After reading the article I have no more reason to consider learning Clojure over learning any of the languages above.

<comment><USER20> One huge difference is the workflow you have in Clojure. REPL driven development is an experience unique to Lisps. When you're working with Clojure, any code can be run in the context of the live app straight from the editor as you write it. This is an amazing experience and very mind expanding in what a development process can look like.

Also, anybody who wants to try FP style programming, but isn't interested in static typing is much better off with Clojure. Type systems in languages like Haskell and Idris add a lot of complexity and mental overhead that's not present in a dynamic language.

<comment><USER24> Is there something about clj's repl that makes it any different from ghci's?

<comment><USER20> Yes, you can reload any symbol in the CLJ REPL directly from the editor. You can also evaluate any function within the context of the running application without going through the main. The REPL is an integral part of the development process in Clojure. You can see this in action here around 15 minute mark [https://www.youtube.com/watch?v=nItR5rwP4mY](https://www.youtube.com/watch?v=nItR5rwP4mY)

<comment><USER25> R and RStudio are actually quite good in this aspect.

\- You can evaluate any part of editor in console with keyboard shortcut. The only difference between using console and editor is that your input is easily saved in editor.

\- The environment browser make inspecting variables, data structures much easier.

Besides, in R you want to use vectorized functions for better performance, so you search for general functions and combine them, which actually promote good functional programming style instead of a big control block with many processes intertwined.

</comment></comment></comment></comment></comment><comment><USER26> I have to say after diving into ClojureScript I came away thinking differently about a number of things - state management, _how_ to program functionally when you are more constrained than in more permissive languages. It was a real learning experience.

<comment><USER27> This ^ right here, is what gets lost in all the squabbling over functional purity and parenthesis hate.

For a huge number of developers coming from the Javascript/web side of things, Clojurescript is poised so perfectly to usher them into thinking about composing your programs as pure functions, immutable data structures and organizing your state such that it is easy to reason about.

Eventually, Clojure led me to Haskell, and even back to how Javascript ought to be written (i.e. fantasy-land specs). This has been the single most eye opening learning effort that I have ever had the joy of undertaking since I started programming.

</comment></comment><comment><USER28> Nothing I've used has the combination of ease of use and interactivity. It's pretty difficult to explain, but one can send both top level forms, or smaller pieces of code to the repl and get results without leaving the code one is working on.

[https://s3.us- east-2.amazonaws.com/photoblobs/screencast_201...](https://s3.us- east-2.amazonaws.com/photoblobs/screencast_2017-08-04_09-03-37.mp4)

</comment><comment><USER29> I would love to use Clojure (it's probably the only language I would consider moving to right now) but the JVM just doesn't work for me. Clojure-native that offered all of Clojure and was realistic - there was one that indirectly used Gambit Scheme at one time, and an incomplete Python version - would be awesome. Clojure that requires you to use the current Java approaches to interfacing with C is not of interest.

<comment><USER10> I've felt that way about clojure native, but what makes a language is the ecosystem, and the JVM brings a fantastic ecosystem.

There really is no way to offer "all of clojure" as native because the ecosystem is part of what "all of clojure" offers.

I've long thought about ways of doing a "native" clojure, and have eventually come to the conclusion that it doesn't offer anything compelling.

If you want fast start up time and scripting, you can do that with node and clojurescript. Or Lumo or whatever else there is in that area.

Once running, the JVM is pretty performant in a lot of cases... Where it struggles are where all garbage collected languages struggle. If that's the pain point, you could probably bootstrap a scheme from Gambit or Chicken that did manual memory management...I struggle to imagine what that would look like in the end though. Lisp flavored C maybe.

People smarter than me have said that the Clojurescript compiler is an excellent starting point for making a compiler that emits other languages. It's over my head, but maybe it would be a worthwhile project to emit golang or something.

I believe some of the clojure-schemes that floated around briefly bootstrapped from clojurescript compiler to emit Gambit Scheme...

Without the libraries/ecosystem I don't think it would be worth it.

<comment><USER29> > the JVM brings a fantastic ecosystem

Unfortunately it's (intentionally) horrible for interfacing with C libraries.

> it doesn't offer anything compelling

Unless you need to interact with native libraries.

There's currently a lot of excitement about Scala Native and Kotlin Native. Those projects aren't being done just for the heck of it.

<comment><USER10> A lot of projects are done for the heck of it. Nothing wrong with that.

Native libraries is a good reason. Particularly GUI libraries.

I imagine Swift would be a decent target for a lisp, for app development.

GUI is a major missing area in clojure. There are some good efforts there, Seesaw targeting Swing, and fn-fx targeting JavaFX.

</comment></comment></comment></comment><comment><USER30> Clojure also affected the way I think about programming in a very positive way. There are downsides to it

\- stack traces \- jvm \- lein is pretty slow

but the upsides

\- immutable data structures \- lisp/macros \- repl (you can send code from your editor to the repl) \- community \- great open source web app libraries (for me, anyway)

outweigh the downsides.

I encourage everyone here to try clojure at some point, it might just become your favorite language.

<comment><USER31> For people familiar with java, the jvm is an upside. Being able to use libraries (especially client ones) from your project can be very useful. The amazing interop support is very nice if your pragmatic over purist and don't plan on rewriting a ton of things.

<comment><USER30> This is true, if you're a java/jvm person, this is a huge upside, even if you aren't, once you see just how much code has been written in java, you'll probably come to appreciate the pragmatism.

When I learned clojure two years ago, I didn't have any experience with java or the jvm, so I had to sort of learn where the boundary was.

After that initial hurdle however, I now use java interop quite a bit.

</comment></comment></comment><comment><USER32> I just saw an article recently about core.async and the "go" macro, which seems to effectively give you goroutines in Clojure. I'd be very tempted to use it for that reason alone. I love Go's concurrency, but it can be a little on the verbose side. Good for some projects, but not all of them.

<comment><USER33> Go is _verbose_? I'm surprised to hear that, to be honest. Can you say what it's verbose in comparison to? What production language/framework has terser concurrency with the same expressiveness?

<comment><USER34> Clojure for one! But I thought it was a common complaint that Go's lack of support for generics and other language design decisions aimed at keeping things easy make it much more verbose.

That's just a non-user's perspective on the scuttlebutt, though - I don't have any actual experience with Go.

</comment></comment></comment><comment><USER35> I was fortunate enough to be given the opportunity to learn Clojure on the job. A majority of my work is on the web side (JavaScript, et al.), so learning Clojure was a fun and interesting challenge.

After the initial hurdle of getting used to a Lisp I found the language very liberating. I definitely approach problems very differently than I did prior to learning Clojure, even when flipping back to JavaScript land. I find my approach is vastly different that it was before. The best way to describe my way of thinking is that I'm very "data first" now.

</comment><comment><USER36> I was lucky enough to land a Clojure job (stitchdata.com, we're hiring!) before having to learn Clojure, because I had the benefit of experienced mentors helping me get to grips with lisps (which were alien to me) and a development workflow that leaned heavily on the REPL (emacs + cider). Clojure has changed the way I think about many programming concepts and has been a joy to learn. It has it's warts but the core is very well built and I find the documentation to be quite good once you understand the basics.

</comment><comment><USER37> I agree with the article, but would also like to mention that it has a very steep learning curve.

1.5 months after my first line of Swift I had my app in the app store (granted I was proficient in Objective-C). 2 years since I've started learning Clojure and a couple of months since I'm working professionally with it and I'm still quite shaky.

Luckily, it's not difficult to begin - you can start hacking small programs in a couple of days, but when it comes to building large applications, that's when it becomes a high-level art form (just one of the many possible metaphors :) ).

Quite similar to C++ in this respect - easy to pick up, hard to master.

It humbled me and made me cry many times. But as with everything, if you don't give up, you level-up.

As far as the experience goes, it gives you this 'overview' experience of programming - you can mimic almost any feature from other languages and you have access to all the libs for the JVM (including C/C++ libs through JNI) plus all the javascript libs.

So in terms of libraries you can use, I dare say that Clojure(script) is the language which can access the most libs out there.

So yeah, definitely a powerful language and a powerful tool which you can go very deep into, albeit a bit tough to learn.

<comment><USER38> It's a bit of a change from most mainstream languages, but still way easier than Haskell though.

</comment></comment><comment><USER39> > core.spec makes it more formal and verifiable. This is very useful when > working with data, and is another example of where Clojure's pragmatism > shines; the language is dynamic in its core, but when you need static typing > - it's there, optionally

Um no. Spec is not static typing, it does runtime checks. And core.typed is currently being rewritten and is not compatible with current version of Clojure.

</comment><comment><USER40> I have been working with Clojure(script) full-time for the past 4 months (coming from javascript). I highly recommend it. Programming is fun again.

</comment><comment><USER41> I'm an EE who is getting more and more interested in software development and computation in general. I've been reading Paul Graham and Peter Norvig and decided to learn Scheme. Any thoughts on Scheme vs. Clojure for learning?

<comment><USER42> Scheme is a smaller language and has legendary beginner books. Start with HTDP and then SICP.

<comment><USER43> Seconding HtDP. I have gotten lots of mileage from that one.

</comment></comment></comment><comment><USER44> Clojure will affect the way you think about programming. It's led a number of people I know to start taking Haskell seriously after their Clojure phase.

<comment><USER45> This seems somewhat surprising to me since they are, in some sense, at opposite ends of the functional programming spectrum... but it's the path I took.

<comment><USER44> I think it's a cultural thing. There's something similar going on with Python and go.

Seems like a lot of people start with "getting types to go away makes a lot of powerful things easier". But eventually you a) get sick of typos causing runtime errors b) start to realise there are even more powerful things you can do with a non-broken type system.

</comment></comment></comment><comment><USER46> Why not Common Lisp or Scheme?

<comment><USER47> I did Common Lisp back in college for several years, it's a great language. But good luck getting a job with it. Clojure on the other hand, I've been paying my bills with that for the last few years. The main difference is a much larger community, and therefore lots more libraries for real-world stuff, and sitting on the JVM you have a lot of options integrating with existing corporate stuff.

<comment><USER48> There's a Common Lisp implementation that sits on the JVM. It's called ABCL. It provides a Java API for loading and calling Lisp code as well as a Lisp API for calling Java code (although it is quite a bit more verbose than that provided in Clojure... nothing a few macros couldn't solve if it became a nuisance).

The community is what does it. I tried for years to get commercial work in Common Lisp. It never happened.

</comment></comment></comment><comment><USER39> By far the most incredible thing for me was to see how far a few characters of code can go. Clojure is a very tight language where you can accomplish a lot in just one line of code. You end up suddenly having all this new, extra time to just think about your problem instead of coding it.

<comment><USER20> Another interesting side-effect of tight code, is that you become a lot less attached to it. When I worked in Java, it would often take 100s of lines of code to solve a simple problem, and once I wrote that code I'd be very hesitant to throw away or refactor it.

With Clojure, it often takes 10 lines or less to solve problems that take 100s of lines of Java. This encourages a lot more experimentation and refactoring in my experience.

Also, since you're always working in the REPL, you can always run the code after you change it and see that it's doing what you want immediately.

<comment><USER49> The functional nature helps with the lack of fear of refactoring. Your Java code may have side effects reaching across the code base.

</comment></comment></comment><comment><USER50> What are the best, up-to-date books to learn Clojure for an experienced developer pretty familiar with FP?

<comment><USER51> Probably Joy of Clojure.

<comment><USER52> Joy of Clojure arguably not very suited for beginners

</comment></comment></comment><comment><USER53> For those of you who have experience with both Clojure and Elixir: what would be reasons to choose Clojure over Elixir, if any? And vice versa?

</comment><comment><USER54> Want to affect the way you think about programming?

Learn Prolog.

<comment><USER55> Prolog is a programming language for turning polynomial-time algorithms into exponential ones.

<comment><USER56> And, true to form, it often works in the _other_ direction too!

Especially with CLP(FD) and other Prolog constraints.

</comment></comment></comment><comment><USER57> The problem is that I want to expand my brain, but I also want to get things done and I have a family.

I think this is one of those you can choose 2 situations.

<comment><USER58> Use breaks and sleep less once in a while. It's just what you've got to do if you want to learn new things outside of your current obligations.

</comment></comment><comment><USER48> The _perfect_ language? I doubt that. It's probably quite decent.

<comment><USER59> The perfect language to expand your brain. In a world dominated by java, php, c++,... In my opinion yes, Clojure could the perfect language to continue learning concepts, at same level would be Haskell.

<comment><USER20> It's also very pragmatic, and probably most used functional languages in the industry at this point.

<comment><USER7> wish that were true, but i doubt it. scala, prolog and erlang are all higher on tiobe index.

<comment><USER20> I personally don't view Scala as a FP language, it's a FP/OO hybrid. It's not opinionated in that regard, and a lot of code in it is written in traditional OO style or a mix of the two.

Erlang is another widely used functional language, but it's not very widely used outside the telecom niche. Clojure has the advantage of running on the JVM, and makes it easy to target a much wider range of domains.

<comment><USER12> Clojure is also a hybrid. The other part is called Java or Javascript. This is claimed as an advantage, since there is already a lot of functionality in another language to be reused by a direct interface. Some stuff is simply deferred to the host language and since the other part is based on OOP, applications will then be a mix of more FP-oriented code calling OOP-oriented code.

<comment><USER20> This is an implementation detail, and doesn't affect the API presented to the user. For example, consider the clj-http library that's backed by the Apache http Java library internally [https://github.com/dakrone/clj- http](https://github.com/dakrone/clj-http) . As a user of clj-http, I don't know or care about the fact that it's a wrapper around OOP code.

Furthermore, if you wanted to, you could reimplement the internals in Clojure and the users of the library wouldn't be affected.

Being able to leverage existing mature libraries is a huge advantage, and the fact that they can be used via idiomatic functional APIs provides the best of both worlds experience.

<comment><USER12> The author of such a wrapper library writes this hybrid code.

Wrapper libraries are one way to deal with hybrid code.

<comment><USER20> Sure, just like if you did FFI in CL. I'm not really sure what your point here is.

</comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER60> That's true of any language. Even within the same language paradigm.

If you know C#/Java then learn C++ or vice versa and it'll affect the way you think about programming.

Go outside of the statically typed OO world and try out the dynamically typed OO languages like ruby or python.

Even better, learn a weakly typed procedural language like C ( lingua franca for CS ).

Or choose an architecture and learn some assembly. Now that will affect the way you think about programming.

Move out of onto a different domain altogether and try one of the flavors of a declarative language like SQL.

Learning a bit here and there of many different languages and paradigms will affect the way you think. Clojure isn't special.

You can even just stay within a framework and try to get a deep understanding of .Net language/IL/Framework Libraries/Runtime stack. Then you get into the debate of breadth vs depth. Should you learn one language/framework/paradigm exceptionally well or should you learn a bit about a lot of a lot languages/paradigms?

<comment><USER58> That is true. Heck, eating a particular meal might affect the way you think about programming. But the article title, and the original HN title, is "Clojure - the perfect language to expand your brain?" So it's asking if Clojure is better at it than other languages/paradigms.

<comment><USER60> > So it's asking if Clojure is better at it than other languages/paradigms.

My argument was that there are such a wide variety of languages/frameworks/paradigms that it makes no sense to make such a claim.

Someone from a functional background ( lets say you know scheme or ML ) would get more from learning an OO language than from learning clojure. He'd learn more from learning assembly and seeing how data moves in and out of registers than from learning clojure.

Programming is such a wide topic. We get this posts all the time. Go will expand your mind more than anything or ruby will or F# or any other flavor of the day or even python.

It all depends on who you are and what you know.

In other words "Clojure - the perfect language to expand your brain?" is a silly assertion. There is no "perfect language" because everyone's brains are different because we all come with different backgrounds and expertise.

But that's just my opinion.

</comment></comment></comment><comment><USER61> " A language that doesn't affect the way you think about programming, is not worth knowing."

If this would be common practise nobody would learn golang.

<comment><USER33> Golang certainly affected the way I think about programming, having learned it after ~15 years of programming experience.

FWIW, I think most language can affect thinking - but the degree varies.

</comment></comment><comment><USER15> Our experiences with clojure are clearly different.

There have been plenty of people who have built successful businesses with perl too. /shrug

I'm still going to recommend people not use either language, because I've personally encountered the downsides of 'when things go wrong'; and it's been significantly worse than in other languages.

> Are we doing opinion threads now? Okay. I can do one too!

That's a bit of a flip off isn't it?

What I have to say is based on my professional experience. Don't like it? Tough. Luck. You had a different experience? fair enough. You want to call it an opinion thread? Well, you know what they say. Opinions are like assholes, everyone has one...

<comment><USER62> Ai yai yai, you took this thread way into the red. Could you please resist the temptation to do that in the future?

The whole idea of HN is to have thoughtful discussion (not to tell one another to fuck off!) That means tolerating a certain amount of provocation when you feel provoked; it's almost always unintentional, and in the rare cases when it isn't, you owe the community better than to respond in kind.

We detached this subthread from [https://news.ycombinator.com/item?id=14929745](https://news.ycombinator.com/item?id=14929745) and marked it off-topic.

</comment></comment><comment><USER63> let clojure = Haskell</comment>


CoffeeConsole: A Chrome Extension - <AUTHOR> http://snook.ca/archives/browsers/coffeeconsole <comment><USER2> I just forked it and added a few things:

        * zero dependencies (except coffee-script.js of course)
        * REPL-style like the standard console
        * command history (up/down keys)
        * console capturing (pretty ugly as it is, the console API is not exposed)
        * on-the-fly syntax checking
        * fixed the icon :)

<http://github.com/ricardobeat/CoffeeConsole>

I messed too much with it to make a pull request. Sorry.

<comment><USER3> Of note, there's an experimental console API that you can use but it requires users to set a flag to use the extension and you wouldn't be able to add it to the chrome store (which I might do at some point).

<comment><USER2> I ventured into that, but having to set a flag is a deal breaker. Let's hope it becomes official soon.

<comment><USER3> btw: I just had a chance to look at your implementation. It's definitely going in a different direction than I wanted to take it. I understand the desire to match the default console but I'd like to keep the more powerful editor (along with some other features I'm looking to add).

Great work, though.

</comment></comment></comment></comment><comment><USER4> Looks good, but I prefer Firefox for most of my debugging. I hope someone eventually makes a similar extension for Firefox, integrating with Firebug (see <http://getfirebug.com/wiki/index.php/Firebug_Extensions>). There is xqjs (<https://addons.mozilla.org/en-US/firefox/addon/xqjs/>), but it doesn't look nearly as polished as this.

<comment><USER5> for firefox there is acebug (<https://addons.mozilla.org/en- US/firefox/addon/acebug/>) which is more polished (cells, autocompletion, better integration with firebug). it doesn't show converted js as you type but that's not very useful anyway

</comment></comment><comment><USER6> This extension made me realize that Chrome doesn't do syntax highlighting in the console. What a convenient feature!

</comment><comment><USER7> As someone who is doing more and more coffeescript this is awesome. However debugging in the console seemed like the only way I was going to stay fresh in native javascript!

</comment><comment><USER8> Very interesting; I like it.

Could you add a keyboard shortcut for running the CoffeeScript? Perhaps "option+(enter|return)" inserts a carriage return while (enter|return) runs the code?

Second choice: command+B "builds" the code.

<comment><USER3> I have it set that Cmd+Enter or Shift+Enter runs the code and Enter just creates a normal carriage return. I know this is a little backwards compared to the normal console, so it's definitely possible to switch it around. This just feels natural to me. (Down the road, having app preferences where this can be toggled might be good.)

<comment><USER8> Ahh yes, just came back here to edit my comment after I found that in the source. I can get used to that.

I'd love to see this become a drop-in replacement for the console. CoffeeScript is so much nicer to deal with in development it's practically the only time I'm still writing plain js.

</comment></comment></comment><comment><USER9> Nice work! I've wanted this for a long time. Giving it a try right now.</comment>


Ask HN: Beginner microscope set? - <AUTHOR> My nine year old daughter wants to get my eleven year old son a microscope set as a gift. We looked around at a lot of options online, and based on the reviews it looks like the cheap ones are nothing but frustration. What's a good beginner microscope set for somebody still in gradeschool? <comment><USER2> For starters, you could get the lens out of an optical drive and place it on top of a smartphone's camera and you'll get ~50x magnification, although with a tiny depth of focus.

There are hobbyists claiming up to 300x (at this level you can clearly see bacteria), by stacking two lenses.

In any case, there are extremely cheap DIY solutions out there, but it may not be worth it for you.

Some ideas: [https://www.wired.com/2011/03/diy-cellphone- microscope/](https://www.wired.com/2011/03/diy-cellphone-microscope/)

[https://hackteria.org/wiki/DIY_microscopy](https://hackteria.org/wiki/DIY_microscopy)

<comment><USER3> A neat idea, I can't imagine an 11-year old kid actually able to use that. (Though it would make a fun crafts project.)

If the son has any real interest in microscopy, I think the money for a proper one is well invested.

</comment></comment><comment><USER4> You're right, the cheap ones are terrible.

For 10x magnification, good for looking at bugs, plants, and money, don't get a microscope - get a loupe (the thing jewelers use). Get a glass one with an LED light. A good one will be about $60.

For 100x magnification, spend around $300. Mine is an Amscope and it works great. Again make sure you get one with an LED light. Get one with the light above the platform unless preparing slides sounds fun.

<comment><USER3> You can get a decent pocket magnifying glass for $10.

If you want to look at any cellular structures, I don't think there's a way around slides and bottom-up lighting. Fortunately, preparing slides is actually fun ;-) Also, all serious microscopy I know is done like that (unless you're using stereo microscopes for entomology), so one might as well learn how to do it properly.

</comment></comment><comment><USER3> I had two microscopes as a kid: my dad's old childrens' microscopy set and an ancient hospital unit.

The former had a rubbish microscope, but a really neat box with plenty of accessories. The second was, like I said, ancient (one of those old brass microscopes with a mirror for lighting!), but with very good optics. With a few more odds and ends, they formed my little "home lab".

One of the things that got me started on my career path to biology...

</comment><comment> d-sc I would recommend investing in a set of pre-prepared samples as well, if you decide to get a decent microscope. They're not super expensive and show a good glimps of what is possible.

</comment><comment><USER5> When I was a kid, I got a beginner microscope, and it was awesome. I guess you don't need the best optics if you are just starting out.

There were a few sources of frustration:

1\. The built in lamp was way too weak, but there was also a mirror, but positioning the microscope to get light from the window was a pain. The biggest difference to the awesome school microscopes was that they had great light.

2\. The microscope only came with 5 or so glass plates to put your samples on. I could only look at a handful of samples, and had to wash my glass plates again, etc. Until one day I just "borrowed" a small box of glass plates from school (I guess I should have just asked my parents for more plates, they don't cost much, but you need lots of them)

3) My microscope didn't have any mechanics to move the sample, which made it pretty tricky to move especially at higher magnifications

4) I also got a box of prepared tissue samples with the microscope, but didn't really understand what to do with them. They had nice colors, though.

</comment><comment><USER6> I bought a microscope off amazon for around $50 and also a set of slides. My 5 year old loves it. It has 3 magnification settings and that seems to work fine.

We found some squash bug eggs in the garden and put these on a slide, it was a good activity.

</comment><comment><USER7> This will seem very low effort because I just looked up USB Microscope on Amazon but I have a similar one and it's very cool. [https://www.amazon.com/Jiusion-Magnification-Endoscope- Micro...](https://www.amazon.com/Jiusion-Magnification-Endoscope-Microscope- Compatible/dp/B06WD843ZM/ref=mp_s_a_1_3?ie=UTF8&qid=1543728064&sr=8-3&pi=AC_SX236_SY340_FMwebp_QL65&keywords=usb+microscope&dpPl=1&dpID=519gxSSvZ0L&ref=plSrch)

</comment><comment><USER8> Just a thought: I wonder whether shopping surplus would get you a "real" unit for an affordable price -- and with the ability to find a spec sheet online that confirms what it can do.

</comment><comment><USER9> I was very impressed with this pocket microscope: Carson MicroBrite Plus 60x-120x. The same company makes 2 more pocket microscopes that I bought, all quite good, but I think this one is the best.

What I can strongly dis-recommend is to buy a set from Barnes & Noble. I bought a microscope kit that came in some sort of plastic "suitcase". It had the microscope itself and all sorts of accessories, like prepared slides. The image quality was awful.

</comment><comment><USER10> For looking at cells? Here is the feature you want: [https://en.wikipedia.org/wiki/Phase- contrast_microscopy](https://en.wikipedia.org/wiki/Phase-contrast_microscopy)

In the "Related methods" section of that article, you can see several things that look like nice modern upgrades that are probably expensive.

</comment><comment><USER11> I have a lot of fun with these lenses: [https://www.microphonelens.com/](https://www.microphonelens.com/)

They're so small that you can always have them with you to look at specimens on the spot, especially useful during walks in nature.

Bought several of them as gifts as well, can recommend!

</comment><comment><USER12> My son has Levenhuk beginner microscope (40x-400x), works for him :)

</comment><comment><USER13> You could look at websites that advertise telescopes. If I remember correctly Celestron also sells microscopes.

<comment><USER14> I have had a Celestron microscope for many years, it has been rock solid.

It has a plug in LED light and also a mirror. You need to prepare slides of whatever you're looking at, as the light comes from below.

</comment></comment><comment><USER15> I found a "my first lab" microscope at Goodwill, and it's been pretty fun!

</comment><comment><USER16> foldscope.com</comment>


If you need something to worry about, here it is. - <AUTHOR> http://www.futurescience.com/emp/emp-notes.html

<comment><USER2> So instead of smuggling a nuke into the country, now your would-be terrorist needs to deal with the logistics of detonating a nuke in outer space yet still close enough to the target to inflict the wanted damage. Beautiful in theory, but in practise?

<comment><USER3> The big problem for a would be aggressor is that _we really don't know this phenomena_. Everything in the open literature is from that _one_ 1962 test, plus theory and simulations.

What if you try it and don't accomplish more than force a electrical grid "reboot"? Better hope we can't figure out from the isotope mix way way up there where it came from.

That's one of the big dangers from doing it in the atmosphere, you're leaving a "this bomb built here from that design and this source of fissionables". If you're smuggling it in, it's because you're not a big nation state. You won't enjoy the wrath of your target....</comment></comment>


Ask HN: What are the security risks with web analytics and mitigations? - <AUTHOR>

My initial brainstrom was: [+] controlling how and what data is captured and stored by the analytics platform [+] if data is traveling to a remote service the transmission security and security in storage [+] access controls to the analytics platform: authentication, authorization, logging [+] where session identifiers and cookies are used protecting these from leakage to an attacker [+] is there any risk of using iframes or zero pixel images of an attacker being able to insert their own or is this sufficiently protected by access control to to content management? [+] can any denial of service on the analytics scripts effect the performance of the service being monitored [+] breach of privacy if any personally identifiable data is collected without concent? [+]  Any risks with service mashups e.g. web analytics pulling in geographic, post code data for example and not validating this input?<p>Anything else? Any of these that are not a risk? <comment><USER2> You're injecting another site's code into your site which is then rendered in your end user's browser. The security of your site (in terms of client side security) now becomes wholly reliant on the security of your analytics platform provider.

Additionally, you're also giving the provider the opportunity to scrape everything on every page that's served with the analytics code in it, as you have no way of knowing what was served to the browser (as you don't control it).

If you imagine taking popular drive by testing tool BeEF and including that javascript, that's effectively what you're risking with google or any hosted service. Nobody's infallible, they may be better at web security than you. Maybe they're more likely to have an advanced attack?

<comment><AUTHOR> Thanks yeah I was thinking along the same lines, how is this risk best mitigated? By requiring that the analytics provider has had the code pen tested and testing it ourselves?

I don't undertand your second point - what do you mean scrape everything on the page with the analytics code? Doesn't the code, script, zero pixel image simply provide the analytics solution with the tracking data? What is the security risk there?

<comment><USER2> > Thanks yeah I was thinking along the same lines, how is this risk best > mitigated? By requiring that the analytics provider has had the code pen > tested and testing it ourselves?

Ultimately you can't. For example, you include script src="<http://some- analytics-server/foo.js> \- at no point can you assert on behalf of your end user that the contents of foo.js are not malicious. Even if it was penetration tested that only provides a snapshot in time. There's no reason why the .js requested in one request should be the same in all and there's no real means to provide any assurance of it's integrity.

As for my second point if you look at Google Analytics' code you'll see ga.js invoked as in a script src. This means that the code is executed in the browser. That URL _could_ contain anything (although it's unlikely to in the case of Google without people noticing, the fact is you have no control over the content or protection of that content and have to adjust your risk assessment model accordingly to take that into account). It could contain a picture of a horse, it could redirect your users to goatse.cx, it could read the contents of the page it's loaded on (depending upon browser and server configuration), strip out the bits it wants and submit to another server somewhere. You just don't know.

Another thing worth thinking about is that some browsers (thankfully not most modern ones as far as I know) will execute javascript in an img src tag if sufficiently seduced by malicious code.

<comment><AUTHOR> Good points, my thinking is that we are placing a level of trust in the analytics provider, we will mitigate this via the standard mechanisms: due deligence, contract clauses, requiring they have secure development practices (this is where I was going with the pen test). But yes I will capture in the residual risk that there is a risk that the script could contain malware or be subverted. However the analytics vendor has a very large incentive to avoid this, we will also put in service credit and cancellation penalties if this actually occures.

On the point regarding vs. script tags, I doubt the business will allow me to request no scripts, but rely only on cookies, session identifiers and zero pixel images. Wonder if the business benefit could be delivered without scripts....

<comment><USER2> With a blank gif you'll only get what the browser sends. You could set a cookie and track that (to see who else visits sites using your analytics tool), but you're unlikely to be able to pull data about flash configuration, javascript engines, browser resolution and certainly wouldn't be able to build heat maps.</comment></comment></comment></comment></comment>


Ask HN: If you were forced to abandon Mac OS, what would you use? - <AUTHOR> <comment><USER2> I was forced to abandon macOS because Apple abandoned Nvidia and I need CUDA. Now running Ubuntu 18.04.

It's fine. The UX is varying degrees of shitty as always but I can do what I need without too much hassle (mostly vscode/vim and the terminal).

The only thing I really miss from macOS is how nice editing PDFs was in Preview (filling out and signing forms). That and Photoshop.

</comment><comment><USER3> I'd go back to windows. With WSL2 I could probably get over most impediments to my preferred workflow and application choices. Linux is great but honestly I'd get tired of fighting to get a reasonably stable configuration of hardware, display, etc. I just want computer to work.

</comment><comment><USER4> That depends.

On a laptop or most desktops, Ubuntu LTS or something similar. If you still needed macOS or Windows, don't go hackintosh or dual-booting, that's for the birds, just run macOS or Windows under VMware Workstation.

On a powerful desktop, VMware ESXi and then Windows 10, macOS, FreeBSD, Arch or whatever in VMs. If you have GPUs, you can redirect them to the VM... people even use them for gaming sometimes too with minimal overhead.

In general, in a VM, Arch or Gentoo in a Docker container for userland, probably combined with habitat (hab). CentOS/RHEL/Fedora and Ubuntu/Debian packages are always old as the hills and their dependency hell package management is so last century.

</comment><comment><USER5> Arch + KDE full time. Not a macOS-a-like experience but it's really usable. Not using it since getting my 16" MBP but it's what's installed on my desktop PC.

The worst thing about desktop Linux right now is the awkward transition from X11 to Wayland and the fact that high DPI support is pretty bad. It's actually worse in some ways on Wayland despite the support for fractional and per- display scaling because half your applications probably still need to run on XWayland and it doesn't support scaling at all.

</comment><comment><USER6> I did abandon Mac OS several years ago. Still use a 2009 MBP on very rare occasions. Have been using Ubuntu LTS desktop most happily ever since.

</comment><comment><USER7> I recently used a Linux desktop system (Ubuntu 19.4) for a a few weeks, the first time I've used a non-MacOS desktop in about 15 years.

In the last view years, I had gotten the impression that Linux on the desktop had made progress. I was surprised to find the experience at just about the same frustrating level that I last left it a decade ago.

It's all very shiny and translucent. The eye candy must come from the same designers as these fancy gaming graphics cards that are Ferrari red with lots of blinking lights, blinking away inside your computer, under your desk. But that part is not too bad.

What's worse are the inconsistencies and annoyances: windows being placed at locations where it's impossible to grab and move them; model dialogs _behind_ their (deactivated) parent window;

Application UIs follow the Anna Karenina paradigm: they are all unique in their failures. Some have menus in the window, some use the top-of-screen menu bar, other have web interface with Hamburger menus, and then there's Calibre, which must be intended as a cruel joke.

In one non-gnome environment I tried, there was a launcher with menu entries "settings", "system", "preferences", "utilities", and "administration". That's five synonyms as far as I can tell.

There are about six places where I can change settings for the mouse. None of them allowed me to make it behave as it should: it's either dog slow, or jumps 20px for every quantum of movement.

Minor stuff: Search functions that pop up a model "nothing found" alert window whenever they don't find anything. The dialog's "Okay" button isn't focused, so you need to switch to the mouse to dismiss it.

There are three or so places to install software. The Ubuntu Store has no rhyme or reason: search results are a wild mix of well-known software and completely obscure widgets last updated during the Bush administration.

Most of the packages are terribly outdated: the version of Calibre I installed was three years old. And that was from the supposedly faster-moving "snaps" package. The only package manager that didn't give me any trouble happened to be _homebrew_ , ported from MacOS just as recently as me.

Don't get me wrong: I've used Linux daily for at least two decades, on servers via ssh. I'd love to switch to an OSS desktop.

This has really put my opinion of Apple into perspective. There's so much complaining about every new MacOS release on HN and other places, I had started to take them seriously. But the gap to Gnome remains vast, and people claiming to have switched to Linux out of frustration must be lying, or have severely impaired judgement for some reason.

<comment><USER8> It's time you tried KDE.

</comment></comment><comment><USER9> Linux. It's a lot worse than macOS in terms of UI and UX (still better than the hotchpotch UI that is Windows, though) but I simply couldn't do without UNIX command line tools.

</comment><comment><USER10> I'd use Ubuntu LTS and might also dual boot Windows for Photoshop.

</comment><comment><USER11> Linux

</comment><comment><USER12> iOS of course. I'm using it right now as a matter of fact.

</comment><comment><USER13> Qubes

</comment><comment><USER14> go manjaro</comment>


2 is greater than 1 - <AUTHOR> http://www.victusspiritus.com/2009/06/10/2-1/

<comment><AUTHOR> Extends beyond 2 of course. Mostly startup/entrepreneur centric view, but applies to any large scale project/design work. Additional observers refine knowledge of our collective state of awareness.</comment>