_halgari's comments

_halgari | 9 years ago | on: Pixie – A small, fast, native Lisp

I'm the original author of pixie, and yeah, I'm a bit surprised to see this hit HN today.

It should be mentioned that I put about a year of work into this language, and then moved on about a year or so ago. One of the biggest reasons for my doing so is that I accomplished what I was looking for: a fast lisp that favored immutability and was built on the RPython toolchain (same as PyPy). But in the end the lack of supporting libraries and ecosystem became a battle I no longer wanted to fight.

Another goal I had was to see how far I could push immutability into the JIT. I learned a lot along the way, but it turns out that the RPython JITs aren't really that happy with VMs that are 99.99% pure. At one point I had a almost 100% immutable VM running for Pixie...as in each instruction executed created a new instance of the VM. It worked, but the JIT generated by RPython wasn't exactly happy with that execution model. There was so much noise in the maintenance of the immutable structures that the JIT couldn't figure out how to remove them all, and even when it could the JIT pauses were too high.

So anyways, after pouring 4 hours a day of my spare time into Pixie for a full year, I needed to move on.

Some other developers have commit rights and have pushed it along a bit, but I think it's somewhat a language looking for usecase.

And these days ClojureScript on Node.js could probably be made to handle most peoples needs.

_halgari | 9 years ago | on: Eta – A powerful language for building scalable systems on the JVM

And yet, Clojure has less parens than your average JS program. Even Java has more syntactic sugar.

Just compare:

    foo.bar(baz)
to:

    (.bar foo baz)
Same number of parens...they're just in different places.

Sure CommonLisp has a ton of parens, but thats CL and it has its own set of issues.

One more example:

    Runnable foo = new Runnable() {
      Object run(Object bar)
      {
        return bar;
      }

    }
vs

    (reify Runnable
      (run [bar]
        bar))
Less parens, no brackets, no semicolons, and no ceremony. This "parens are killing Clojure" meme is just a straw-man.

_halgari | 9 years ago | on: Eta – A powerful language for building scalable systems on the JVM

I've been a full-time Clojure dev for about 4-5 years now. And the number of times you have to refactor (in the traditional sense) Clojure code is pretty rare. And the reason is that Clojure leverages it's use of immutable data structures, namely hash maps.

So let's say I have a function that needs :name and :addr and it adds a new field calls :name+addr. Now in most (all?) statically typed languages I would have to say that this function takes a "name and addr" and returns "name, addr, and name+addr". So I have a type conversion, right? If the time comes that I need to modify these types, I have to do some sort of refactor.

In Clojure we'd just take a hash map and add a new k/v pair to the hash map we get. Any hash map will work, as long as it has the proper entries, and we'll just add a new entry to that. So if the time comes that I want to call this function with a "company" instead of a "person", it just works, as long as I have the proper keys. And to help check this sort of stuff we do have spec (https://clojure.org/about/spec).

TL;DR -- my belief having programed in both static and dynamic languages is that deep refactoring is primarily driven by the inflexibility of static types.

_halgari | 9 years ago | on: Challenging Clojure in Common Lisp (2014)

Same data in Clojure:

    [{:appt/start #inst "01-02-2014T9:15:00Z" :appt/end #inst "01-02-2014T9:15:00Z" :appt/description "See Anderson"}
     {:appt/start #inst "01-02-2014T10:45:00Z" :appt/end #inst "01-02-2014T11:00:00Z" :appt/description "See Lundstrom"}
     {:appt/start #inst "01-02-2014T13:15:00Z" :appt/end #inst "01-02-2014T16:00:00Z" :appt/description "Attend Y Committee Meeting"}
     ...]

Let's point out some important differences:

1) Clojure prefers maps over cons cells. This means that I always know exactly what I'm looking at. I don't have to guess that the second times are the end-times...I know because it' named :appt/end.

2) We don't overload data types. Have a date? Use a date type. In the CL example we see symbols and numbers sometimes used for descriptions, sometimes for times, etc. Here in Clojure we have #inst ... which creates an actual DateTime object. Now I no longer wonder what I'm looking at, I know it's a date.

3) Clojure prefers data over DSLs. What this calendar example shows is some sort of domain specific language that not only has to be parsed by a program, but it also has to be parsed by a human.

4) Got a meeting description, use a actual string....what's up with the use of symbols as strings (I never understood that about CL).

5) From the perspective of a data modeler...in the CL example if you want a meeting to last over midnight or for longer than a day, it looks like you're sunk.

But thanks for the example, it's fun to see how data modeling is done in other languages.

_halgari | 9 years ago | on: Challenging Clojure in Common Lisp (2014)

Sure, but what do those functions do? In clojure they manipulate data. That's pretty much the gist of the language: using pure functions to manipulate data.

Almost all the work I do these days as a software engineer is data transformation. Going from a HTTP request, which is data (even the header is a hashmap), and a HTTP body, which is data, into some business logic that eventually writes to a database in a different format.

