Settings

Theme

Have: a new language that transpiles to Go

havelang.org

77 points by wowoc 9 years ago · 66 comments

Reader

bnchrch 9 years ago

If I had one recommendation to increase your projects chance of success it would be to make sure a snippet of code is shown right away. On your homepage, on your github page, where ever you think someone will encounter the project for the very first time.

This seems to be a common problem with programming language projects, at least initially, so I'm not trying to berate or shame you just point it out.

Anyways it does look interesting and I'm always happy when I see python inspired syntax!

  • felixangell1024 9 years ago

    To add to this: show some of the banner features of the language - what makes it different to X or Y, and why would I want to use it or look into it more.

  • wowocOP 9 years ago

    Thanks! Yeah, now it does seem bad that I haven't put any snippets on the front page. I'll fix that later today.

  • Syzygies 9 years ago

    Yep, good advice, and I admire the degree of encouragement you're giving.

    I stopped reading when I timed out, still having no idea what the point is here, other that an exercise for the author. Make the case up front somehow, but make the sale while you still have eyeballs looking.

nolite 9 years ago

Is this a contest to find the most ungoogleable names possible? I think they just took the lead..

  • ionforce 9 years ago

    Do you have Have? You would have had Have if you could have Googled for it. But that's okay. Having half Have is better than having no Have at all.

  • cleaver 9 years ago

    "Have" is a top 10 most common word for English. "Go" is only top 50. They've gone five times better.

    As for how much better you can do... Someone just (6 days ago) registered "be-lang.com" so we might get a top 2. Good news is that "the-lang.com" and the .org equivalents are available.

    https://en.wikipedia.org/wiki/Most_common_words_in_English

  • 0xmohit 9 years ago

    The syntax is inspired by Python/Go and the name by Haxe [0].

    [0] https://haxe.org/

    • na85 9 years ago

      I'm not sure that that makes it okay to use such an ambiguous word as a name. I guess they were following Go's similarly bone-headed choice.

      • kbenson 9 years ago

        Next we'll have a pared down forth (!) called for, a variation of self called me, and a specialized subset of C called c *we'll have used up all the crappy names by then, so people will just start using case to denote the difference). But that's okay, because according to the developers you pronounce it "little-c". so it's not confusing at all.

        • untothebreach 9 years ago

          Well half the devs call it "little-c" but the other half call it "clang," and what do you mean there is already something called clang?

        • vortico 9 years ago

          Ha, "c" is hilariously bad. I suggest the file extension to be .C since C gets to use .c

  • rootbear 9 years ago

    It won't be a problem, since the name of this language is pronounced "hah-vay".

    (Just kidding!)

Lxr 9 years ago

The command to transpile should be havetogo :)

guessmyname 9 years ago

I read the name "Have" as "Haxe" [1] and thought it was a subset of their cross-platform toolkit. I cannot think of many use cases (a transpiler for a system programming language) because Go in itself is very simple, which is one of the main reasons so many developers from other communities have switched, because with a short list of reserved keywords, C-like syntax, and simplicity of its standard library people can do amazing things.

At least it will provide Generics [2] ¯\_(ツ)_/¯

Would you use a project like this? If yes, for what?

[1] https://haxe.org/

[2] http://havelang.org/post/for_gophers/#generics

  • echelon 9 years ago

    I'm already becoming really productive in Rust, so I haven't had any reason to really pick up Go. (We do use it at our company, but I mostly work in Java, Ruby, and TypeScript.)

    That said, the idea of a transpiled language that adds generics definitely piques my interest. Ultimately, I suppose I would be worried of the language stalling or falling out of favor, like CoffeeScript.

    The name choice doesn't seem that well thought out, which also makes me question the authors somewhat.

    • wowocOP 9 years ago

      I think the issue with CoffeeScript was that it didn't add anything beyond the arguably prettier syntax.

      Have changes the syntax too, but it is also trying to fix things that often cause bugs in Go code, it adds generics, and there are a few other features on the way, too.

  • nouney 9 years ago

    No I wouldn't. I can't see any reasons to use Have.

weberc2 9 years ago

I'm not usually a stickler for syntax, but `interface{}` => `interface: pass`? It really seems like the indentation approach creates more problems than it solves. :(

