7 ms·
Mars: a hybrid imperative-declarative higher-order language
- tormeh 12y agoGreat. 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.
- k__ 12y agoJust try it. At university, many of my fellow students wrote their own LISP, to get started with it. I wrote a few DSLs in XML, which is rather easy too. With this knowledge it is easier to learn new languages :)
- reeses 12y agoThe concepts are the important part. You can get a long way with a nasty interpreter to see if your concepts play out. :-) If it's a "deep" concept, I'd pick a simple representation that I can implement without much cognitive overhead (a basic Lispish or Forthish stacks-and-registers syntax is usually something I can spin up in a few minutes) and then start layering my concepts in. Some of the things you think will be awesome will end up just being wrong or inefficient, but you'll cut the loop down really quickly. It makes it really easy to compare your hypotheses. If you want to factor them into a more conventional syntax model (c, python, haskell, etc.) you can always learn that along the way. In fact, if you want to get really simple about it, write the code you would want to write and hand interpret it. You can get really far with simple pre-processors written in whatever text or AST manipulation environment with which you feel comfortable. (I'm notorious for being lazy and writing 50-pass compilers, just writing 10 to 200 line features and chaining them, all in a ghetto RPN.)
- mattgreenrocks 12y agoYou won't fail. I worked through the How to Write Your Own Freaking Awesome Programming Language ebook. I made some toy languages and put them on Github (https://github.com/mattgreen/learning-language-design/tree/master/gamma https://github.com/mattgreen/learning-language-design/tree/m...). It's so much fun!
- sigzero 12y agoLooks a lot like Python.
- deleted 12y ago[deleted]
- shadowmint 12y agoMm. The native library looks difficult to use and primitive (http://bazaar.launchpad.net/~mgiuca/mars/trunk/view/head:/lib/native.mar http://bazaar.launchpad.net/~mgiuca/mars/trunk/view/head:/li...) making this interesting in a theoretical sense, but not really in any practical sense (to me, at least).
- untothebreach 12y agoTo be fair, they admit it isn't usable for "real" software: About Mars ... Mars is an experiment, not a full-featured programming language. You can use it for playing with the boundaries between imperative and declarative programming, but we don't recommend you write real software with it.
- Thiz 12y agoI hate the double colon, it's so unpythonic. I believe the 'as' keyword would be more smooth: def hello(name as String) as String: var greeting as String greeting = 'Hello '+name return greeting
- jimktrains2 12y agoThis isn't Python. :: is common in many languages, especially functional ones (which aren't just using it as a scope resolution operator).
- pdabbadabba 12y agoNot sure what place "unpythonic" has as a criticism of a language other than Python. (As a matter of personal taste, I too prefer "as." Probably because I do most of my work in Python. But who cares?)
- rilut 12y agoReminds me of Cobra http://cobra-language.com/ http://cobra-language.com/
- peaton 12y agoAnd boo http://boo.codehaus.org http://boo.codehaus.org
- chton 12y agoEven that isn't smooth enough for me. Why is the 'var as' still there? it's superfluous, ofcourse we're declaring a variable, there's nothing else that makes sense at that point. Why not: def hello(String name) as String: String greeting greeting = 'Hello '+name return greeting which is how a lot of other languages are doing it. On the other hand, maybe I just don't like writing syntax that doesn't add any meaning :p
- mborch 12y agoWhile definitely superfluous, it arguably makes it easier to read and scan.
- rayiner 12y agoMixing 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. 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. Rust is probably the most mainstream example of the former, but Mezzo is another language exploring this area: http://protz.github.io/mezzo http://protz.github.io/mezzo. 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: http://arxiv.org/pdf/1406.2061.pdf http://arxiv.org/pdf/1406.2061.pdf (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.
- tel 12y agoThen of course there are monads which aren't too inappropriately described as the pattern of expressing controlled imperative features in the type system.
- tomp 12y agoThe difference between monads and the kind of effects system used in Koka is that in Koka, effects are inferred, whereas with monads, they have to be stated up-front. Koka also allows you to mix effects, e.g. a function can be `<io, st<h>, ndet>`, meaning that it reads/writes files, reads/writes memory in heap `h`, and is non-deterministic. Effect variables are akin to higher-kinded polymorphism, so that e.g. `map` can be polymorphic in the effect of the mapping function.
- acron0 12y agoThis 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.
- scott_s 12y agoWhat do you mean "committing to the public"? The source code is available, and it's GPL 3.0. And I think their caveat is clear: they consider the language a research project at the moment, and not only do they not have enough confidence in the reliability for real-world use, they probably don't want the implied responsibility.
- mgiuca 12y ago(I am the creator of Mars). Yeah, it basically means a few things: 1. This is a research project. It doesn't have any support and if there are future versions, they might change the language in backwards-incompatible ways (but I will generally follow proper practices and bump the major version number in that case). 2. I am reaching the end of my PhD and I don't anticipate spending a lot of, if any, time working on Mars. 3. The language as it currently stands isn't very palatable to use for real-world software, basically because it is missing a lot of features. I've compiled a brief list here: http://mars-lang.appspot.com/docs/faq.html#what-features-is-mars-missing-such-that-it-isn-t-a-real-language http://mars-lang.appspot.com/docs/faq.html#what-features-is-... I think if you were to play with it a bit, you would start to realise how primitive the language actually is ;) Sorry to disappoint you. Having said that, the source code is fully available and GPL, so there is no technical or legal reason why you can't use it in any way you like.
- sparkie 12y agoSomething that bugs 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). ?> Nil.head Runtime Error: List instance has no field 'head' 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. type Foo: X(u :: Num, v :: Num) Y(v :: Num) There's nothing wrong with `v` here, as it is total, but you can easily introduce a runtime error by using `u` incorrectly. ?> x = Y(1) ?> x.u Runtime Error: Foo instance has no field 'u' 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. 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.
- tel 12y agoYeah, the Prelude in Haskell has a lot of warts. Interestingly, if you use some of the Template Haskell derivations for lenses you get this record-of-sum optionality resolved at least partly.
- mgiuca 12y ago(I am the designer of Mars.) You make an interesting point. I haven't decided if I agree with you, but here are my thoughts. If I understand you, you're saying that x.v should have type Num, but x.u should have type Maybe(Num) (because u is not totally covered). That sounds like a very bad thing, because it means that if I were to change the type so that u is covered, by changing Y to: Y(u :: Num, v :: Num) then suddenly everywhere I refer to x.u would break, because x.u would now have type Num, not Maybe(Num). If I was to go for the "safe" option, it would have to be that all fields return a Maybe no matter what (and I think that would make fields quite unpleasant to use). I think a better plan (which I've designed but didn't implement -- and I realise that now executing this plan would require a backwards incompatible version of the language) would be to do a simple static analysis of switch statements which records exactly which constructors a variable might have at any given program point, and make it a compile-time error to access a field of a variable unless it is provable that the variable has that field. So in general, x.u would be a compile error. But this code would be legal, and never generate a runtime error: switch x: case X: whatever(x.u) You could also do error checking up front to avoid nesting your code too much: switch x: case Y: error("blah") # Guaranteed to have a 'u'. whatever(x.u) (For the record, I actually didn't blindly copy Haskell's semantics in this instance; I came up with this scheme myself and then only later discovered that Haskell had the exact same scheme!)
- adultSwim 12y agoCalling 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. --- The language looks pretty good. I think for most programmers some kind of vanilla ML would work well.
- vfclists 12y agoFirst time I ever saw on appspot.com 503 over quota message. Are Google that measly with the bandwidth allocations?
- mgiuca 12y agoApparently you only get 1GB per day. I've enabled billing now so it's back on its feet.