HackerTrans
TopNewTrendsCommentsPastAskShowJobs

lkitching

no profile record

comments

lkitching
·पिछला वर्ष·discuss
I've already shown that type hints do not constitute type checking:

  (defn f [^String s] (.length s))
  (f 3)
is a valid Clojure program that fails at runtime with a cast error.

  class X { public static int f(String s) { return s.length(); } }
  X.f(3)
is not a valid Java program at all. Clojure compilation generates bytecode to dispatch dynamically and all but the most basic checks are handled at runtime by the JVM. This is fundamentally different to the static type checking that languages like Java and Scala do. It's not that Clojure is hiding something from Java, but rather that it isn't doing the considerable amount of effort the Java type checker does to analyse the program before execution. This is by design - Clojure has deliberately avoided adding a static type system in favour of things like spec.
lkitching
·पिछला वर्ष·discuss
Of course Clojure has to ultimately be compiled into a native format for the host platform, bytecode in the case of the JVM implementation, but that doesn't require type checking in the same way Java does.

Clojure functions are compiled into implementations of clojure.lang.IFn - you can see from https://clojure.github.io/clojure/javadoc/clojure/lang/IFn.h... that this interface simply has a number of overloads of an invoke method taking variable numbers of Object parameters. Since all values can be converted to Object, either directly for reference types or via a boxing conversion, no type checking is required to dispatch a call. With a form like

  (some-fn 1, "abc", (Object.))
the some-fn symbol is resolved in the current context (to a Var for functions defined with defn), the result is cast (not checked!) to an instance of IFn and the call to the method with required arity is bound. This can go wrong in multiple ways: the some-fn symbol cannot be resolved, the bound object doesn't implement IFn, the bound IFn doesn't support the number of supplied arguments, the arguments are not of the expected type. Clojure doesn't check any of these, whereas the corresponding Java code would.

Protocol methods just get compiled into an implementation of IFn which searches for the implementation to dispatch to based on the runtime type of the first argument, so it doesn't introduce static type checking in any way.
lkitching
·पिछला वर्ष·discuss
Protocols do not work like Java interfaces or classes. Their methods are compiled into regular functions which lookup the implementation to use at runtime based on the runtime type of the receiver. Compilation will check for the named function but doesn't do any further checking. Given the following protocol and implementation:

  (defprotocol P
    (method [this ^Integer i]))

  (extend-protocol P
    String
    (method [s i] (.substring s i)))
both (method "test" "call") and (method 1 2) will be accepted by the compilation phase but will fail at runtime.

Of course there's no requirement for Clojure code to be AOT compiled anyway so in that case any name errors will still only be caught at runtime when the compilation happens.

Type hinted bindings are only converted into a cast and are not checked at compilation time either e.g.

  (defn hinted [^String s] (.length s))
  (hinted 3)
will be accepted but fail at runtime.

deftype is only used for Java interop an is also not a form of type checking. The methods will be compiled into Java classes and interfaces, but the implementations defer to regular Clojure functions which are not type checked. You can only make use of the type information by referencing the compiled class files in Java or another statically typed language, using them from Clojure will not perform type checking.
lkitching
·पिछला वर्ष·discuss
Neither defprotocol nor deftype introduce static typing into Clojure. Errors in their usage are not checked statically and are only discovered at runtime.
lkitching
·2 वर्ष पहले·discuss
That just means the semantics of the language are defined by whatever the default implementation does. It's a big stretch to conclude that means Rust 'was' OCaml in some sense when the compiler was written with it. Especially now the Rust compiler is written in Rust itself.
lkitching
·2 वर्ष पहले·discuss
I'm not convinced the implementation language of the compiler counts as a feature of the Rust language. If the argument is that Rust wouldn't have been invented without the original author wanting a 'systems OCaml' then fine. But it's possible Rust would still look similar to how it does now in a counterfactual world where the original inspiration was Haskell rather than OCaml, but removing the Haskell influence from Rust as it is now would result in something quite different.
lkitching
·2 वर्ष पहले·discuss
Which OCaml features exist in Rust but not Haskell? The trait system looks very similar to Haskell typeclasses, but I'm not aware of any novel OCaml influence on the language.
lkitching
·2 वर्ष पहले·discuss
The way in which monads are monoids isn't really helpful for understanding them for progamming.