Hacker Newsnew | past | comments | ask | show | jobs | submit | stefanchrobot's commentslogin

Why not both? I want the language to provide an iterable/enumerable interface with the usual generic workhorses (map, reduce, etc.) and allow me to implement that interface as a free function for any type. If I'm authoring a type, I'll add specialized functions as needed.


Ruby manages to do this. The default implementations of all the methods you want are on the enumerable module, so if you implement the “each” method you get everything, including the ability to get an enumerator object that you can pass round and use for anything else you want.


Very satisfied with Elixir! I think it just fits my way of thinking. I love the terse, but explicit code, the VM, OTP, pattern matching, working with immutable data, integrated tooling, documentation support. The community is great, too.

The popular packages are top-notch, but as others have said - there might be issues finding what you need. My personal experience seems to be the opposite though - when going from Elixir to Ruby, it turned out that some of the gems were really, really far from perfect.

In terms of deployment, my take is that the community has finally figured it out. Elixir is a compiled language, so there is a build-time configuration and runtime configuration and I think it's best to keep the two separate, which is now well supported by the new runtime config (Elixir >= 1.11). Mix releases + runtime.exs + Docker works for me perfectly.

If you're coming from RoR, you'll be able to pick up Phoenix really quickly. It draws a pretty clear line between your web layer and your business/app layer though. Writing controllers and views should be similar, but I'd suggest spending some time on Ecto - it's quite different from ActiveRecord (in a good way, IMO).

One thing I'm missing in Elixir is optional static typing akin of TypeScript, but that's not coming anywhere soon. Other than that, no regrets.

I got introduced to Elixir in 2015 and was trying to work with it full-time since then. I was able to get a full-time Elixir job and I'm really happy about that. If you're looking for opportunities, I'd suggest attending ElixirConf or ElixirConf EU - last year I got 5 interesting job opportunities from ElixirConf EU alone (it was a virtual event, so the ticket was cheap).



Hey Stefan, nice to see you here :)


Oh, wow. The language was complex already and this makes me avoid C++ unless it's constrained to a narrow subset (something like Google C++ Style Guide). No wonder languages like Go and Rust gain so much traction.


I find comments of this type bizarre. C++20 is trying to make the language -less- complex by deprecating the aspects of it that make things gross. Yes, for it to still be C++, you have to "add" the modules feature to the compiler, but the whole point of adding them is so that you -don't- have to think about include's. All of the disgusting complexity that results from doing literal textual inclusion goes away if we all use modules. Instead of having mandatory ifdef's in every header, repeated compilation of the same code, humongous compilation units, separation of implementation and interface (except for templates!)(and inlines!), you get... the interface we know we want.

If you have arguments with the implementation that's one thing, but what would you prefer? That the language just stay still, warts and all? Ok... well then just keep using C++03. But you probably don't want to do that, because '03 sucks, right? Ok, and what would make it better? ----> All the things they're trying to fix via C'11 through C'20...


Well, hopefully NOT like the Google Style Guide, which is pretty universally seen in the C++ community as A Bad Thing, unless you work for Google.

And as I pointed out in another comment, these additions are mostly not aimed at C++ application developers. If you don't need them (and you probably won't) then don't use them.


And as I pointed out in another comment, these additions are mostly not aimed at C++ application developers.

That's often been true in other recent C++ standards, but looking at the linked page about C++20 in particular, quite a lot of those points might reasonably appear in application code.

If you don't need them (and you probably won't) then don't use them.

The trouble with this argument has always been that if your language provides a certain feature or syntax, even if you don't use it, there is no guarantee that everyone else whose code you depend on won't use it either.

Some language features are inherently contagious. If you are calling code that uses exceptions or const qualifiers or asynchronicity, you probably need to take that into account in your own code. I recognise that these aren't particularly esoteric as language features go, but I've still seen plenty of teams over the years that attempted to avoid using them in C++ based on some argument about making things too complicated, mostly with results that weren't great.

Even for new language features that are expected to be used mostly within libraries and not to be seen much in application code, you might still have to dig into the source code for a library to trace a bug or performance problem, which means in practice you still need enough awareness of the full language to do that.

