Hacker News new | past | comments | ask | show | jobs | submit login

Looks very interesting from ergonomics point of view: it is indeed does introduce useful tools like generics, type inference, pattern matching, which are very painful to do in C. Though it seems like the language misses on popular nowadays generators, lambdas and coroutines. So I would say give it a plus on language design, and there is a space to grow.

Memory model looks C-ish, there are pro's and con's to it. Guess it works for the niche that language aims for.

What I think could be done better: compiler infrastructure / FFI. In this day and world interoperability with other languages is a must, and there is usually a need to provide standalone and embeddedable implementations of a language. IMHO would be great if Myrddin just compiled to C (like Chicken Scheme), that would broaden possibilities to use Myrddin as script language, or just use it side-by-side with C/C++. It can be done with the current Myrddin compiler implementation, but overhead of maintaining whole separate compiler/toolchain might be too big to enable wider adoption.

---

Edit: I was wrong, all functions are lambdas! Which is really great.




(Primary author here)

> Though it seems like the language misses on popular nowadays generators, lambdas and coroutines. So I would say give it a plus on language design, and there is a space to grow.

Lambdas are actually the only way to define functions.

    const f = {args
         /* do stuff */
    }
is just assigning a lambda literal to 'f'. You can also just pass them around, if you want:

    use std
    const main = {
        var value = 42
        thread.spawn({; std.put("hi from a thread. I captured {}", value)})
    }
Coroutines are possible to implement as a library, and generators don't fit well -- there are iterators, though:

     use iter
     const main = {
          var v = [1,2,3,4]
          for p : iter.byperm(v[:], std.numcmp)
                /* use permutation p */
          ;;
      }
> What I think could be done better: compiler infrastructure / FFI.

You can already link to C, but writing the function definitons function definitions are painful. There's ongoing work to take Andrew Chambers' C compiler implementation, and extend it so that it can automatically generate the glue code.

We had a Summer of Cod[1] person working on it, but they dropped out due to lack of time.

[1] https://myrlang.org/summer-of-cod


> Lambdas are actually the only way to define functions.

Oh, missed lambdas, that's great!

> You can already link to C

I mean, only on Nix-es, only in Sys-V-like ABI. What if I'm under Windows? What if it's not Sys-V? What if I want Javascript (aka emscripten)?

My use case is game development, I could have a need to ship to wide variety of platforms (for some you don't even have publicly available specs, like PS3), and this platforms only provide C/C++ compilers. Why Myrddin compiler take a burden of supporting all C ABI's out there by implementing it's own asm code generation? Easier way out code be just generating higher level code like C or LLVM IR, and using libffi to implement FFI.

I would love languages like Myrddin to succeed, but let's be pragmatic, it is nearly impossible to support asm code generation with all C ABI's without having a full time team working on it. It is a huge time investment (not even speaking of financial investment connected to it). So I find it's hard for languages to get traction because they keep getting stuck inside Sys-V/Windows realm :( While something that compiles to C somehow magically just-work on everything, even web.


> Q: Is GARGLE SUMMER OF COD considered an internship, a job, or any form of employment?

> A: No. You're fucking getting paid in fish, for fuck's sake.

Thank you for the hilarious FAQ.

(read on)


Oh, also, you can abuse closures to do generator-like things with captures, thanks to the way they're implemented.

      use std
      const mkincrement = {inc
           var x = 0
           /* No GC, so the upwards closures are explicit */ 
           -> std.fndup({
                x += inc
                -> x
           })
      }

      const main = {
           var g = mkincrement(5)
           std.put("{}\n", g())
           std.put("{}\n", g())
           std.put("{}\n", g())
           std.put("{}\n", g())
	   std.fnfree(g)
      }
Will output:

      5
      10
      15
      20
The trick is that the function state needs to be in the capture.


> Lambdas are actually the only way to define functions.

How does that work with regards to interacting with the function? If you see that function in a debugger or print it out, do you get just a generic "lambda" name or does it do some magic to get "f" when defined and assigned straight to a name?


> How does that work with regards to interacting with the function? If you see that function in a debugger or print it out, do you get just a generic "lambda" name or does it do some magic to get "f" when defined and assigned straight to a name?

It does some magic to get `f` when assigned straight to a name. The magic is pretty trivial.


Cool language!

Total bikeshedding: why the double semicolon? It's one of the few parts of OCaml that nobody likes.


Single semicolons were useful as line endings, {} always denoted closures, and 'end' is too good a variable name to waste :)


True--the more I thought about it the more it made sense to me.


I think lack of objects/destructors is also a bit of a minus. Manual memory management is hard to get right, and if you're not going to go the Rust route, I think a modern systems language should at least provide RAII-style facilities for managing complex data structures.


In my opinion, "defer" as used by Go and Zig is the way to go in more minimal (i.e. not Rust) C-like languages.


Take a look at

https://eigenstate.org/archive/myrddin-dev/2018-Jan/0000008....

I think there are still going to be some changes before it stabilizes, but it's currently in master.


So as with `defer` in Go, the use is optional?

That is, it makes non-leaky code nicer, but it does not ensure that code is non-leaky.


One thing to note:

In go, defer appends a function call to a heap allocated list that gets run at the end of a function.

In zig, defer (and errdefer) do not allocate memory, and get run at scope exit.


Is defer commonly used for memory management in Zig? I'm not very familiar with Zig, but it seems pretty onerous to have to write defer { free(mything); } after every allocation that's supposed to be scoped.

I don't think it's valid comparison to Go, since that's a garbage collected language.


I just got through evaluating Zig. It's idiomatic to use defer right now but the language is also still pre-1.0 and making big changes, and that's one that might be covered in syntactical sugar at some point. Rust had a GC at one time, after all.

Overall Zig feels closer in intent to C than most "better C" languages. In its current form it has a lot of attention to detail about its behavior around common edge cases. It cares about not blowing the stack and dealing with OOM, and the default behavior of numeric overflow is a crash. Stuff that allocates to the heap is stuff that the programmer is made aware of, and "defer" is one of those little additions. It's less developed w/r to higher level abstractions, with the exception of a strong metaprogramming facility and sum types.


I've written less than 200 lines of Zig but have been kind of following its development on and off. My impression is yes, defer (and errdefer) are intended to be used for this purpose. I don't see the problem with it though.


If you want defer in Rust, th the scopeguard package has your back.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: