Hacker News new | ask | show | jobs
by spellcard199 2164 days ago
After trying Typed Clojure, liking it, but giving it up because of Clojure's GPL-incompatible license, I got interested in Kawa Scheme because it has some rudimentary form of type checking. For example, this produces warnings:

  (define (f1 x::String y::String) (x:concat y))
  (define (f2) (f1 3 3))

  ;; /dev/tty:3:19: warning - type integer is incompatible with required type java.lang.String
  ;; /dev/tty:3:21: warning - type integer is incompatible with required type java.lang.String
  ;; /dev/tty:3:15: warning - cannot convert literal (of type gnu.math.IntNum) to Type java.lang.String
  ;; /dev/tty:3:15: warning - cannot convert literal (of type gnu.math.IntNum) to Type java.lang.String
Unfortunately it does not support fully static type checking nor generics, otherwise it would be my favorite scripting language hands down.

As for type checking Elisp, Elsa[1] seems an interesting project and I hope it becomes a stable option. On the other hand I wonder if in future type checking could also come from gccemacs[2], since one of the "long-term improvements" may be "better compile time warning and errors relying on the propagation engine".

[1] https://github.com/emacs-elsa/Elsa [2] https://akrl.sdf.org/gccemacs.html

Edit: grammar.

2 comments

Typed Racket tends to work pretty well, and you can gradually add types to dynamic code. Probably the most mature type system of any Lisp.

And if you feel like types are too constraining for a part of your code, you can just leave them out. You get the best of both worlds!

I was really excited when I started using racket that I could switch to static typing when I wanted it. However after trying out contract's, I must say I'm quite a fan of them as an alternative. Sure, you lose out on static, compile time checking, but honestly, I haven't missed it. And it's _even more_ seamlessly integrated into un-contracted code. You can express more interesting things and complex relationships between parameters using the ->i contract than any type system I know of will allow. There's some limitations, but between it and unit testing, I've been having a blast.
Contracts incur absolutely massive performance penalties. Sparingly used, they can provide value though.

There's no reason why you can't have types and contracts though. I personally can't live without compile time guarantees.

I've tried racket/typed before and my knowledge or experience with it might be outdated, but sometimes I just could not get it to agree with my code. I fix one typing warning or thing it cannot infer and another would pop up. I fix the other, then a third pops up. I try to fix the third one, but realize I cannot and need to go back to the original state. When such things do not happen, it is very cool though. The code behing typed racket for me seems so mind bogglingly complex, I did not dare to investigate further. It is a language composed of macros, which use rackets macrology stuff, which is already more complex than other Schemes'. That language can be used to design any type system as far as I read about it.

With my typing trouble I should have come to the user list and asked, but I dId not, frustrated and thinking I was too stupid to get it ^^'

I did once at least see a question on the mailing list, where the answer was, that typed racket could not do it, as in infer types, so it might not be perfect yet, or perhaps it did improve since then.

I wish more Schemes could just copy the typed part of typed racket, using that macro language, as in theory they should be able to represent it, but I guess the devil is in the detail and slightly different workings of macro facilities.

Racket has a much more advanced macro system than scheme's traditional syntax-case.
Yes, it certainly has, but I think it's still based on that traditional syntax-case stuff. So in theory other Schemes could perhaps copy it, if anyone can get all the macrology behind it. Also in theory it should be possible to express all the advanced Racket stuff in syntax-case.

Do you think it is not possible to express these things in syntax-case? And if so, why?

Not always. Quite a lot of contracts can be statically checked. Unfortunately the only contract checker [1] I have experience with is too slow to be useful on source code that is itself large enough to be really useful.

And in C# at least contracts can be disabled for release builds so that the performance penalty is only inflicted on the developers.

[1] https://docs.microsoft.com/en-us/dotnet/framework/debug-trac...

If Racket had packages functionally equivalent to the ones on the JVM that I can't live without (Selenium, JGraphX, ...) I would start learning it right away. However sticking to the JVM and Kawa I get a vaguely similar typed/untyped experience except for the un-lispyness of Java. Usually when I write a script I make a new Java project that also pulls the dependencies and then embed Kawa (or jshell/ammonite jupyter server) for interactivity. Between the pom.xml and the code itself embedding Kawa (or jshell/ammonite) in a java program is like 10 lines at most.
Racket's graph library can do everything jgraphx can do, and much more elegantly. There's also this (and others) for selenium:

http://planet.racket-lang.org/package-source/untyped/seleniu...

> Racket's graph library can do everything jgraphx can do

What I need is to make a diagram from a file produced by diagrams.net without me writing the parser (JGraphX can already parse diagrams.net's xml), show me a window where I can select and adjust elements by hand, transform the diagram programmatically in a language where I have both type-checking and good completion for (eg) the selected objects, export back to diagrams.net's format. Occasionally I want to extend the already interactive window myself. I also evaluated Typed Racket before picking Kawa and the JVM, but JGraphX was just a more appropriate tool for this specific workflow.

> There's also this (and others) for selenium

I remember finding that, and I counted it as a subset of Selenium's functionality rather than equivalent.

I agree on the sentiment on Racket though, as for the language itself Java was a second choice for me. What eventually convinced me to invest in it was that I could always call what I had already written from other languages on the JVM (mainly Scala and Kawa, which also happen to have decent repls) without writing any glue code.

> because of Clojure's GPL-incompatible license

"GPL compatible: Optionally but not by default[3]"

- https://en.wikipedia.org/wiki/Eclipse_Public_License

In the page you linked it says the text you are quoting refers to the EPLv2, while Clojure is licensed under the EPLv1 [1]. It seems [2] they discussed changing Clojure's license to EPLv2, but decided not to.

[1] https://clojure.org/community/license [2] https://groups.google.com/forum/#!topic/clojure/uWAWm0xqrTI