HNHacker News
TopNewBestAskShowJobs

cpleppert

2,035 karma · joined September 27, 2010

submissionscomments
cpleppert··on India may build new coal plants due to low cost despite climate change
It isn't just about prioritizing the latter. For india, Money spent on improving the economy or alleviating poverty goes a lot farther than spending on carbon neutral energy.

For a rich western nation like germany? Not a lot of low hanging opportunities so might as well spend on green energy.

cpleppert··on What should we agree on about the Repugnant Conclusion?
>> So the most ethically optimal population is one in which adding new members will cause life to no longer be worth living to at least the same number of other members.

I can't see how that follows. The paradox is comparing possible worlds which have differing average happiness and total populations. It doesn't follow that there exists some way to transform each world so that it matches the other. You aren't killing off the excess population in B to somehow reach A or vice-versa adding population. The paradox exists because you are comparing the happiness of a person which doesn't exist in one possible world with his (realized) happiness in another.

There could be any actual relationship between population size and happiness but the paradox would still exist because you wouldn't be able to order the desirability of some possible worlds.

cpleppert··on Is WebAssembly magic performance pixie dust?
>> This not only ensures correct 32 bit integer semantics (like wrapping around), but also helps the engines to use actual integer instructions in the generated machine code.

But there is only one type of number in javascript. Everything is just a double(BigInt aside). You get a 32-bit integer because the bitwise operator casts the result to one. c has the exact same semantics as any other js number.

Yeah there are tricks to convince the engine you are using an integral type but those unless you are doing a lot of benchmarks they aren't really useful. Any compilation tier can choose to use any intermediate representation it wants.

cpleppert··on Is WebAssembly magic performance pixie dust?
WASM can be faster than JS but you need a language that doesn't shoehorn a GC into the compiled binary. I'm not really sure what the author expected here. Modern managed runtimes usually give you the benefit of bump allocation in the nursery for free with a generational GC and the runtime has a lot more room to optimize the GC phase. None of this is possible without a native GC for webassembly.

This isn't WebAssembly being slow the benchmarks just show the overhead of the GC. If you are writing a computationally expensive algorithm in Rust or C++ wasm can be a lot faster but its hard to get close to native performance(i.e. running on bare metal x86/arm).

Our webassembly prototype is about 3-4x faster in raw computation(and that is targeting webassembly exclusively) but has a much higher overhead when interacting with the DOM. That is basically the limiting factor especially on mobile.

cpleppert··on Why machine learning struggles with causality
> First, you make a mental model. Then, you test it.

Except that isn't how that really works right? A mental model explains part of the reasoning that led to an outcome but never all. After all, the map is not the territory. A mental model is grounded in trivial assumptions. Ultimately, your brain produces inferences in a way that is incredibly hard to couple to a specific logical processes. There has been a lot of research on how experts think and reason and none of it is compatible with having a mental model whatsoever.

cpleppert··on Why machine learning struggles with causality
Except AI isn't being 'sandboxed away' in any discernible way. A child being an unpleasant annoyance isn't comparable to a an AI that can't drive in either risks of failure or capability because the child is far more capable of moderating his behavior to conform to social norms than an AI.
cpleppert··on US, Europe 'unrealistic' in fab expansion drive, says TSMC chair
That would be incredibly dangerous for Taiwan because China would react if it felt the military balance would actually change.

More importantly, the EU/US are not really in a position to make a credible threat to China. Let’s say they China declares its intention to forcibly ‘reunify’ Taiwan. EU sanctions on China would be incredibly painful... for the EU. The EU just signed a new trade treaty with China which probably tells you all you need to know about that option.

So down to the US. If the US didn’t deter China by trying to change the facts around Taiwan when it was considerably weaker it’s hard to understand why the US would take that step now.

That’s kind of the problem here. There isn’t anything that would credibly deter China at all so taking moves to antagonize China don’t accomplish anything. Even if other countries felt threatened by this they would much prefer to engage in ‘buck passing’ rather than taking actions that would directly hurt them.

cpleppert··on US, Europe 'unrealistic' in fab expansion drive, says TSMC chair
It doesn’t make economic sense to build basically an entire new supply chain though.

You can’t just build a modern foundry with any amount of money. TSMC is part of a massive supply chain and engineering cluster. If you wanted to build something that looked like TSMC and in an emergency could produce something in six months you are probably talking about tens of billions per year at a minimum. Most of your costs are things TSMC gets paid for.