EDIT: Props for writing this in Go though. Oden (the other 'compiles to Go' language) is implemented in Haskell, which means that I can't hack on it.

  • s_kilk 9 years ago

    Basically the same problem Python suffers from. You can omit block symbols from the language, but you still need a way to express an empty block.

  • wowocOP 9 years ago

    That's what I'm a bit afraid of - that it will feel awkward to people without prior Python experience. I have spent a considerable amount of time developing in Python, so the way empty interface is written looks natural to me.

    • weberc2 9 years ago

      I program in Python professionally, and it still feels a bit awkward. :/ I don't want to make this a bigger deal than it is, but I'm not sure that you gain much by adhering to the Python syntax. That's just my $0.02. I'm excited to play around with it though. :)

gravypod 9 years ago

Might be worth using just for generics. Template out small bits you need, compile them to go and use them as libraries for generic-heavy tasks like sorts and what not.

Merovius 9 years ago

So, let me phrase my criticism as questions :)

How do you declare methods on non-struct types? Or are you disallowing defining your own non-struct types? It seems to me that the method-syntax you introduced will either be a step back, because it disallows non-struct types, or it will be a step back because it makes method declaration inconsistent.

How are the generics implemented? The general tone seems to suggest that you do naive template expansion, but the section about when makes it seem that you are using interface{} and type-assertions in the generated code.

How is the overloading of make handled (assuming it's actually just implemented with the existing generic mechanisms)? It can take between 1 and 3 arguments and does vastly different things to them depending on the type parameter. The latter part might be handled by your specialization mechanism (with considerable runtime overhead for a very central part of the language), but the former is not described.

Overall, I admire implementing a language as a hobby project (I always wanted to do that myself). But I don't see anything that would compel a significant share of people to migrate over either from python or from go. It doesn't come close to python's expressiveness and it also lacks go's simple and orthogonal design.

It seems to me, that you added a few things that are better addressed (and will be addressed) in an eventual go2 and then more or less arbitrarily changed a bunch of things for personal taste. The result feels a bit patchworky; your generics have even more overlap with interfaces than people have feared about a go addition (which is one of the major reasons it doesn't have them) due to the type-switchy-when and the syntax changes create a bunch of inconsistencies.

Still. Plow forwards :) There can only come good of more stuff in the world :)

  • wowocOP 9 years ago

    > How do you declare methods on non-struct types? Or are you disallowing defining your own non-struct types?

    It will be allowed, through type opening (which isn't implemented yet). It's mentioned in the intro, I called it "structure opening" but actually it will work on any non-builtin named type.

    I'm not sure how the syntax will look like yet, but say that you have a struct:

      struct A:
        func MethodA():
          pass
    
    Then you will be able to open it and add new methods to it, it could look like this:

      open A:
        func MethodB():
          pass
    
    > How are the generics implemented? The general tone seems to suggest that you do naive template expansion, but the section about when makes it seem that you are using interface{} and type-assertions in the generated code.

    No, it's closer to template expansion, "when" is "executed" (for lack of a better word) during compilation. Inactive "when" branches are ignored by the code generator (and type checker, thus they can contain code that's invalid for given instantiation). There's no type-switch in the resulting Go code.

    > How is the overloading of make handled (assuming it's actually just implemented with the existing generic mechanisms)?

    Right now it's not handled at all. I don't want to add default argument values to the language, so, unless I come up with something better, I'm afraid that there will need to be more than one "make" function, each named differently.

    Thanks for your feedback! I'm well aware that the chances of Have becoming popular are tiny, but I'm having lots of fun working on it anyway.

    • Merovius 9 years ago

      > No, it's closer to template expansion, "when" is "executed" (for lack of a better word) during compilation. Inactive "when" branches are ignored by the code generator (and type checker, thus they can contain code that's invalid for given instantiation). There's no type-switch in the resulting Go code.

      As I've now understood better what you mean, let me suggest a possible solution to your default-case conundrum: What about, if I don't want to allow the default-case, I just leave out the default case? And the compiler erroring out, if you pass in a type to a when-statement that doesn't have a valid case defined?

    • cbHXBY1D 9 years ago

      > No, it's closer to template expansion, "when" is "executed" (for lack of a better word) during compilation. Inactive "when" branches are ignored by the code generator (and type checker, thus they can contain code that's invalid for given instantiation). There's no type-switch in the resulting Go code.

      I'm not sure I understand. Could you point to where you do this on Github?

    • NateDad 9 years ago

      Not quite sure why this isn't just

        type foo int:
            func MethodA():
                pass
      
      
      Analagous to this:

        type foo int
        func (foo) MethodA(){}
      
      Why opening and all that? Or is that a way to add methods to types outside the current package? If so, you're opening up a whole new can of worms.
      • wowocOP 9 years ago

        Your example looks good as well. Opening gives more flexibility with how the code can be structured, say that you have two interfaces:

          type I interface {
            A()
          }
        
          type J interface {
            B()
          }
        
        And you have two structs that implement them, you can then group methods from the same interface together:

          type X struct{}
          type Y struct{}
        
          func (x X) A() {}
          func (y Y) A() {}
        
          func (x X) B() {}
          func (y Y) B() {}
        
        I've seen that used in the Golang codebase, and sometimes it does seem useful.
    • wnoise 9 years ago

      Why the exception for built-in types?

      • perfmode 9 years ago

        I think it might be because you can't define methods on built-in types.

        func (s *[]string) Foo() is not valid.

        func (m map[int]string) Bar() is not valid.

        • wowocOP 9 years ago

          That too, but I rather meant predeclared named types. According to Go specification, types that you define with "type Name OldName" are named, but "int", "string" and the rest are named too. Go disallows declaring methods on predeclared types.

          https://golang.org/ref/spec#Types

