For the last couple weeks I've been experimenting with Perl6 because I finally became sufficiently annoyed with Python's lack of real (No GIL) threading and a quick inspection of the Perl6 feature list looked promising. I'm trying to keep an open mind because Perl is pretty culturally different than the languages that I'm used to working with (C++ may give optimized code but it is not trying to be -Ofun) so although I've run into a few stumbling blocks I mean for the points below to just be observations -- I don't have a feel yet for whether or not some of these things are hard for me because I'm not used to them or because they are problem in the language design. Maybe you all can set me straight.
I've read both the "Perl 6 Introduction" and the "Learn Perl 6 in Y minutes" (and a smattering of the advent calendar and the official documentation). They are both well-written and super useful but they don't cover some things that a new Perl6 programmer will run into immediately and where the official documentation is almost completely opaque to an outsider: * Sigils are initially explained in a way that makes them look like a shorthand way to indicate whether or not you have an array or hash or a scalar. But since you can store an array or hash in a $ variable, and because you can put a sigil before the sigil, e.g. @$foo it's not immediately obvious what to prefer and when. Examples using other container types to illustrate that the built-in array and hash types are not special would be useful to make this more clear. The temptation is for me to always use $ and if it turns out I need to loop over something use @$x or %$x. I'm not sure why you wouldn't just want that to be the way to do it in general in the language. Also an explanation of how you implement your own container to be @ or % compatible. * I can find no concise easy-to-understand explanation for how to define what other languages would call constructors. Instead there is a mess of bless, magic inside Mu, new, BUILD, BUILDALL... It's not clear when you should prefer to override BUILD or new or both. I also assume there are some benefits to teasing apart object construction this way, but right now I don't know what they are. This is also an area where I think there are older blog posts confusing the situation because they discuss semantics from an older version of Perl6. * It would be nice for people coming from Python for a tutorial that explained the basic module importing, the scope of things imported, and how name collisions are avoided when importing from two modules that have the same sub. The official documentation is trying to distinguish a bunch of subtle and presumably useful for advanced users distinctions that are completely lost on a newcomer. I just want to know what is the equivalent of import, from foo import bar, and import foo as bar. * Coming from almost any other language the => operator is dark magic because of its implicit quoting of the left hand side. Likewise the implicit quoting done by <foo>. Some explanation of why this is done, and how you could write a sub or operator that does the same thing would probably go a long way towards making it less confusing. * I haven't been able to find any guidance on when I should be using a role and when I should be using a class. The former seem to give you better error messages when you forget to define a method from a base role... So never use classes? I suspect it's more complicated than that. Then there were some more issues that took longer to come up: * Types feel like second-class citizens. Without knowing the details of the implementation it feels like the errors that Perl can statically detect is chosen at random. It's generally useful to have an intuition about what kinds of errors are detectable at compile time versus runtime so that you can prefer the former when designing an API to make it harder for users to hang themselves. There are also instances where it's not clear whether or not something is part of the type system -- I had an undefined method in a role that subclasses/roles were meant to override and I had a derived role that defined it but used different sigils, and a different explicit type on one of the arguments, and Perl6 gave me no errors. Finally if I want to implement my own container I haven't been able to find any documentation explaining how to parameterize my type, e.g. I specifically want MyContainer[int, float]. Also tying in to the point about object construction :D did not appear to work on arguments to overrides of new(). Also sometimes when you get a type error at runtime no line number information is given so where the error occurred is anyone's guess. * :D is a great idea for function signatures, and is what you probably want for 99% percent of all your function arguments but surprisingly is not the default in the otherwise very terse Perl6. Why not? * set/SetHash are confusing on multiple levels. Set can be parameterized by a type but SetHash cannot for some reason. If you deliberately choose to use SetHash and want to do any set operations on it you will get back a set, not a SetHash. If you try to store two equivalent objects in a set, you will get a set with two elements instead of one because apparently sets are hardcoded to use object identity and no obvious API is provided to make them use something else. I'm not up to writing a balanced binary tree implementation for my project, so I stopped after this. Many other aspects of using Perl 6 were a joy, that static types were an option at all was a welcome improvement, as was the method override detection by Roles. Omitting parentheses in method and function calls, regular expressions ignored white space by default, much reduced boilerplate defining simple classes with the implicitly generated named argument constructors, are all pretty sweet as well. Macros look pretty promising although again I had trouble finding good tutorials.