3 ms·
I like the idea, but please no "async/await". In a higher level language green threads like Go has are the correct answer IMO (and I'm not a Go fan, but I feel
by nu11ptr 3y ago
I like the idea, but please no "async/await". In a higher level language green threads like Go has are the correct answer IMO (and I'm not a Go fan, but I feel they got this part right).
Gradual typing is interesting, but I wonder if necessary. Static typing doesn't have to feel like a burden and could make it hard to reason about performance. I think more type inference would be better than gradually typed (like OCaml/ML).
- jerf 3y ago"Gradual typing is interesting, but I wonder if necessary." Open question: Are there any languages that can be used in a (decent [1]) REPL, that are strongly typed, but do not have Hindley–Milner-based type inference? We have multiple concrete proofs that you can have a REPL with Hindley-Milner inference, but I'm curious if this is perhaps a concession to the difficulty of a strongly-typed REPL without a deeply inferable type system. But it's just an idle musing I'm throwing out to see the response to. [1]: That is, for example, multiple people have put a Go REPL together, but anyone who has used a "real" REPL from the likes of Lisp, Haskell, Erlang, O'Caml, Python, etc., will not find it a "decent" REPL, as Go just can't have one for various reasons.
- naasking 3y agoScala has a REPL. It uses HM, but has limitations on type inference due to subtyping.
- munificent 3y agoI'm not aware of any technical reasons why a given language would profoundly struggle to have a good REPL. I think it's mostly a matter of culture where REPLs aren't a priority in some language ecosystems because programmers there don't generally work that way.
- jerf 3y agoI'm not immediately aware of one either which is why I asked. HM does have its advantages but static languages are generally pretty clear on the type of an expression without annotations and just giving a variable the type of what it is set to achieves most of what you're looking for. It just occurred to me I couldn't name an instance of a static language without HM that does that, though. (At least I'm assuming LISP REPLs generally operate dynamically.)
- munificent 3y agoOne thing that does make it kind of weird is that a lot of statically typed languages that aren't from the ML family have a grammar top level that isn't imperative. In C#, Java, Dart, etc. The top level of a source file is purely declarative. That can make a REPL sort of semantically weird. Do you allow variable declarations? If so, are they local or global? Do you allow class declarations in them? If so, can they access previous declarations? All of that's easier in a dynamically typed language where the top level of a program is more or less just regular imperative code. It's not insurmountable though, because you can be a little hand-wavey about semantics in a REPL if needed.
- mplanchard 3y agoPersonally I love explicit coroutines for their flexibility. It's great to be able to multiplex a bunch of IO bound operations on a single thread, defining some in chains and other to execute in parallel. It's great to be able to easily decide when I want to wait for them all to finish, to do something like `select`, or to spin them off into the background. Rust's ownership occasionally makes this a bit more of a challenge than I would like it to be, but I certainly wouldn't trade the ability for a more "convenient" syntax.
- rkangel 3y agoElixir and its Task module (https://hexdocs.pm/elixir/1.12/Task.html https://hexdocs.pm/elixir/1.12/Task.html) is the best of both worlds here. The fundamental concurrency system is green threads (similar to Go), which makes for a fantastic programming model where you spend your time writing linear blocking code, while actually having full parallelism. This is achieved both with the VM and the abstractions built on top like GenServers. The Task module is a convenience that allows you to do "await" type work when that makes sense - because (as you describe) sometimes it does.