Extra complexity in the design of a programming language always comes at a cost, whether or not you intend to use it. The important question is usually whether the price is worth paying.


> I've still seen plenty of teams over the years that attempted to avoid using them in C++ based on some argument about making things too complicated

Of course - the Google Style Guide being a prime example.

> you might still have to dig into the source code for a library to trace a bug or performance problem

I've been programming in C++ since the 1980s and I've never even tried to debug someone else's library - life's too short, and it's not what I'm getting paid for. Have you looked at the source for (say) your Standard Library implementation? If you are not intimately familiar with it (which kind of negates the advantages of using a library in the first place) you won't stand a chance of debugging it, no matter how deep your knowledge of the C++ Standard.


>Have you looked at the source for (say) your Standard Library implementation?

All the time, why would this be unusual? I actually find myself often looking over MSVC's implementation straight in VS and comparing it to libstdc++:

https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-...

One recent thing I caught from going over the implementation was how MSVC's implementation of std::tuple is semantically different from GCC's, where GCC constructs left to right, but MSVC constructs from right to left.

I also debug through boost and have reported bugs, or just found bugs in it that had already been reported.

Qt is another library that I am constantly reading over, heck if anything just for the sake of learning interesting UI implementation techniques.

Anecdotally, I find it unfortunate that people who talk about how they've been programming in C++ for 30+ years are almost always the ones who have very backwards and archaic practices and talk about those practices like they are common place.

"I've been programming in C++ for 500 years and never once have I had to do this, therefore it follows that no other C++ developer will ever have to do it either!"

There are entire generations of developers who've learned C++ and use it in ways very different from you, in technical domains you may not even realize exist. Don't presume that just because you personally have never done something, that it can't possibly be relevant or useful to an entire community of developers using the same technologies as you but in different ways.


I'm saying that on principle I do not debug other people's libraries (I do, of course, debug my own). I also do use many modern C++ features, (C++11 and later) particularly from the Standard Library, and I think that more developers should do so.


Fair enough, that's a principle you can have for yourself and depending on your role and responsibilities that may suit you. But at least be aware that others may have a different principle and set of responsibilities. I have a professional responsibility to take all measures I can to deliver the most reliable software to my customers and if that means debugging third party libraries, so be it. Heck if that means debugging the toolchain, the operating system, whatever the case, then it's my job to do it.

I don't have the luxury of having the software I deliver to end users fail and then saying "Oh well, it's because there's a bug in a third party library and as a matter of principle I don't bother debugging it, reporting it, or taking basic measures to deal with it so you poor customers will just have to deal with it."


Project manager asks me:

"What did you do this week?"

I say:

a) "I spent the week chasing down an apparent bug on one of the Standard Libraries we use."

or:

b) "I implemented connectivity with the Hong Kong stock exchange, improved our MT performance to get a 20% improvement on submitting trades, and identified a bug we were having with currency conversions as possibly being in one of the libraries we use, wrote a work-around for it, wrote the fix and tests up on our developer wikki, and submitted a report to the library vendor."

Now, I would say that(b) is of far more value for the company I work for and is at least as "professional" as (a).


Several times in my life I've been in situations where a) was more important because the bug was causing real issues now. In your industry a bug that miscalculates risk can cost billions of dollars. In my industry a bug can cause a safety system to fail and kill people.


It looks like we're in similar industries then based on your comment and if that's more or less the level you've been operating at on a weekly basis for decades then without a doubt you are a significantly more productive individual than I am and really kudos to you for it.

My point is mostly that not everyone is you though, similarly I don't presume everyone works like I do. Hence arguing that because you've done something for 30 years that it reasonably follows that everyone else should also do it is a really poor argument.


Now, I would say that(b) is of far more value for the company I work for and is at least as "professional" as (a).

That's fine, but it does assume that a workaround exists and can be implemented within a reasonable amount of time. If you're talking about a bug in a library of convenient text processing utilities, that might well be the case. If you're talking about a bug in a security-related library that you rely on to authenticate instructions to make high-value trades, maybe not so much.


Fair enough, that's a principle you can have for yourself and depending on your role and responsibilities that may suit you. But at least be aware that others may have a different principle and set of responsibilities.

I can't upvote this sentiment enough. C++ has been used by millions of programmers working in numerous fields over a period of decades. Any attempt to generalise from a single person's own experience of using C++ to that entire community is surely unwise. I note (for no particular reason, honest) that this applies even if you are a long-standing member of the standards committee.


I've never even tried to debug someone else's library - life's too short, and it's not what I'm getting paid for.

What is your general strategy to deal with bugs in other code? Sometimes just stepping through other code and fixing something small there is by far the fastest way to get things done. Not life-shortening at all :) I.e. way faster than alternatives like submitting a bug report and hoping it gets fixed, or hacking around the bug, or looking for another library. I do not understand why you'd abandon the idea out of principle. Perhaps you had some really bad experiences with it when you just started or so?

Have you looked at the source for (say) your Standard Library implementation?

Very often. Usually not to 'debug it' in the sense of finding bugs but to figure out in detail why my code invokes UB or asserts or whatever somewhere else. Or in case of documentation not being clear to find out what really happens. Also a good way to learn by seeing how others write code.


Of course - the Google Style Guide being a prime example.

Indeed, though it's been going on since long before Google was around!

Have you looked at the source for (say) your Standard Library implementation? If you are not intimately familiar with it (which kind of negates the advantages of using a library in the first place) you won't stand a chance of debugging it, no matter how deep your knowledge of the C++ Standard.

Some years ago, I did exactly that. Found a bug in it, too.

Part of my concern with the ever-increasing complexity of C++ since C++11 is that what I did back then would be increasingly difficult today, because there are so many intricacies aimed at library writers squeezing out every last drop of performance. Of course, for a systems programming language like C++, that emphasis is understandable. But as I said, extra complexity in language design always comes at a cost. And if we'd had to wait for someone upstream to fix the bug in the library I mentioned above, that cost would have had quite a lot of digits in it and a dollar sign at the front.


Many of the new features will help with readability. Conditionally explicit is a good example. There are a ton of places in the standard library where conditionally explicit constructors are needed, and the workaround isn't too nice, it's a ton of boilerplate.

Concepts will also help for the same reason. SFINAE is used a lot in libraries and it's simply not readable. Concepts will make it more approachable.


Many of the new features will help with readability.

Indeed, and this has been the argument for many of the new developments right back to C++11. There is something of a devil-you-know argument here as well, though.

SFINAE is a surprisingly useful consequence of the way overload resolution is specified, but as you say, it's been used a lot. Many C++ programmers have encountered it over the years. Much has been written about it to explain it for those encountering it for the first time.

Realistically, C++ programmers will still have to understand the resolution rules even after C++20 becomes widely adopted. Those rules are also relevant for other reasons, and even in the specific case of SFINAE, the entire ecosystem isn't going to rewrite all its code to use newer alternatives overnight.

So now, any new C++ programmer who wants to analyse a third party library to trace the source of a bug is going to need to recognise multiple techniques to achieve that kind of behaviour and not just the strange but at least ubiquitous way we had before.


Only somewhat. As new features become more common the old ones that were harder to use become less important. C++11 has made a big impact on the type of C++ you see in the real world, now that it is 9 years old we can see change. The change wasn't overnight, but it is there.


Do you have any pointers to information as to why it’s considered the Google style guide is considered to be a bad thing?


It's the style guide for Google's specific environment. If you are not Google, much of it is likely irrelevant.

For example, the style guide says that C++ exceptions are the way to go...except that by the time the guide was written there was already too much existing code that wasn't exception safe. Therefore the guide says that regretfully, exceptions cannot be used.

Edit: clarification


And this is why the guide is "bad" - you simply can't avoid dealing with exceptions in C++ code, unless you also forgo the Standard Library, use weird and unreliable methods to detect constructor failures, and a bevy of other problems.


Many of the rules that are considered best practices in Tour of C++ or C++ Core Guidelines are no go for Google.



And I disagreed. Application developers need to break their code up, Modules aid that. Applications generally have a few custom templates for something and so concepts will be useful. <=> is useful for a lot of classes.


As I said: "mostly not aimed at C++ application developers" - note the word "mostly". Of course, some features are usable and useful to application developers.