Since that doesnt really make sense you probably want a homegrown competitor. You just don’t have the domestic experience and expertise to replicate what TSMC has; It will never be cost competitive. TSMC can send billions on fabs and recover their costs and a domestic alternative will never be able to. Modern chips have to be adapted to each foundry; a homegrown alternative will have to eat this cost at first just to get orders.

If you want to be competitive you need to go big and stay there. Something like $100 billion a year for the foreseeable future would be the minimum. You could probably limp along with massive discounts.

cpleppert··on A categorized list of all Java and JVM features since JDK 8 to 16
Worth keeping in mind that the implementation they have chosen of stack copying from the heap has a larger performance overhead than something like Go which was designed around green threads/fibers/virtual threads/ etc. from the start.

If you can keep your stack size very low in each task then this probably won’t be noticeable if you are doing lots of IO which can trigger wakeups. More of a replacement for an async/await state machine for handling a request than something like a goroutine you could use for everything.

I have a feeling lots of existing Java libraries and frameworks won’t work well with it. Will be interesting to see how it plays out.

cpleppert··on U.S. fears China attack on Taiwan
I think this article essentially misses the mark. China isn't flirting with taking Taiwan because the leader is willing to take risks; China is flirting with taking Taiwan because it now has overwhelming military superiority over Taiwan.

The United States has bases thousands of miles away while Chinese bases are literally right there. China's capital spending on military capabilities (new + direct research & development) is almost certainly higher than the United States which is burdened by personnel spending and world spanning commitments. China can afford to focus its gigantic military preparations on a single objective; its preparations are literally mind-blowing.

As for when China will seek or threaten a military solution it depends on tradeoffs that only the leadership knows. Does China want a provocation to unify its society in a war? What margin of military superiority does it require to avoid long term economic damage to Taiwan's economic prospects? Will the world become more dependent on Taiwanese semiconductors or less? Most importantly, how does CCP view the benefits of ruling a unified China as opposed to the costs of a war?

cpleppert··on Was German unification inevitable?
I don't think those cases are really comparable. Scandinavian countries had separate state institutions (even when countries were part of the same empire or composite monarchy) in a way that didn't apply to the former Holy Roman Empire/German Confederation which were nominally part of the same political unit and saw themselves as having much closer ethnic ties. The HRE was seen as an entirely german political entity and had almost no non-german kings in its entire history. The fact that German states jealously guarded their sovereignty does not mean they did not see themselves as fundamentally german.

Similar reasons apply to Italy. Because of the geography of the Italian peninsula a unified Italian nation state would be much more successful economically than a patchwork of small entities. Once Italy's maritime commercial decline began states had less incentive to block unification.

>> Put another way, German unification was not for the benefit of Germans, but for the benefit of Prussia.

The rest of Germany not only strongly benefited economically from german unification but also supported protective tariff policies after unification that had the effect of tying their economies much closer to Prussia (and vice-versa of course). If they didn't believe it was in their interest why in the world would they do that? If anything, the rest of the German states probably engaged in free-riding off of Prussia's military support. This once again benefits both sides.

cpleppert··on Was German unification inevitable?
The $2T cited in the book does not refer to the direct costs paid to Russia but to the total amount spent on reunification which came out to something like $100 billion per year for twenty years.

The opposition of the rest of Europe and Russia has to be put in context. Russia would not have been able to support the East German economy nor would it have been able to afford to maintain a pointless troop presence that would no longer have local support. The rest of europe might have been opposed because of historical reasons having to do with security but not allowing unification would have created a massive roadblock for the european economy. Short of reunification, there was not an acceptable legal regime to end Germany's limited sovereignty(which the rest of europe supported).

Given that Germany strongly supported reunification and the US was in support for obvious geopolitical reasons there was no way for any other power to stop the process. Russia could either be paid to leave or get nothing and spend money it doesn't have to maintain the troop presence to boot. Poor relations with Germany would have had a catastrophic impact on the Russian economy. The UK was never really serious about stopping reunification and barely tried to bluff. Similar reasons apply to France which could not oppose reunification and support European integration.

For all these reasons I find the the focus on contingency to be rather overdrawn. It was not inevitable in the sense that it had to happen(you can come up scenarios where the soviet union continues into the 21st century) but given the collapse of the Warsaw Pact it's hard to understand how unification could have been ultimately prevented.