diggan 9 years ago

Interesting! But I would love a clojure-like (or even clojure) that compiles into go-code and then built into native code (or another solution). I don't really want to ship .jar files, and I love golang for building CLIs but I really want to get away from that kind of syntax.

gagege 9 years ago

Should have called it Hare, to go along with the rodent theme.

leshow 9 years ago

The author claims one of the goals is to write zero cost data structures. i don't see how thats possible if it compiles to Go, as most data structures in go have implicit cost associated with it because there is a language runtime and GC.

Unless he means zero-cost ON TOP of Go, which is an odd definition.

NateDad 9 years ago

reposted from r/golang:

> Have is an indentation based language

Nooope.

That kills half the benefit of gofmt - fixing indentation.

  if foo:
  bar()
Did I forget a "pass" or did I forget to indent bar? You can't tell, so you just have to punt.

It also prevents fixing up copy and paste:

  if foo:
  --paste start--
          if tooMuchIndentation():
              something()
  --paste end--
      previouslyInsideIf()
What would your formatter do here? Did I mean for the last line to be inside the new if, or outside of it? You can't tell, so you have to make an assumption, and it'll be wrong half the time.

And that's not to mention all the other benefits of braces, like easy visual indication where blocks start and stop, having anonymous blocks (without if true), etc.

Also, requiring methods to be placed inside of structs (or, presumably other named types like type foo int) means that for large files, it won't be immediately clear what type a method is for.

Halfway down the 1000 line file network.go you have

  func *String() string: return self.Name()
What type is this declared on? There's no way to know without scrolling up to the beginning of the type declaration. Also it means that almost all your code is uselessly indented once for no reason.
  • YesThatTom2 9 years ago

    I would expect havefmt would read the indenting using the Python indenting rules (which cover situations where, for example, one line is 10 spaces and the next line is 5 spaces and 1 tab). It would then write it out to be uniformly 2 space indents (if you are a Google employee) or 4 space indents otherwise.

    Yes, go has the benefit that you can do pathologically bad formatting and let gofmt fix it all. I love to type my Go code and rarely press RETURN, knowing gofmt will fix it. However, I also miss the Python indenting system.

  • wowocOP 9 years ago

    Well, that's a more general problem with indentation based languages, but Python users seem to be happy. It's a tradeoff, code that's (arguably) more pleasant to read, for a bit more work while writing it.

    It's true that gofmt-like tool would be less beneficial, but I think that most of the things you've mentioned could be helped with editor/IDE support, e.g. indent-aware paste, block navigation and so on.

    • nilliams 9 years ago

      Yep this, basically the things gpp mentioned just aren't problems day-to-day for Python developers.

      And the 'halfway down the 1000 line file' one was just plain silly.

knocte 9 years ago

Generics and tabs, awesome!

Now, if you remove the horrible feature of ignoring errors by default, I will play with it :)

drcongo 9 years ago

If this manages to bring the readability of Python to Go then I'm all for it. Good luck!

anentropic 9 years ago

"Tabs are preferred"

Aaaarggghh!!!

:)

  • Stratoscope 9 years ago

    Tabs make great sense in an indentation-based language. One tab, one indent level. Left and right cursor keys move one indent. No questions of how many spaces to use, and no off-by-one errors in your spacing.

    The only real advantage of indenting with spaces is if you use a column aligned coding style like this:

      SomeFunctionName(firstArgument,
                       secondArgument,
                       AnotherFunctionHere(itsArgument,
                                           itsOtherArgument),
                       lastArgument);
    
    If you use tabs for indentation, you're into the old problem of "should I use tabs to indent and spaces to align?"

    But this kind of column alignment has many disadvantages: excessive line lengths, spurious diffs in your source control when you change the length of a name and have to realign everything, and the fact that you'll very likely forget to realign something when you do a global replace.

    I've seen each of these problems in the Servo source code which uses mandatory column alignment (examples in one of the links below).

    An alternative way to format code is to use indentation only with no column alignment:

      SomeFunctionName(
          firstArgument,
          secondArgument,
          AnotherFunctionHere(
              itsArgument,
              itsOtherArgument
          ),
          lastArgument
      );
    
    This solves all of the problems mentioned above, and it means that tabs become a perfectly reasonable way to indent the code, since there's no question of indentation vs. alignment.

    Here are a couple of previous comments with more examples and discussion of the advantages and disadvantages of indentation vs. column alignment:

    https://news.ycombinator.com/item?id=10206860

    https://news.ycombinator.com/item?id=9469713

sdegutis 9 years ago

The real link: http://havelang.org/post/for_gophers/

So it's just Go with Python syntax: "Have syntax is inspired by Go and Python, but semantics is usually the same as in Go."

  • wowocOP 9 years ago

    Not quite. It has extra things too, like generics. But things that exist in Go are there too, mostly unchanged.

    • jerf 9 years ago

      First, generic disclaimer: To the extent that you just want to have fun and learn things, please be my guest. The rest of this post is suggestions from the point of view of whether you might want others to adopt it in the future.

      That "mostly" in "mostly unchanged" is a problem. Have should probably be either significantly radically different from Go, so that when I use it I'm not confused, or it should be as similar to Go as possible except that it adds some features, so that it seems like a nice add on.

      Rewriting syntax that ends up really just being a gloss on the existing syntax (i.e., not really allowing much new expressiveness) is just a hurdle to the language; it's a hurdle to your implementation, a hurdle to anyone picking it up and using it, and a long-term burden of trying to explain the slight differences to everybody. See, for instance, the Python 2 vs. Python 3 pain.

      Since it seems to me the major feature of Have is giving Go generics, I suggest comparing with some other things already out there: https://github.com/sasha-s/go-inline , and I also reference the projects mentioned in the FAQ. I am not saying these things solve the problem, but you may want to compare notes and steal (in the "good artists borrow, great artists steal" sense) the good things if you can. You might also find it helpful to contact the authors or users of those projects and ask about pain points.

      • witty_username 9 years ago

        The differences between Python 2 and 3 are not just syntax.

        Fixing syntax is easy; 2to3 can do that.

        • jerf 9 years ago

          Considered from the point of view of the entire language landscape, the point is that they were minor little changes. Python 3 is not anything like the way Perl 6 should never have been named "Perl" at all... it's the same language with some minor fixes that did not bring benefits anywhere near commensurate with the costs.

          (It was one of the great learning experiences of my software career, because I was full-throatedly in favor of Python 3 back when it was proposed. My support counted for nothing, so I'm not "responsible" for it in any way, but I still was very wrong.)

          • witty_username 9 years ago

            If they were minor changes then 2to3 should work perfectly.

            But it doesn't; for example 2to3 can't always fix the shift to Unicode by default.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection