Mixing imperative and functional paradigms is a really interesting point in the design space, and has gotten me (begrudgingly) interested in statically-typed languages. I noticed writing Common Lisp that I preferred to write code in a functional style, but occasionally I'd want to bury an imperative update somewhere. Putting a comment saying: "this should be the only use of SETF in the whole algorithm" isn't the most satisfying solution.<p>Languages like Common Lisp and Dylan (and SML) have mixed imperative and functional paradigms in a non-controlled way for awhile, but there is some interesting work going on about how to do it in a more controlled way. Much of this work involves limiting aliasing and mutability, or expressing imperative features an effect system, or some combination of the two.<p>Rust is probably the most mainstream example of the former, but Mezzo is another language exploring this area: <a href="http://protz.github.io/mezzo" rel="nofollow">http://protz.github.io/mezzo</a>. The basic idea is that if you've got the unique reference to an object, or a tree of objects, you can modify it without worrying about how it will affect the rest of the program. Koka is a language that focuses more on the latter, expressing the imperative characteristics of a function through an effect system: <a href="http://arxiv.org/pdf/1406.2061.pdf" rel="nofollow">http://arxiv.org/pdf/1406.2061.pdf</a> (section 2.1). The basic idea here is similar to Java's exception specifications. If the set of objects potentially modified by a function must be part of its type, then you can use the type system to keep you from modifying an object, or calling a function that does, in a context where the rest of the program doesn't expect that object to be modified.
Something that <i>bugs</i> me in Haskell, and which Mars inherits as it is mostly the same semantics - you've taken the effort to create a good type system with optional types and type checking, only to decide to not actually use them for some common operations you're performing in the language (namely, head/tail).<p><pre><code> ?> Nil.head
Runtime Error: List instance has no field 'head'
</code></pre>
Such runtime errors could easily be avoided by making head/tail return Maybe, and using Nothing in the case of Nil. This hardly complicates code, but it provides the correct behavior, particularly when it comes to doing "records" properly. The Mars docs give an example of how I consider copying Haskell's semantics directly without improving them leads to flawed code.<p><pre><code> type Foo:
X(u :: Num, v :: Num)
Y(v :: Num)
</code></pre>
There's nothing wrong with `v` here, as it is total, but you can easily introduce a runtime error by using `u` incorrectly.<p><pre><code> ?> x = Y(1)
?> x.u
Runtime Error: Foo instance has no field 'u'
</code></pre>
This is why using records in combination with sum types in Haskell is widely considered a bad idea. It's a misfeature as far as I'm concerned. If given the chance to redo Haskell's awful record system, I'd fix it.<p>The problem can be trivially avoided by making `u` return `Maybe Num` in this example, where it returns Nothing for Y and `Just 1` for X. Ideally, the compiler should check if field names are total over the constructors - if not, it should automatically return an optional type. If the fields are total there's no need. I doubt there would be any noticeable performance cost to moving the error to compile time - particularly because you don't actually need to use it in internal implementations of map/fold and such - you could have an internal function which mimics the current behavior, but don't expose it from the module.
Mm. The native library looks difficult to use and primitive (<a href="http://bazaar.launchpad.net/~mgiuca/mars/trunk/view/head:/lib/native.mar" rel="nofollow">http://bazaar.launchpad.net/~mgiuca/mars/trunk/view/head:/li...</a>) making this interesting in a theoretical sense, but not really in any practical sense (to me, at least).
This looks really good. What prevents them from committing this language to the public? Their About ("we don't recommend you write real software with it") is really off-putting for me because I can think of a fantastic use case for this in my current line of work but what does this even mean? I should expect compiler bugs? Conflicted.
Calling functional programming declarative seems like a bit of a stretch to me. I understand the reasoning. Still, when I read the headline I was imagining something pretty different.<p>---<p>The language looks pretty good. I think for most programmers some kind of vanilla ML would work well.
I hate the double colon, it's so unpythonic.<p>I believe the 'as' keyword would be more smooth:<p><pre><code> def hello(name as String) as String:
var greeting as String
greeting = 'Hello '+name
return greeting</code></pre>
Great. I've thought about making a language with similar concepts, but I just can't get myself to make a proper stab at it. Not motivated enough. Perhaps scared of failing. I don't know.