a) Data is just data, divorced from behaviors, and functions (not methods) manipulate data. This is really just old-school functional programming.
b) Data is represented by hashmaps, and are extensible - if the data gets richer over time (= more keys in the hashmap), functions that used to work on the previous, poorer data still work on the new, richer data. In other words, each key of a hashmap is automatically an interface, and data satisfies interfaces depending on which keys they have (structural typing).
Now, this interface mechanism is a bit sloppy if keys are just string identifiers, but this is overcome by namespacing keywords (which has its own syntax, ::keyword), thus removing the risk of the same name being used for different purposes. This idea is most clearly articulated in the core.spec library, which encourages you to establish a 1-to-1 relationship between a (namespaced) keyword and a spec (https://clojure.org/guides/spec#_registry).
Previous dynamic languages have always used hashmaps to represent data, either directly or indirectly. But once in the land of high-level abstractions, they would revert to "canonical" Java-style OOP (Python and ES6 being the most notable examples). Clojure seems to be the only mainstream-ish language out there that uses -- or at least aspires to use -- hashmaps as a real abstraction mechanism rather than a convenience.
I don't see why that would be at all relevant to porting to other platforms? Most languages with richer syntax would parse to a backend-independent AST first, and so porting to a new platform would not require touching the parsing code at all - you'd be working on the same level as S-exprs, effectively.
The difference Clojure has is that the core language is tiny, but you could do this with an alternative syntax as well. You'd just need macro support, even if they're more clumsy to write.
(I literally have an editor open working on a Clojure compiler as I write this, so I don't disagree with your premise).
(or the original M-expressions for Lisp)
RICH HICKEY: Ok, so, problem number one on that list was place oriented programming. Absolutely, this is the problem. Almost all the programs I wrote, lots of the things on that list were multi-threaded programs, you know, they're crazy hard in C++. Just impossible to get right, when you adopt a normal mutability approach, you know, mutable objects. So, this is the number one self-inflicted programming problem. It seemed, you know, clear to me that the answer was to make functional programming and immutable data the default idiom. So the challenge I had was, were there data structures that would be fast enough to say, "we could swap this for that". And the objective I had, the goal I had was to get within 2x for reads and 4x for writes. And I did a lot of work on this, this was actually the main research work behind Clojure, was about these persistent data structures. Eventually I found...you know I looked at Okasaki's stuff and, you know, the fully functional approach and none of that gets here. And then I found Bagwell's structures were not persistent, but I realized could be made so, and they just have tremendously great characteristics combining the persistence with the way they're laid out, the way memory works. They made it. They made this bar, and I was able to get my friend to try my programming language. You know, we (?) have large library of pure functions to support this, and, you know, immutable local bindings. Basically if you fall into Clojure, your first hurdle is not the parentheses, right? It's this, this functional paradigm, everything is gone, there's no mutable variables, there's no state, there's no mutable collections and everything else, but there's a lot of support, there's a big library. You just have to, you know, sort of learn the idioms. So I think this was straight-forward, the critical thing that's different about Clojure is, by the time I was doing Clojure, the people who invented this stuff had adopted a lot more, right? I think most of the adherents in the functional programming community considered functional programming to be about typed functional programming, statically typed functional programming is functional programming. And I don't think so, I think that this is, you know, this falls clearly in the 80/20 rule. And I think the split here is more like 99/1. The value props are all on this side, and I think Clojure users get a sense of that, they get a feel for that. This is the thing that makes you sleep at night.
https://github.com/matthiasn/talk-transcripts/blob/master/Hi...