News for hackers. Stuff that matters.
Re:Standard ML in 2020 by hajile on Sunday October 25, 2020 @08:00PM (#24891349)
StandardML really hits a nice sweet spot in language design.

The syntax is super-easy to learn (The BNF for the whole fits in a mere 2 pages[0]), but contains a lot of features in that small package. Rather than tacking on functional features (eg, Java with lambdas), these features have been carefully considered and streamlined and include bits like proper tail calls and currying.

You get nice bits like actually sound types (hindley-milner types as Milner was also one of the SML spec authors), generics (way better than typical interfaces), type inference that actually works, and modules (super-powerful encapsulation). Pattern matching in all it's awesomeness is also on display.

SML has an amazing concurrency story (CML is rather like golang channels, but better with better typing and a bit more flexibility) and compilers like PolyML or Mlton are very fast (once again, around the same as golang).

Despite this, the language doesn't have the academic flaws of its descendants like Haskell.

SML isn't a lazy language, so reasoning about performance is much easier than some other functional languages. SML doesn't pretend the world is a pure function. You are free to make functions that have side effects. While most primitives and data structures are immutable by default, they either have mutable variants (eg, vector and array) or can be used as if mutable with refs (something like typesafe pointers without all the reference/dereference bits).

[0] https://cse.buffalo.edu/~regan/cse305/MLBNF.pdf

Re:Standard ML in 2020 by jberryman on Sunday October 25, 2020 @10:52PM (#24892425)
> doesn't pretend the world is a pure function.

At a first approximation, Haskell pretends the world is a piece of state, not a pure function.

Re:Standard ML in 2020 by marcosdumay on Monday October 26, 2020 @11:02AM (#24896888)
To be a bit pedantic (because this thing is interesting), it's more like a context. In Haskell you'll say "this code must run on the real world".

Mercury literally pretends the world is a piece of state. You explicitly say "Here, run this code. The world before it runs is on variable `a`, place the world after it runs on variable `b`".

Re:Standard ML in 2020 by fanf2 on Monday October 26, 2020 @01:18PM (#24898560)
The classic paper Imperative Functional Programming https://www.microsoft.com/en-us/research/publication/imperat... introduced the IO monad and explained that its internals are based on passing around the state of the world. The monad hides the world and keeps it linear. The compiler (ghc) optimizes out the world so that it is implicit in the compiled program. I believe this is still the way that ghc works.
Re:Standard ML in 2020 by marcosdumay on Tuesday October 27, 2020 @12:03AM (#24904386)
Oh, yes, the stdlib does pretend the world is a piece of data. But it does a very good job on keeping this hidden from any developer, so this is more of a compiler design that does not leak into the language.
Re:Standard ML in 2020 by skissane on Sunday October 25, 2020 @08:06PM (#24891382)
> Despite this, the language doesn't have the academic flaws of its descendants like Haskell.

Can you elaborate on what those flaws are?

Re:Standard ML in 2020 by stutonk on Sunday October 25, 2020 @08:42PM (#24891630)
The profusion of Category-theoric abstractions and some of the more recent purely functional norms in Haskell are like the PhD-level version of `AbstractVisitorContextFactoryBuilder` which, aside from all the unnecessary cognitive load, lead to enormous dependency graphs of the npm variety.

Personally, I wonder if uniqueness types in languages like the sadly forgotten Clean (a close relative of Haskell) would have been better than the whole Monad/Arrow thing. All of that abstract theoretical stuff is certainly fascinating but it's never seemed worth all the bother to me.

On the other hand, in SML you get all the benefits of strong HM type inference/checking, immutability by default, etc, etc.. while also still being able to just `print` something or modify arrays in place. SML's type system isn't higher-order like Haskell's so its solution to the same problem Haskell solves with type classes isn't quite as elegant but otherwise SML is the C to Haskell's C++.

Re:Standard ML in 2020 by chriswarbo on Monday October 26, 2020 @04:59AM (#24894088)
I find there are two main problems with monads in Haskell:

- Monad is just an interface (with nice do-notation, to be sure), but it's elevated to an almost mythic status. This (a) causes Monad to be used in places which would be better without (e.g. we could be more generic, like using Applicative; or more concrete by sticking to IO or Maybe, etc.) and (b) puts off new comers to the language, thinking they need to learn category theory or whatever. For this reason, I try to avoid phrases like "the IO monad" or "the Maybe monad" unless I'm specifically talking about their monadic join operation (just like I wouldn't talk about "the List monad" when discussing, say, string splitting)

- They don't compose. Monad on its own is a nice little abstraction, but it forces a tradeoff between narrowing down the scope of effects (e.g. with specific types like 'Stdin a', 'Stdout a', 'InEnv a', 'GenRec a', 'WithClock a', 'Random a', etc.) and avoiding the complexity of plugging all of those together. The listed advantages of SML are essentially one end of this spectrum: avoiding the complexity by ignoring the scope of effects; similar to sticking with the 'IO a' type in Haskell (although even there, it's nice that Haskell lets us distinguish between pure functions and effectful actions).

Haskell has some standard solutions to composing narrowly-scoped effects, like mtl, but I find them to be a complicated workaround to a self-imposed problem, rather than anything elegant. I still hold out some hope that algebraic effect systems can avoid this tradeoff, but retro-fitting them into a language can bring back the complexity they're supposed to avoid (e.g. I've really enjoyed using Haskell's polysemy library, but it requires a bunch of boilerplate, restrictions on variable names and TemplateHaskell shenanigans to work nicely).

Re:Standard ML in 2020 by stutonk on Monday October 26, 2020 @09:48AM (#24896097)
Well said. This is exactly my gripe with Haskell monads. There are too many places where the hierarchy isn't uniform and there are a bunch of special monads like IO and List. It leads to the same ambiguous "is a" problem of complicated OO hierarchies and is one of the reasons they don't compose well.

The ironic thing is that these algabraic effect systems have a feel/control flow pattern that's quite similar to exception handling from the OO languages or interrupt handlers in low-level code.

It's much easier to just say "this piece of code is impure, it may do X, Y, and Z and if so then ..." than to try and shove everything ad-hoc into the abstract math tree. But then you lose the purity of your language and it's really awkward in a language whose primary concern is purity. That may be a reason why algebraic effects seem a bit more natural in OCaml.

Re:Standard ML in 2020 by nine_k on Sunday October 25, 2020 @10:51PM (#24892422)
I don't think there's a way to not use monads, because a ton of everyday things just work in a monadic way, things like lists, or statement sequences in presence of exceptions. I think it's wiser to admit and use these properties instead of ignoring them.

Ignoring maths that underlie computation when writing software is like ignoring math that underlies mechanics when building houses: for some time you can get by, but bigger houses will tend to constantly fall or stand a bit askew, and the first woodpecker to fly by would ruin the civilization, just as the saying goes.

Uniqueness types were a nice idea indeed. I suspect linear types (or their derivative in Rust) do a very similar thing: data are shared XOR mutable.

Re:Standard ML in 2020 by earthboundkid on Sunday October 25, 2020 @11:09PM (#24892520)
I recently read a blog post by someone who worked as a carpenter for a summer. He said he disliked the saying “measure twice, cut once” because actual carpenters avoid measuring as much as possible! For example, to make a staircase, you could try using simple trig to calculate the lengths of the board, angle of stair cut outs, step widths, etc. But that would all be wasted effort because you can’t actually measure and cut wood to sufficient precision. Instead, you need to just get rough measurements and then use various “cheats” so the measurements don’t matter, like using a jig to cut the parallel boards at exactly the same length (whatever it turns out to be).

Analogy to monads is this: yes, there are mathematical formalisms that can describe complex systems. Everything can be described by math! That’s literally its one job. But will the formalisms actually help you when the job you’re doing has insufficient achievable precision (eg finding market fit for a website)?

Re:Standard ML in 2020 by nine_k on Sunday October 25, 2020 @11:53PM (#24892694)
I think that the metaphor leaks badly. Finding market fit is like deciding on the general shape of the staircase. Execution of whatever design still needs the stairway to be strong and reliable all the same.

Writing code is a much more precise activity that cutting wood. Using "cheats" can get you somewhere, but due to the precise nature of the machine logic, the contraption is guaranteed to bend and break where it does not precisely fit, and shaving off the offending 1/8" is usually not easy, even if possible.

Re:Standard ML in 2020 by tikhonj on Monday October 26, 2020 @01:42AM (#24893135)
> But will the formalisms actually help you when the job you’re doing has insufficient achievable precision (eg finding market fit for a website)?

In my experience, this is exactly the problem Haskell's core abstractions—monads among them—help with!

What do you need when you're trying to find product-market fit? Fast iteration. What do Haskell's type system and effect tracking (ie monads) help with? Making changes to your code quickly and with confidence.

Haskell provides simple mathematically inspired tools that:

1. Make clean, well-factored code the path of least resistance.

2. Provide high-level, reusable libraries that keep your code expressive and easy to read at a glance despite the static types and effect tracking.

3. Give you guardrails to change your code in systematic ways that you know will not break the logic in a wide range of ways.

If I had a problem where I'd need to go through dozens of iterations before finding a good solution—and if libraries were not a consideration—I would choose Haskell over, say, Python any day. And I say this as someone who writes a lot of Python professionally these days. (Curse library availability!)

Honestly, Haskell has a reputation of providing really complicated tools that make your code really safe—and I think that's totally backwards. Haskell isn't safe in the sense that you would want for, say, aeronautical applications; Haskell programs can go wrong in a lot of ways that you can't prevent without extensive testing or formal verification and, in practice, Haskell isn't substantially easier to formally verify than other languages. And, on the flipside, Haskell's abstractions really aren't complicated, they're just different (and abstract). Monads aren't interesting because they do a lot; they're interesting because they only do a pretty small amount in a way that captures repeating patterns across a really wide range of types that we work with all the time (from promises to lists to nullable values).

Instead, what Haskell does is provide simple tools that do a "pretty good" job of catching common errors, the kind of bugs that waste a lot of testing and debugging time in run-of-the-mill Python codebases. This makes iteration faster rather than slower because you get feedback on whole classes of bugs immediately from your code, without needing to catch the bug in your tests or spot the bug in production.

Re:Standard ML in 2020 by zwaps on Monday October 26, 2020 @04:13AM (#24893848)
As a bit of an aside, it's interesting that the CS (Haskell, mainly) descriptions of a Monad are much more complicated than the math.

Knowing a little bit of maths, but not much category theory, the wiki entry for Monads(Category Theory) is pretty clear. First sentence: A Monad is an endofunctor (a functor mapping a category to itself), together with two natural transformations required to fulfill certain coherence conditions. Easy.

Knowing a bit of programming, but not much Haskell, reading the entry for Monad (functional programming) or any blog post titled "A Monad is like a ...", it almost seems as if the author is more confused about what a Monad is than me. The first sentences of the Wikipedia article for example are a word-salad. With dressing.

From an outsider's perspective, it's almost as if a monad in functional programming is not a 1:1 translation of the straightforward definition of category theory, leading to an overall sense of confusion.

Re:Standard ML in 2020 by Twisol on Monday October 26, 2020 @07:09AM (#24894849)
> Easy.

The formal definitions are straightforward enough, but the definitions alone don't really motivate themselves. A lot of mathematical maturity is about recognizing that a good definition gives a lot more than is immediately apparent. Someone without that experience will want to fully understand the definition, and fairly so -- but a plain reading defies that understanding. That is objectively frustrating.

> As a bit of an aside, it's interesting that the CS (Haskell, mainly) descriptions of a Monad are much more complicated than the math.

I actually do agree with this, though. I feel like monads are much simpler when presented via "join" (aka "flatten") rather than "bind"; and likewise with applicative functors via monoidal product (which I call "par") rather than "ap". "bind" and "ap" are really compounds of "join" and "par" with the underlying functorial "map". That makes them syntactically convenient, but pedagogically they're a bit of a nightmare. It's a lot easier to think about a structural change than applying some arbitrary computation.

Let's assume the reader knows abut "map". Examples abound; it's really not hard to find a huge number of functors in the wild, even in imperative programs. In short, "map" lets us take one value to another, within some context.

Applicative functors let us take two values, `f a` and `f b`, and produce a single `f (a, b)`. In other words, if we have two values in separate contexts (of the same kind), we can merge them together if the context is applicative.

Monads let us take a value `f (f a)` and produce an `f a`. In other words, if we have a value in a context in a context, we can merge the two contexts together.

Applicative "ap", `f (a -> b) -> f a -> f b`, is "par" followed by "map". We merge `(f (a -> b), f a)` to get `f (a -> b, a)`, then map over the pair and apply the function to its argument.

Monadic "bind", `(a -> f b) -> f a -> f b`, is "map" followed by "flatten". We map the given function over `f a` to get an `f (f b)`, then flatten to get our final `f b`.

It's a lot easier to think about these things when you don't have a higher-order function argument being thrown around.

Re:Standard ML in 2020 by stutonk on Monday October 26, 2020 @09:57AM (#24896191)
The problem isn't with the mathematical concept of monads, it's that Monad is a typeclass in a hierarchy along with other totally abstract category theoric classes introduced at different stages and people use them with varying levels of knowledge and ignorance so things are placed arbitrarily and there are a bunch of ambiguities. Just look at this [0] mess. Is that really what we want?

[0] https://wiki.haskell.org/wikiupload/d/df/Typeclassopedia-dia...

Re:Standard ML in 2020 by hajile on Sunday October 25, 2020 @09:00PM (#24891766)
Are you familiar with unsafe IO?

It's used pervasively in low-level code because the idealism of monads just doesn't cut it. In my opinion, this proves that the pragmatism of side effects is a necessary evil for actually getting things done in a performant way.

Lazy evaluation has the same kind of issues. Most humans don't think that way, so performance suffers. This may be a universal problem as in my experience, Haskell doesn't have good tooling to help with this issue.

Always immutable is another large issue. Yes, there's a ton of safety in immutability and it's the right tool for MOST code. Compilers aren't prefect and there seem to be an endless stream of situations where the compiler can't figure out if it is safe to mutate "immutable" data to gain performance. For the foreseeable future, the ability to mutate can have huge performance dividends.

Finally, Haskell and it's libraries are prone to rather academic programming styles and techniques. These are amazing and beautiful. They also can be hard to grep even if you know the math. When you consider that the overwhelming majority of programmers don't know the math, it seems plain that these constructs are a detriment to pragmatic, non-academic usage.

Re:Standard ML in 2020 by elihu on Sunday October 25, 2020 @10:30PM (#24892325)
> Are you familiar with unsafe IO?

> It's used pervasively in low-level code because the idealism of monads just doesn't cut it. In my opinion, this proves that the pragmatism of side effects is a necessary evil for actually getting things done in a performant way.

It seems like you aren't very familiar with the ways Haskell programmers deal with side effects and mutation. UnsafePerformIo is sometimes needed, and there are a few common idiomatic ways to use it, but there are usually better options. What at first looks like an impenetrable wall between the IO monad and pure code is actually surprisingly permeable, just not (usually) in ways that violate expected semantics. For instance, you can read a file into a string in the IO monad and pass the string into pure code to process it. The string is lazy, so the pure code actually triggers the file to be read as it's consumed.

Another escape hatch is the ST Monad. It allows you to run imperative computations (i.e. use mutable variables and arrays) within pure code. Since the ST computations are deterministic, they don't violate any important guarantees about pure code. You can't read and write files from the ST Monad, but if you want to do array-based quicksort or something similar it's available.

Some aspects of Haskell are hard to work with. You're right that laziness introduced some performance issues that can be tedious to fix, and some of the libraries are hard to use. However, it's a perfectly reasonable tool for many general-purpose programming applications. It's not a replacement for C, but you could say the same thing about C# or Java or any other language with a garbage collector.

(edit: fixed grammar typo)

Re:Standard ML in 2020 by EE84M3i on Monday October 26, 2020 @01:40AM (#24893122)
Wait, I thought that lazy io (e.g. getting a lazy string back from "reading" a file, which triggers subsequent reads when you access it) was widely considered bad and a mistake.
Re:Standard ML in 2020 by dllthomas on Monday October 26, 2020 @03:24AM (#24893602)
This depends very much on the context. Using something like `readFile` without carefully exhausting it is absolutely a mistake in a long lived application or a high volume web server, and in a setting like that reaching for that kind of an interface and hoping future modifications preserve the "reads to exhaustion in reasonable time" is questionable at best.

On the other hand, in a program that handles a small number of files and doesn't live long after file access anyway (say a small script to do grab a couple things, crunch a few numbers, and throw the result at pandoc), there's nothing wrong with lazy IO and it can be quite convenient.

Re:Standard ML in 2020 by chriswarbo on Monday October 26, 2020 @10:21AM (#24896424)
Lazy IO is really useful for commands which stream data over stdio, e.g. this is a really useful template, where 'go' is a pure function for producing a stdout string from a stdin string:

    {-# LANGUAGE OverloadedStrings #-}
    import qualified Data.ByteString.Lazy.Char8 as BS

    main = BS.interact go

    go :: BS.ByteString -> BS.ByteString
    go input = -- Generate output here
If you don't mind Haskell's default String implementation, then it's just:

    main = interact go

    go :: String -> String
    go input = -- Generate output here
Re:Standard ML in 2020 by elihu on Monday October 26, 2020 @01:58AM (#24893194)
Yes, that's true. I thought about mentioning that in my comment, but it seemed like a bit of a digression and it was already getting a bit wordy.

Anyways, the problem is that you might open a file, read it into a string, close the file, and then pass the string into some pure function. The problem is that the file was closed before it was lazily read, and so the string contents don't get populated correctly; you get the empty string instead, or whatever was lazily read before the file was closed.

That was a design oversight from the early days. If you know about it, it's pretty easy to work around it in simple applications. There are some more modern libraries for doing file IO in a safer way, but I haven't used them and don't really know what the details are.

Re:Standard ML in 2020 by darksaints on Sunday October 25, 2020 @09:29PM (#24891936)
One of my favorite rants on the practicality of Haskell vs ML.

https://existentialtype.wordpress.com/2011/05/01/of-course-m...

Re:Standard ML in 2020 by dan-robertson on Sunday October 25, 2020 @08:11PM (#24891416)
Reasoning about haskell performance is hard because it is a lazy language and the compiler pulls a lot of tricks. In SML, code is executed in some sense roughly in the order it is written whereas in haskell it is very hard to know when something will be executed.
Re:Standard ML in 2020 by djhaskin987 on Sunday October 25, 2020 @08:34PM (#24891563)
In Haskell's defense, they meant to do that.
Re:Standard ML in 2020 by nicoburns on Sunday October 25, 2020 @10:01PM (#24892136)
How does it compare to OCaml?
Re:Standard ML in 2020 by wtetzner on Monday October 26, 2020 @09:04AM (#24895691)
They're very similar. Some people prefer Standard ML's syntax, though I actually prefer OCaml's (most likely just a result of me learning OCaml first).

The module systems have some small differences, but are very similar (I believe OCaml's was inspired by SML's).

Standard ML is also standardized (hence the name), and there are multiple implementations, whereas OCaml is basically defined by its single implementation.

But OCaml does have a larger ecosystem, Opam, more features (first-class modules, polymorphic variants, etc.).

Re:Standard ML in 2020 by Davidbrcz on Monday October 26, 2020 @05:57AM (#24894414)
OCaml's design was influenced by Standard ML
Re:Standard ML in 2020 by eatonphil on Sunday October 25, 2020 @08:01PM (#24891358)
Have you used CML for any real projects? Very curious to see. I've always used Poly/ML when I wanted parallelism.
Re:Standard ML in 2020 by bjoli on Monday October 26, 2020 @05:43AM (#24894349)
Of you are a lisp person guile has a parallel CML implementation called guile-fibers.

I used it, just for fun, in a static site generator. That was fun and worked great.

Re:Standard ML in 2020 by fouric on Monday October 26, 2020 @08:33AM (#24895429)
Why should I use SML over Rust or Lisp?

Rust's performance is almost certainly much better, with a larger library ecosystem.

(Common) Lisp has macros, which allow me to implement pattern-matching; an even simpler BNF (as short as one line, depending on how you define it); dynamic typing, which makes generics unnecessary, and for all the hate that it receives is regularly deployed to production systems on large scales; tooling that is almost certainly better than SML's; and a condition system, which beats any other type of error-handling system, bar none (meaning that I can make my programs more robust than yours).

Re:Standard ML in 2020 by hajile on Monday October 26, 2020 @09:31AM (#24895948)
Those are both great languages.

Rust is very much a ml variant. It's all the things you claim and probably more. It's also at least an order of magnitude more complex. If you know rust, you'll probably find SML super easy to learn and refreshingly easy to code.

People gravitating toward SML likely want a few things: easy to learn, simple infix syntax with functional support, compile time type static type checks, multithreaded, very fast without a drastic recode.

Common lisp libraries are better, but not drastically so (well, I've never had 5 grand to throw at lisp works, so I can't comment there). CL is more complex to learn (must people can probably learn the entire SML language in the time it takes to master the loop macro). Macros are powerful, but mean that even if you can find a lisp dev, it'll take a long time for them to learn your custom variant of the language.

CL offers unofficial threading, but last I checked it was much harder than the SML solutions. CL is pretty fast out of the box, but if you ever need peak performance, the code changes a lot and can become very finicky (though CL makes seamlessly hiding those bits easier than most languages). Even at it's most optimized, I don't know that it can match milton in performance or memory usage.

Dynamic vs static typing is a battle that's all but over. When you have devs coming and going on a team, type make transitions easier. Loads of dynamic languages have started adding them and even CL sort of does.

CL has loads of interesting features from well known ones like macros/reader macros or metaobject protocol to less known ones like optional dynamic scoping.

I'm just saying why I enjoy SML (not trying to argue that it's the end all, be all of programming). There are other great languages too. Do what you love.

Re:Standard ML in 2020 by fouric on Monday October 26, 2020 @10:10PM (#24903878)
Thank you for your actually informed, well-reasoned, and thoughtful answer!
Re:Standard ML in 2020 by johnnycerberus on Monday October 26, 2020 @09:10AM (#24895748)
SML over lisp:

* Doesn't have macros, which in my 16 years of experience is a plus, macros pollute, should at most be an implementation detail

* Has types

* Doesn't have parantheses and the annoying prefix notation

* Your knowledge of SML can be translated easily to OCaml, Java, Scala, which are more or less part of the same family

SML over Rust:

* I don't have to reason about lifetimes, I'm not in a constrained environment

* TCO (tail call optimization)

* At its core, Rust is still an imperative language, it was influenced by ML but not that much as many believe

SML over Scala:

* It doesn't suffer of Haskellism and Extreme Bipolarity (oop/fp) and gets the job done.

Re:Standard ML in 2020 by fouric on Monday October 26, 2020 @10:07PM (#24903865)
> * Doesn't have macros

> * Has types

Your words betray your ignorance. Common Lisp has a type system. Have you ever written it? Do you actually know anything about it? Moreover, macros are a plus - you clearly have not actually used Lisp macros, which are categorically different than macros in other languages.

> * Doesn't have parantheses and the annoying prefix notation

Spelling mistake. Additionally, the parenthesized syntax is a choice, and one that you get used to quickly. Subjective, and therefore not valid as one of the items you listed.

> * Your knowledge of SML can be translated easily to OCaml, Java, Scala, which are more or less part of the same family

Meanwhile, knowledge of Common Lisp transfers to almost every dynamically-typed language ever made, and a good many static ones - including Java and Scala - because Lisp influenced all of those languages. That is, Lisp knowledge transfers to far more languages than SML knowledge does.

Re:Standard ML in 2020 by johnnycerberus on Tuesday October 27, 2020 @08:22AM (#24906698)
Ok, I don't want to start a language war again, when I say types, I mean the modern reference to the word that it has a static type system. Indeed, Lisp languages are strongly typed but I'm sorry, in the real world it doesn't help me, I need types, statically checked types.

I don't know if Lisp, the language, influenced Java and Scala so much, it was more about its runtime, the garbage collector, etc. The only thing that I liked about Lisp is the composabiltiy, and coupled with objects from Simula created my favorite industrial languages, Java and TypeScript. I'm passionate about parsers, compilers and transformers and this is why I have a fost spot for SML, OCaml. I simply dislike Lisp, interesting language but not for me.

Re:Standard ML in 2020 by fouric on Tuesday October 27, 2020 @10:47PM (#24914510)
> when I say types, I mean the modern reference to the word that it has a static type system

Can you show me a significant body of literature or a whole community that uses "types" to mean "a strong type system"? Because I've never heard that aliasing done before.

> I don't know if Lisp, the language, influenced Java and Scala so much, it was more about its runtime, the garbage collector, etc.

Lisp pioneered lambdas and first-class functions, in addition to garbage collection, all of which were adopted by Scala and Java later.

> I simply dislike Lisp, interesting language but not for me.

I understand! I have things that I like and dislike, too. However, it's extremely frustrating when you ask for an analytical comparison between several languages, and some random person lacking knowledge on at least one of the languages (I suspect you don't know Rust either) comes in and, instead of actually providing relevant information, gives fallacies and opinions.

Re:Standard ML in 2020 by johnnycerberus on Monday November 02, 2020 @08:56AM (#24968135)
All languages associate types to expressions. But, all dynamic languages can have only one type for expressions. Indeed, dynamic languages associate types to values all the time but there is no static distinction. What people from dynamic languages are calling "types" are in fact runtime tags. What makes Lisp strongly typed are those runtime tags that prevent implicit conversions at runtime, something that JavaScript lacks.

In Common Lisp objects are values, so runtime tags are attached to data objects => which are actually values => which are stored in variables => which are not typed.

You can make it optionally typed at compile time to help the compiler but that means to annotate your code with 'type' keyword and it's verbose. The compiler does not enforce it.

Re:Standard ML in 2020 by fouric on Thursday November 05, 2020 @09:03AM (#24998262)
Again, I've never seen this distinction made before. Please show me a body of literature that claims that dynamically typed languages do not have a type system - your claims on their own do not convince me.
Re:Standard ML in 2020 by Exolon on Monday October 26, 2020 @10:53PM (#24904078)
> Your words betray your ignorance. Common Lisp has a type system. Have you ever written it? Do you actually know anything about it? Moreover, macros are a plus - you clearly have not actually used Lisp macros, [...]

This isn't really okay. It's fine if you disagree, but I don't get why such aggression is needed.

Re:Standard ML in 2020 by fouric on Tuesday October 27, 2020 @11:00PM (#24914599)
I specifically avoided insulting them. "Ignorance" is not an insult; it's a description of your knowledge on a topic, and if it isn't the right word to describe telling such a blatant and fundamental misunderstanding, then what is?