
Four MLs and a Python (2015) - breck
https://thebreakfastpost.com/2015/04/22/four-mls-and-a-python/
======
eatonphil
I'm really grateful for this guy's posts. It can be a nightmare figuring out
how compilation works across different MLs. I just ported my Ponyo library for
Standard ML to support MLton and his guides were a great aid. Keep up the good
work!

~~~
cannam
Thank you!

Did you notice this one? [https://thebreakfastpost.com/2016/06/11/naming-
conventions-i...](https://thebreakfastpost.com/2016/06/11/naming-conventions-
in-standard-ml/) It's definitely a bikeshed moment, but I had meant to drop
you a line to ask you why you chose This_Sort_Of_Naming for structures in
Ponyo. It seemed a bit of an outlier.

I'm delighted to see you're still doing bits of work on Ponyo. I have a
pleasant pipe-dream that, while frameworks and libraries for other languages
rot because of language evolution, decades of random tiny personal SML library
projects - written for a somehow still-modern language that never changes -
eventually turn out to constitute a genuinely sound basis for new development
work.

~~~
eatonphil
Ha! It's funny (and great!) to be featured there. The particulars of the
naming convention are pure preference I suppose (and I recently simplified the
naming of files [perhaps to the detriment of convention?]). I'm still trying
to figure out proper naming conventions though and I'm not completely
consistent. This makes the automated documentation generation I've tried to
put in place hard...

Anyway I'd like to point out that the namespacing exists at all because all
structures in Standard ML are global by default. Some implementations have
compilation managers that allow you to hide certain exports but Poly/ML does
not. In general, if I define a String structure, I just overwrote the Basis
String structure. (Ponyo exports a Basis structure up front that exports all
overwritten Basis structures so you always have a way back). You could always
overwrite these yourself, but _Ponyo_ itself prefixes all structures with
their path for pseudo namespacing. But Ponyo also exposes them in a hierarchy
for ease of use (the Ponyo structure embeds the Net structure which embeds the
Http structure, etc.). But the original named structures are still accessible
too. The worst part is signatures and functors. In the Standard ML standard,
functors and signatures cannot exist inside of structures. This is a pain in
the butt... And some non-standard extensions exist to support this (at least
in SML/NJ maybe also in MLton). So in those cases you must ignore the
structure access convention (Ponyo.Net.Http...) and use the full real name
(Ponyo_Container_Dict). So in the worst case it's C-like (with only
string/prefix "namespaces") and in the best case you can access and make
shortcuts to intermediate structures (structure H = Ponyo.Net.Http).

~~~
cannam
Yes, it's disappointing that you can't just open a structure to wrap an entire
other SML library or program. SML's module mechanism is usually very tidy but
it has its awkward aspects, a pity for an otherwise so elegant language.

------
dfboyd

      (ns fourmls.core
        (:gen-class))
    
      (defn csv-line-to-doubles
        [line]
        (map #(Double. %)
             (clojure.string/split line #",")))
    
      (defn barf-if-different-lengths
        [s1 s2]
        (if (not= (count s1)
                  (count s2))
          (throw (Exception. "Mismatched lengths"))
          s2))
    
      (defn sum-csv-lines
        [prev curr]
        (if (nil? prev)
          (csv-line-to-doubles curr)
          (->> curr
               csv-line-to-doubles
               (barf-if-different-lengths prev)
               (interleave prev)
               (partition 2)
               (map (partial apply +)))))
    
      (defn -main
        "I don't do a whole lot ... yet."
        [filename]
        (println
         (clojure.string/join
          ","
          (map str
               (reduce sum-csv-lines
                       nil
                       (->> filename
                            clojure.java.io/reader
                            line-seq))))))

~~~
joncampbelldev
Very nice.

Perhaps using (partition 2 1 _) could be a clearer way to view the prev line
instead of the reduce on a nil?

------
pmoriarty
This article doesn't talk at all about safety, which is one gigantic advantage
modern statically typed languages have over traditional dynamically typed
ones.

It also doesn't talk at all about the pain of having to wrestle with the
compiler in statically typed languages in order to get the damn thing to
compile, nor with having to deal with inscrutable error messages that
sometimes need years of type theory courses under your belt to understand.

~~~
aaronchall
Discussing "safety" isn't safe unless you properly define your terms. That is,
otherwise, you don't know what type of "safe" people will interpret your words
to mean.

(Sorry, tongue got stuck in my cheek.)

Of course, you probably mean type-safety? For example, if you try to add an
integer and a string in Python you'll get a TypeError.

Hindley Milner proves that we can infer the most general type of a program. I
wonder if your concerns about safety are misplaced, but then I think of
languages where one _can_ add 1 and '1' and then I think you've certainly got
a point.

~~~
f00_
php for example(?)

type casting there always seems horrible

------
a-nikolaev
A probably better OCaml implementation:

[https://gist.githubusercontent.com/a-nikolaev/b6fb099ebb28d7...](https://gist.githubusercontent.com/a-nikolaev/b6fb099ebb28d7f58e71e51981960920/raw/244d73198fdd7f2db7db2d3f359e746763275742/sumup.ml)

With similar improvements to the solution posted in the article's comments,
tail recursive, and no need for regular expressions. Works about 15% faster.

------
marmaduke
I did a similar comparison of expression evaluation in C, C++, Haskell, OCaml,
Go and Python. Oh Java too:

[https://gist.github.com/maedoc/cfd893b8fed9ee57f1d3](https://gist.github.com/maedoc/cfd893b8fed9ee57f1d3)

I enjoy these kind of comparisons more for the Rosetta Stone aspect than
benchmarks, but I can't say they'd be useful for a real world project language
choice.

------
Redoubts
> That’s Python 3. Python 2 was about a second faster.

Of course it was.