The only thing here where I think "wow, that's a lot" is the whole `module` thing (and even that, I'm sure I could love, it's just alien to me for now, and I doubt it'll gain much traction for quite a while). Everything else seems like a very C++ thing, or an improvement.

No one ever forces you to use extra features. But if you can improve/reduce your code, why not?


Erlang's VM comes to mind. It has great APIs for inspecting a running system and quite a few options for consuming that data: build-in observer [0], CLI version [1], web live dashboard [3] and more.

[0] https://erlang.org/doc/apps/observer/observer_ug.html

[1] https://github.com/zhongwencool/observer_cli

[2] https://github.com/phoenixframework/phoenix_live_dashboard


...or pattern matching in case of dynamically-typed languages:

  case some_operation() do
    {:ok, result} -> # do something with result
    {:error, error} -> # handle the error
  end


You lose the ability to make sure you've handled an error AOT, but sure, this feature is pretty much the same as a sum type except that it's structural. When I used to write typescript, there were plenty of times I was happy to have it's union types!


Similar tool that I currently use: https://github.com/watchexec/watchexec


Original author here, glad you like it!

watchexec was borne out of a few frustrations with entr, mostly around how it handles new files being created. However, from a pure design standpoint, entr is just better than most anything out there due how closely it hews to UNIX philosophy, and it gets so far on just that.

The only real improvement that can be made to these tools (currently) would be to have perfect information about what caused a file to change. Currently, most tools require you to tell it files/patterns to ignore to avoid triggering loops where the file watcher changes files and ends up triggering itself over and over. watchexec did good work here by ingesting your .gitignore and using that.

Unfortunately OSes don't provide great info when it comes to file modifications. On Linux, ptrace/LD_PRELOAD would enable us to know the set of all files changed as a result of running the file watcher (and thus ignoring them automatically). DYLD_INSERT_LIBRARIES is a thing on macOS, though it is subject to SIP restrictions with some binaries. I'm unsure what mechanism exists on Windows. The highly platform-dependent nature of this is one reason why I haven't really pursued this line of work in watchexec.


Thank you for watchexec. It makes my life better every day.


I started to write the engine for my favourite game in my favourite programming language and the experience was addictive and enjoyable beyond compare. Sadly I just couldn't justify to myself the amount of hours that I would need to spend to complete this project.


A much better suggestion would be to look for a language/VM that supports a better concurrency primitives, like Elixir/Erlang. Obviously you can't run that everywhere, so sometimes you'd have to deal with threads. But after giving Ruby an honest shot at writing a backend system and hitting concurrency bugs (in an external gem), I'd rather avoid threaded programming model altogether.


This is another categorical statement. I love how the languages you mention do concurrency, but I don't think that if you use threads, one should only be doing it in Elixir/Erlang (or go).

I find that nearly as disagreeable as the original posting.


I'm categorical only in terms of my personal preferences. Threading model is just hard, so in general, I'd suggest looking for alternatives. But that's not a universal advice as there are cases where it does not apply or the developers are up to the task of handling multiple threads.


Quite surprising take on the languages.

> When to use Python or Ruby

> Python and Ruby seem to me to be pretty similar in that they’re scripting languages and dynamically typed and seemed like the greatest thing in the 00’s. You use them when speed is more important than legibility or debugging.

I'd say you pick them when productivity and time to market is important. I personally find dynamic languages far more legible (unless you're doing metaprogramming-heavy stuff).

> Haskell or Erlang maybe I would use if I were doing something that required a very elegant or mathematical functional approach without a lot of business logic.

I think it's a mistake to throw these two into the same bag. I'd say Haskell is functional and comes from academia. Erlang is concurrent (with functional aspects) and comes from engineering background. You'd want to pick Erlang if you want to build scalable backend systems.

> my guidelines for JS are:

> Try to push as much logic as possible to the server. If the front end weren’t super complex, I would consider something like Phoenix instead which actually pushes everything to the server.

Phoenix is a web framework for Elixir and Elixir is a Ruby-like syntax on top of the amazing Erlang VM, so this kind of contradicts the suggestion above. Either way, Phoenix LiveView might be a game changer when it's applicable and for people who don't find the whole JS thing very exciting.