You can see a similar dynamic taking place in South Korea where unification is broadly supported by the younger population in the face of titanic security and economic concerns. German unification has been supported for hundreds of years for comparable reasons.

cpleppert··on What World War I Can Teach Us about Misjudging Tech and Social Change (2020)
>> demographic changes in France - higher relative population growth

I think you have it exactly backwards. France had a significantly slower population growth. To give one example of how this impacted the military caculus: Germany was able to easily expand its army in 1911 and 1913 and still have a large reserve pool of manpower but France had to increase the term of service from 2 to 3 years and expand its conscription to almost the entire adult male population of fighting age; which led to riots and political chaos. At the time of the outbreak the French army had been expanded so rapidly that training had to be cut significantly.

>> However, the types of wars in which the Great Powers of the time were involved - and from which their military planners derived their assumptions about war with modern weaponry - were mainly colonial conflicts against relatively under-armed opponents, eg. the Boer war, which the Great Powers typically "won." The outcome of the Russo-Japanese war (1904-05) was shocking enough to change the calculus for planning the European war, as Russia was now seen as a less able ally for France... and on and on such analysis could go!

I would strongly disagree. Russia lost the Russo-Japanese war mostly due to inept military execution and the difficulty of troop transportation through an incomplete Trans-Siberian railway; hardly relevant to a european total war. You could argue( and some less astute observers at the time did) that Japan's victory through aggressive assaults on static russian positions 'proved' that offensive power would carry the day to a decisive conclusion.

cpleppert··on What World War I Can Teach Us about Misjudging Tech and Social Change (2020)
Angell's argument was more along the lines that war cannot be strictly justified by economic, financial, or security incentives: "(2) War is not impossible, and no responsible Pacifist ever said it was; it is not the likelihood of war which is the illusion, but its benefits." [^1]

His point was that economic interdependence in the current age(1910-1860) meant that changing the international order by force of arms would not lead to a more favorable outcome for the aggressor. In fact, quite the opposite. The aggressor's economy would be wrecked even in victory no matter the length of the war. Economic isolation from world trade and credit would be devastating.

If he was claiming that war was impossible would he bother to write a book arguing that the benefits of war were not commensurate with the cost? The entire reason he wrote the book was to dissuade 'militarists' and stop the buildup of military potential that began with the dreadnought race and germany's more aggressive wilhelm foreign policy. The book was almost directly aimed at a german audience as a result.

[^1]: http://www.gutenberg.org/files/38535/38535-h/38535-h.htm#Pag...

cpleppert··on Jepsen: Scylla 4.2-rc3
> The only safe use of these 2 software is basically: 1) add new unique rows (no updates) 2) much later (granted only after repairs, which take a real lot) you can read, but only up to a certain time in the past. 3) basically almost avoid deleting

1000x this

That is exactly what Cassandra was originally designed to do. Cassandra doesn't implement complex distributed mechanisms that would make it hard to operate and implement like most distributed databases or impose a cost on application developers to understand the tradeoffs they will have to grapple with and make the. Cassandra is not AP with less than a quorum read/write or CP with a quorum read/write. It only fulfills those guarantees in the way you might expect if your cluster topology never changes and your timestamps are carefully synchronized.

Absent these guarantees modifying existing data is essentially an undefined operation. This isn't a shot at cassandra developers. Cassandra isn't magic. There is no possible way it can magically use a simple last write wins strategy to guarantee that data updates won't be lost in the absence of outside guarantees.

Cassandra is essentially a prototype of a class of NoSQL databases try to be incredibly easy to manage for write heavy workloads. Look, I get it, it was a collection of appealing technologies, I found the original white paper on Cassandra interesting too. columnar read-repair eventually consistent merkle trees NoSQL column family super columns cluster gossip phi accrual failure detector

Of course, the 'columnar' attribute was originally intended so that applications designed around cassandra could reconcile multiple values associated with a single key:attribute path without having to utilize a complex api. Whether this is actually viable is another story entirely.

CQL's only advantage is that it vaguely resembles SQL. CQL is not a query language. It is a collection of Cassandra operators mapped onto a vaguely SQLish syntax that bears little relation to the underlying semantics they are derived from. Cassandra just shoehorns a bunch of its idiosyncrasies onto an SQL look alike. INSERT and UPDATE do the same thing(which is not what SQL does for either and are probably not what you expect). The entire behavior of how a 'query' is actually executed can change drastically. In order to use Cassandra correctly you have to understand how the database physically implements every operation. So the query language doesn't provide a meaningful abstraction at all.

CQL would have never made sense in the original implementation of cassandra because cassandra was never designed to do the things that people expect from a database that implements a query language.

cpleppert··on Sweden edges closer to NATO membership
Nonsense. Turkey allied with the United States when Soviet demands post-WWII induced the republic to seek a security guarantee for eastern anatolia. This occurred prior to any formal NATO membership and turkey previously demonstrated its alliance commitments by supporting the united nations in korea. Turkey wouldn't have allowed nuclear weapons to be based on its territory because of 'concessions'(in fact, they protested their removal after the cuban missile crisis).

Since the Bosphorus/black sea region is vulnerable to a blockade traffic to the Mediterranean sea can be easily closed by the US Navy in times of war regardless of the political regime that controls the straits. Turkey was far more geopolitically important when Russia had a Mediterranean ally(france) and control of the mediterranean was contested.

cpleppert··on Balancing the needs around the CentOS platform
The entire value proposition of CentOS/RHEL was you don't have to do things like compile your own kernel. You have a relentlessly tested operating system with the certainty of knowing it is compatible with anything you could run on it. You don't want to manage multiple versions in the first place.

> Unless you are doing kernelly things then the small difference in kernel version will not be that big a deal. > It's also not very hard to compile your own kernel if you really need an exact version.

It isn't about having a specific version because the RHEL kernel backports features anyway. If you are compiling the RHEL kernel you might as well use the actual distribution that has been tested with it. What would be the point otherwise?

cpleppert··on Balancing the needs around the CentOS platform
The intention behind this was obviously a business decision[^1]. You don't need to read an article with quotes from redhat executives to understand the reasoning. Putting out articles like this to obfuscate the reasoning just creates distrust. Obviously Redhat wants to move as many people as possible over to subscriptions in light of cloud offerings hurting them with their core enterprise market.

[^1]:https://www.zdnet.com/article/why-red-hat-dumped-centos-for-...

cpleppert··on The Mill CPU Architecture: Switches [video]
>>If we assume that they really do mean "associative cache" for the predictor table, then that's obviously something that really works in hardware, and can be updated on mis-predicts. Flushing the predictor state out to some OS-accessible area when the task quits doesn't sound like magic to me.

That is quite a complex operation though. How large is the associative table that is being flushed and how often does the flushing occur? Assuming we are talking about something in the general size of a BTB loading this entire segment into the branch predictor on very context switch is possible(although how this is implemented on silicon would have to be quite complex)

The data structure described in the paper must be quite a lot larger than a simple BTB though if the predictor is to work as described. It has to hold significantly more information than a BTB if Mill wants to replace all the other associated branch prediction machinery with a table that needs to predict every target. I don't believe a prediction table this size would be feasible to load on every context switch. It's possible they want a smaller table and to replicate some of the branch prediction machinery in a modern CPU. But this seems to defeat the entire point of having a prediction table produced by a compiler and updated by successive runs of the program.

It's very hard to tell exactly what they are loading or what the table will actually do. That's why I'm not surprised they described it as a hash table. It's a simple explanation for how their solution works that avoids having to explain tricky implementation details.

>> but I don't think you've adequately explained why it's impossible to pull off.

I think it's theoretically possible in the sense that they could design silicon that does something similar to what they described. I totally understand what they are trying to do:

Have the compiler produce a complete set of predicted branch targets and improve the targets over time by instrumenting the process. It sounds great superficially, you don't have to bake any branch prediction logic into the cpu at all and you can use the all the information the compiler has combined with how the program actually runs. The problem(performance-wise) is that most branches are executed many times and have dynamic behavior that can't be exploited by just producing a table of branches.

Silicon-wise I don't see any way they could integrate such a complex piece of standalone logic into the frontend of the CPU and still maintain acceptable latency. The branch predictor of modern CPUs is incredibly well engineered and optimized and this just isn't in the same ballpark and can't perform as well.

cpleppert··on The Mill CPU Architecture: Switches [video]
I'm not sure I follow about the benefits of this branch prediction scheme in the first place. I already have a branch target from the branch target buffer( assuming I'm in a conventional processor), so either the frontend can begin immediately loading code from the cache or I stall while I load from main memory. I'm never prefetching anything(at least in terms of an initial target)

Let's assume that Mill can produce a prefetch chain though that can load additional code segments beyond the initial branch target. Does this really benefit the processor? I don't understand how a static prediction of where I will branch to next after an initial branch target is even useful. If I have already branched to that location before the code will be sitting in the L1 cache waiting for me, if it isn't, well, how does the branch predictor know more about the behavior of my program than the L1 cache?

To put it another way: if the instruction set doesn't fit in the L1 cache is there some predictable way that I can load and unload the cache just based on a given branch target( that in turn implies other branch targets will be loaded next with a total instruction set larger than the cache). I don't really think there is any possible way to predict the behavior of an entire program like this. Larger instruction segments and more branch targets imply more complex programs that are correspondingly harder to predict so I'm always better off just relying on the instruction cache.

Assuming Mill tries to load entire chains of instructions into the cache based on a simple static target I would be much better off just disabling this and relying on the instruction cache in almost all cases therefore.

cpleppert··on The Mill CPU Architecture: Switches [video]
>> One of the perennial questions that I've never received a satisfactory answer to is: Where's the ILP?

Anyone with any experience in the field can come up with an instruction encoding structure that produces more instruction level parallelism in theory. It's usually a simple mental exercise to determine that such a CPU isn't implementable in the "real world." That's exactly what is happening here with Mill except they have really dived off the deep end and do so much handwaving that it's hard to tell exactly how mill is supposed to work.

Take branch prediction: Last time I checked they wanted the processor to load what they described as an "exit table" associated with a module of code that serves as a branch prediction unit. The problem is that this doesn't work at all. You can't have a CPU load a separate data structure that replaces its internal state like this.

First off, this is way too complex as a piece of front end logic for the processor. Trying to access this as code is running is basically impossible. Secondly, A branch predictor has to produce a prediction immediately, you can't just handwave and say you will ask an internal data store structure to produce a result. Their description of this is that it is in some way a "hash table" (http://millcomputing.com/wiki/Prediction). That's really interesting because you would never ever want to implement a hash table in a CPU. Either a) they described it analogously as acting like a hash table; which doesn't make a lot of sense here in a technical description b) they really want to implement a hash table lookup as a branch predictor which be horrendously complex and would never work latency wise or c) they are are calling an associative cache a hash table. They also want to somehow update this "hash table" with a correct prediction on a mispredict. So somehow the processor will update a separate data structure (using a hash table lookup) every time there is a misprediction. Which again, doesn't work latency wise.

By the way, all of this somehow has to be loaded and unloaded seamlessly into main memory.

Notice that there is no description of any advanced logic that is used in modern processors to dramatically increase the accuracy of predictors. I don't even understand how they would possibly implement any of that advanced logic with the branch prediction unit so complex and decoupled from the front end of the processor.

Of course, this kind of compiler driven prediction has been tried before and it doesn't work for obvious reasons. The compiler has a lot less information about the current state of the program than the processor does.

So to recap: they described a feature that doesn't work as described, if it did work would be horrendously complex and wouldn't properly work as a branch predictor and finally doesn't actually provide better predictions at all.

This is basically Mill in a nutshell.

cpleppert··on [dead]
>>Do Trump's supporters, who are largely working class, represent the working class...yes

This isn't true, most of his voters are richer than Hillary voters by a long shot.

cpleppert··on Russia plans to install Pole-21 anti-missile jamming device on cell towers
It doesn't even make any sense at all. Why would you install jammers on every tower? You clearly don't need to cover the whole country. The maintenance cost of trying to coordinate access with the telecom company and install extra equipment would be insane.
cpleppert··on Chelsea Manning Asks President for Clemency and 'First Chance at Life'
>> Incidentally, what are the war crimes that were specifically revealed by this leak?

I guess the same as the massive corruption exposed by the brave Julian Assange of the infamous organized criminal organization known as the DNC. What? All the emails occurred after Sanders mathematically lost the nomination? Are you telling me the DNC was trying to support the certain nominee in a general election? Horrible and shocking!

On a related note the DNC scheduled so few debates because they wanted to help Clinton clearly. (Just ignore the fact that the number of debates was comparable to 2008 with far less candidates and a less competitive race.)

cpleppert··on Chelsea Manning Asks President for Clemency and 'First Chance at Life'
>>Part of the reason I did not go out to vote for Clinton was because she was a continuation of Obama's policies; civilian collateral damage from extrajudicial drone strikes, no pardon for Edward Snowden, the possibility of a drawn out proxy war in Syria, as well as no stop to the NSA domestic surveillence program. (Neoliberalism = "Republican lite") You might retort "But Trump! (and his threats of killing families of terrorists, etc)". If Clinton was elected it would've been business as usual, everyone would've gone back to their bread and circuses. Not now though.

Regardless of what you think of Clinton Trump was a far worse alternative on every measure. Trump will be able to dramatically change the supreme court and US federal legislation as well. Complaining about Clinton/Obama doesn't change the simple fact that he is far to the right on her on almost every issue.

>>Sidenote: Trump has already swung moderate, deciding to stick with NATO [2] and keeping most of the ACA after speaking with Obama [3]. Maybe he doesn't stick to those ideals, but its clear Trump the president may not be as bad as Trump the person. I have hope, but I had hope for Sanders as well. (Excitingly enough, the /r/SandersForPresident subreddit was reactived today, with ~210k active subscribers).

Trump CANT keep most of ACA even if he wanted to keep the good parts. The expansion of coverage is paid and supported by the entirety of the law, it doesn't work without all the provisions.

cpleppert··on Donald Trump will now control drone assassinations and mass surveillance
>>How many "typical campaigns" pay people, including explicitly mentally ill people, to commit violent acts to give an impression that the other candidate is violent, will bring violence if elected, etc.? (Granted, that didn't come to light by emails, but they helped to confirm it.)

You mean the heavily edited video that the group who did the so called 'expose' refused to release in full?

>>And speaking of violence, how many modern candidates for President have seriously desired to commit high collateral drone assassinations in 1st World countries of people who aren't exactly making war on the US per se, aren't even under any US indictment? As I say elsewhere, Julian Assange is no doubt resting a bit easier.

That was a joke. Hard to take you seriously when you make things up like that.

>>Ditto that one party's wiring the nomination for a particular candidate,

She won overwhelmingly, no 'wiring' required. There was a reason no one else challenged her.

>>And that's not even touching on the possibly traitorous criminal conspiracy of the foundations. Which I doubt Obama will pardon wholesale, and then we'll get to see if Trump truly wants to "drain the swamp".

AIDS drugs for africa? Yup, treasonous activity. Hint: You don't use a charity foundation as a front for 'traitorous criminal conspiracy.'(that sounds really bad, and clearly not a collection of ominous sounding words you threw together in lieu of a coherent thought)The clintons made their money through the paid speaking circuit. Why the hell would they launder money/favors through their foundation? (Hint: they didn't)

cpleppert··on Martin Luther King on “Guaranteed Income” (1967)
A negative income tax has the same issues as a basic income. It isn't remotely affordable based on the current tax rates without large cuts to social spending and/or eliminating it entirely.
cpleppert··on The 14 Characteristics of Fascism (2003)
>>but I suspect she and her assistants are well aware of the laws, may have stretched things to limit but careful not to step over.

What actual evidence is there of this? The clintons receive more than enough money through paid speeches and those would be the route you would use if you wanted to set up a quid pro quo. Using a charitable foundation to do this doesn't make sense generally nor in this case. Of course, lobbying and getting on paid boards after a government career is basically a quid pro quo( the presumption is that after you work for the industry you get a cushy career paid by the industry you helped) but that has been totally ignored this election cycle.

cpleppert··on The 14 Characteristics of Fascism (2003)
>>He foundation pay-to-play activities for instance -- highly illegal

Not sure how soliciting charitable donations is pay to play. On the face of it laundering donations through a charitable foundation is pretty stupid and pointless and it seems unclear how donations would drive her to take the risk of doing a quid pro quo when the quid has little personal benefit to her.

cpleppert··on Does Chinese Civilization Come from Ancient Egypt?
This is false. The Chinese writing system and Mythos have no connection at all with Egypt. Descriptions of rivers predominate in ancient myths and there is no reason to construct a hypothesis that has little explanatory power and even less plausibility.
← PreviousPage 5 of 15Next →