Even the most complex systems I've built containing dozens of servers and multiple databases, queues, http servers, etc. All boil down to transforming data from format A to format B perhaps with conditional logic applied.

So yes, Clojure is a functional language, but functions are just a tool to be used to get the actual work done of transforming data.

_halgari | 9 years ago | on: Challenging Clojure in Common Lisp (2014)

STM and concurrency...sure those are "aspects" of Clojure, Clojure's biggest strength is that it's data-centric. The vast majority of the language is focused around manipulating hashmaps, vectors, sequences, etc, and do that in an efficient way. All the concurrency stuff is just icing.

So I really have to sit back and shake my head when the author says he's going to be as good as Clojure, then goes off into the weeds with custom syntax, STM and actors. Really? Why actors?

This would have been a much better article if it just left Clojure out of the discussion since whenever the author talks about the language he's mostly wrong.

And as always, lies, damn lies, and benchmarks: https://benchmarksgame.alioth.debian.org/u64q/compare.php?la... If you're going to use a phrase like "faster", at least spend some time to define the word.

_halgari | 9 years ago | on: Challenging Clojure in Common Lisp (2014)

Can we get some sort of edit to this title to show that it's from back in 2014? A ton of work has gone into Clojure since then and in some aspects the language has gotten orders of magnitude faster (not that it was really that slow to begin with).

_halgari | 9 years ago | on: In 2017, learn every language

Clojure - prioritized rich immutable data. I haven't found any other language that prioritizes open data sets: where a map has "a" and "b" but it could also have "c" and "d", if you only care about "a" and "b" it doesn't matter if the other data just tags along.

And I say "rich" data since other languages are pretty data-centric (scheme of course), but not any that prioritize immutable hash maps, sets, vectors, linked-lists, etc.

_halgari | 9 years ago | on: The Next Five Years of ClojureScript

CLJS has been self hosted for about a year now. It's cool, but its really not needed. Google Closure on the other hand is amazing. I've seen speed improvements of 10x when switching to advanced compilation mode. Its not just dead code elimination, its also partial evaluation and inlining.

_halgari | 9 years ago | on: Why we chose Vue.js over React

React is about the only real framework in the ClojureScript community, via frameworks like Om.Next and Reframe. React in JS is rather clunky since you're dealing with a mutable language that prefers OOP primitives. In ClojureScript most UIs are data-driven and declarative and that's where the strengths of React really shine. So I would argue that ClojureScript turned React into a better React.

_halgari | 9 years ago | on: Spec-ulation – Rich Hickey [video]

Absolutely, I think the "perfect world" would be adopting some of the ideas Rich proposes but adding (git url + sha) as the dependency management system.

Of course for that to work well you'd also need to protect yourself from people deleting their git hub repos, or rewriting git history.

_halgari | 9 years ago | on: Spec-ulation – Rich Hickey [video]

Sadly then Go went and shot themselves in the foot. Originally (I assumed this hasn't changed), you specified dependencies via git URLs. Sounds great, but then they went and said every dependency always used the head of master. So now you're in the horrific situation of your deps suddenly changing whenever your build decides to pull the latest from the git repos.

(Note: I don't use go, but this was the situation about 3 years ago when I last looked).

_halgari | 9 years ago | on: From Kafka to ZeroMQ for real-time log aggregation

ZMQ's default behavior (and in some cases only behavior) of dropping new messages when buffers are full, made it a no-go for my client. We ended up switching away from ZMQ to a more traditional durable queue and ended up saving a ton of code complexity and got a lot of reliability in the process. Having now researched it I can't think of a reason I'd ever use ZMQ again. I'll either use a durable queue when I care about message delivery, or something much more traditional when I don't.

_halgari | 9 years ago | on: GitMonitor on Elixir

"Elixir is blazing fast" it says, so I follow the link and notice that "blazing fast" apparently means 10x the speed of Ruby. I don't think that phrase means what they think it means.

_halgari | 9 years ago | on: Two Years of Eve

You honored my rant with a reply, so I will honor it with a reply as well :)

The problem is this...when software is designed it is critical to know what is being solved. I don't think the problem set or the way they will be solved has been nailed down, or if it is, it has never been properly explained. In two years of work, and 2mil in funding I would have expected at least a usable alpha (80% complete prototype) in this amount of time. Perhaps that's a wrong expectation, but without even a problem statement and a roadmap, how am I to know?

I have yet to see a rationale for Eve. I'd love to see a 1 paragraph description of what the problem is Eve is trying to solve. Then a bullet point list of goals and non-goals. After that I would love to see a list of architectural decisions (is Eve distributed or not, what size of datasets is Eve aiming for, etc.). After that I'd love to see a list of tradeoffs (because we are distributed, we have these problems. 1GB datasets will require optimizations around ingestion, etc).

Without all of this, all I see is two years of vaporware and a few developers spending investor money hacking on pet projects.

page 2