People overrate the elegance and readability of languages. You can write elegant and inelegant Java. I've seen python code that is totally unmaintainable and python code that's some of the most elegant out there. You can find Rails code that is some of the most indecipherable spaghetti out there despite Ruby being such an elegant language (the project had Fat Controllers, Fat Views and Fat Stored Procedures...yikes). There's a lot of elegant C code out there then there's C code where you don't wanna touch anything because you're not sure what anything does.

I think the general rule of thumb for languages is pick whichever language has the best community, learning resources and packages for your project.

For example R excels at analyzing data because of the wealth of packages from industry and academia for analyzing data and the tutorials dedicated to statistical analysis in R. Python excels at high performance data driven products because of the wealth of packages for ML, scientific computing, etc and the wealth of resources on doing these things in python.

The exception to this is JS and your point about Phoenix LiveView. Potentially it could be better to pick a single language for frontend and backend to limit context switching while developing frontend and backend.

I haven't used Clojure or Haskell yet so I don't know what they excel at. I also haven't dived into Erlang and Go enough to know which situations either is better for scalable backends.


> People overrate the elegance and readability of languages. You can write elegant and inelegant Java.

It's not what you can write, it's what the next guy can write.

You can write elegant Perl. But the language isn't suited to that. The next guy is going to use a more typical write-only style of Perl. Extreme example, but you take my point.


> People overrate the elegance and readability of languages.

> The exception to this is JS

JavaScript is beautiful. You're crazy.


I think I was unclear. I meant that the exception to picking a language based on community, resources and modules are JS and Phoenix Liveview where there is an additional benefit of using a single language for frontend and backend. In these two examples you might forego using a separate language for frontend and backend (that could have a better community, resources or modules for what you are building) because you can use the same language for both (which offers the unique advantage of having to use and learn less tools for a fullstack app).


> I personally find dynamic languages far more legible

Maybe you're a 2xer though.


"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?" -Brian Kernighan

Over time I've come to appreciate this sentiment. Banging out clever code super fast isn't that important... Spending some time up front thinking about types and architecture pays off in the long run. Especially for server side code. Far from being annoying, error messages from the compiler make me feel warm and fuzzy inside.

On the other hand, for quickly prototyping user interfaces, some "stream of consciousness" Javascript might just be good enough.


I very much like this quote. Used to work with a team of contractors out of Eastern Europe. They were exceptional programmers but wrote code using obscure language features and in such an odd way that now that they are gone, every time someone has to debug some of their code its a very frustrating process. There are definitely times to use 'clever' coding practices but nine times out of 10, just write it simply and focus on readability. Your team will thank you and you will thank yourself a couple years down the road.


We all used to do this (ii feels right) until we got burned or had to upgrade and rewrite. Now I try to make everything as simple and straightforward. Really helps you scale because yesterdays work doesn' t need to change.


Me? I’m a fan of Blub.


I liked Blub before the 3.0 release ruined it with all those new features.


Well written code in dynamic languages is legible. The problem is when you encounter poorly written, illegible code in a dynamic language, the lack of strong types kneecaps your ability to figure out what it is supposed to do.

I loved Ruby until I inherited a project that was poorly written Ruby.


Well, you can't make everyone happy. Personally, I've started with the C family of languages (C, C++, C#, bit of Java), but after going through Python, Ruby and Elixir I never want to go back to curly braces. The other thing that puts me off is mixing types into the declarations - I treat types as comments and only reach for them if I need to dig deeper; in most of the cases the names of the arguments are self explanatory and types make it really hard for me to parse the function declaration. So instead of this:

  pub fn any(tree: Tree(a), check: fn(a) -> Bool) -> Bool
I'd really prefer something like this (preferably with a syntax highlighter that would grey out the types):

  fn(Tree(a), fn(a) -> Bool) -> Bool
  pub fn any(tree, check)
For some people, including myself, type annotations in Python are killing the spirit of the language. For me, there's no way to format those declarations to look reasonable, except for doing it like in Haskell or Elixir (@type).


While what you've suggested is my preference I've found us to be in the minority, so we moved away from it.

The syntax well not be changing again I'm afraid.


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

Search: