1. 1

    I’d love to hear more about how Reflex changed your career so much.

    1. 2

      Before Haskell I wasn’t really interested in web development at all. Haskell single-handedly made web development interesting (and a lot of other things more fun too) because it provided a learning challenge and abstractions that were up to the task.

      Before Reflex and GHCJS I wasn’t really interested in front-end development at all. Reflex single-handedly made front-end development interesting because it provided a learning challenge and makes complex interactive and composable GUIs enjoyable to write.

    1. 1

      A few short years ago: Emacs. It introduced me to the love of my life: Lisp.

      Also, maybe a bit surprising to some: JavaScript. Getting a job writing JS set me up to get a couple other jobs, and I’ve made a lot of great friends through those experiences. Not to mention that JS also introduced me to FP and subsequently Clojure(Script) and a wider world of programming languages.

      1. 3

        Yeah, I can definitely agree with your choice of Emacs. I recently switched from Vim to Spacemacs and it was a significant jump in my productivity. I almost put it in my above list, but decided not to because although it was a big improvement, it wasn’t quite as paradigm-shattering and career-changing as the other three.

      1. 22

        Pretty sure calling on the fame of a few to validate an argument and/or a position is a fallacy. One of the things I liked most when I coded in C#/VB.Net under the Framework.Net like 7 years ago was the debugger. I think it was pretty darn awesome. And it saved me a LOT of time.

        It’s much easier to set a break point and examine the state of the system around you at that point than it is to pepper printf statements around your code. I think there’s an objective argument to be made about using the right tool for the right job.

        1. 11

          Among other mistakes, I’m pretty sure Linus is not personally debugging all 15 million lines of the kernel, so it’s fairly misleading to say it works for him.

          1. 6

            In the actual article Torvalds talks about using gdb, just not supporting a “kernel debugger”.

            It seems that the author is just plucking out the little bits that sort of make their point.

            1. 2

              Yeah, I work in kernel land every day, I’d call crash/gdb a debugger, I may not be stepping kernel code line by line but honestly that wouldn’t work anyway.

              Is printk a debugger?

              1. 5

                Print is a debugging technique, but I wouldn’t call it a debugger. I would say that a required feature of a debugger is that it allows inspection of program state that was not predetermined at compilation time.

                1. 1

                  Sure but with dynamic debugging, I have stupid scripts watching dmesg -w that turn on/off certain functions that I’m looking at. Which is just splitting hairs really.

          2. 3

            I absolutely agree with you. printf may have lower barrier to entry but is limited. On the other hand many implementations have horrible debugging tools, e.g. Python, Ruby MRI. There are tools that build upon the built-in capabilities but having to look for a third-party software might be a barrier to adoption.

            1. 2

              The author of Python, Guido van Rossum has been quoted as saying that uses print statements for 90% of his debugging.

              Part of me believes that the reason for this is that Guido finds pdb awkward too.

              1. 1

                I absolutely agree with you. printf may have lower barrier to entry but is limited.

                Actually it is the other way around. It is debuggers that are limited–print/log statements are universal. There are many situations where you can’t use debuggers, but I have yet to encounter one where some variation of print statements cannot work. Maybe there are some really low level embedded system situations where print statements are not feasible, but in those cases you certainly won’t have debuggers either.

                1. 3

                  Print statements do not work when you are debugging low-level stuff like object file formats, linking, and machine code generation. In fact, it’s often the case you don’t even have a standard library available. Usually the debugger is the only way to inspect a running program.

                  1. 4

                    Print statements do not work when you are debugging low-level stuff like object file formats, linking, and machine code generation.

                    What? Print statements are the easiest way to debug those. Stepping through the code in a debugger is almost intractable, since you’re doing lots and lots of transformations that need to be correlated, and can be far away from each other.

                    I do use a debugger, but generally I use the debugger as a glorified way of inserting print statements without recompiling. From a recent debugging session for the Myrddin compiler, I had a questionable node ID in the debug dump:

                     ; isn't generic: skipping freshen
                            Delay $54 -> union
                            `Some int
                            `None
                     ;;
                        Unify $54 => foo.u
                                indexes: tynil => tynil
                    

                    At which point I run it again in gdb, and poke around when I’m unifying this:

                    (gdb) b unionunify
                    Breakpoint 5 at 0x425ecb: file infer.c, line 840.
                    (gdb) cond 5 u->tid == 54
                    (gdb) call dump(n, stdout)
                    Nexpr.69@9 (type = (foo.u -> void) [tid 51], op = Ovar, isconst = 1, did=7)
                        Nil
                        Nname.68@9(foo.nope)
                    

                    I could have added the calls to dump in by hand, with conditionals, but I basically use a debugger to do the same thing. Printf debugging and debugger debugging are – for me – more or less the same, but with fewer recompiles.

                    (Also, since when were object formats and machine code generation low level tasks? The result is low level, but the code that generates them can be as high level as you want. It’s just something that reads input and printf()s bytes, nothing fancy.)

                    1. 1

                      I agree. But when you don’t have debugging symbols nor the ability to call things because, say, your call stacks are not correct yet, this doesn’t work. This is especially the case when working cross platform.

                      Right now I’m porting Swift to z/OS and making LLVM target mainframe object file formats. It is not the first time I ’ve been in this sort of environment. I use the print/dump approach when generating the files and it' s great, but it doesn’t work when you actually link them because there’s no DWARF support yet and the specs aren’t as precise as one would hope. So I’m relegated to using stepi in dbx when you can even run something. That’s the low-level I’m referring to.

                      1. 1

                        I agree. But when you don’t have debugging symbols nor the ability to call things because, say, your call stacks are not correct yet, this doesn’t work. This is especially the case when working cross platform.

                        Even then, I tend to use the ‘write’ system call directly for logging [it’s usually not so hard to get that working by thinking about it.]. For dumping data, I write the values directly and interpret a hex dump.

                        When I do step through instruction by instruction – which is sometimes useful, but very rarely – it’s usually because adding the write calls introduces spills that change the incorrect assembly.

                  2. 3

                    Maybe there are some really low level embedded system situations where print statements are not feasible, but in those cases you certainly won’t have debuggers either.

                    To the contrary, if your embedded system has JTAG, debugging is always available, unlike character output.

                  3. 1

                    I dunno, pry in ruby is pretty good. I guess it’s third party so maybe that’s your point, but it’s one of those ubiquitous things in the ruby ecosystem these days… hard to imagine developing without it honestly.

                  4. 1

                    Yes… Carl Sagan: “Authorities must prove their contentions like everybody else.”

                  1. 5

                    I taught a short course in Haskell last summer in Chicago. My experience was that monads aren’t “hard” to learn in the sense that there is a high failure rate. Most competent programmers (all?) can learn monads. It certainly takes time, though, and unlike many things in this field, there are no shortcuts. As in mathematics, you really do have to learn the conceptual infrastructure (e.g. type classes) first, especially if you want to motivate the concept (which is really the only way to make it stick, in my experience).

                    1. 5

                      Monads aren’t that hard to learn. However, to get almost any non trivial stuff done, monad transformers are necessary, and that becomes complicated very fast.

                      1. 3

                        Monad transformers really aren’t much more complicated than monads. They, like monads, just take some time to absorb.

                        1. 2

                          I think the main problem with people talking about monads is the people who understand it don’t enjoy talking in non-rigorous language. What happens is that because there is a lack of good explanation for those that don’t know the terms, then those who barely understand it feel a need to try to explain it which is mostly harmful. You can learn what they are and how to reason about them without the underlying mathematical theory, and those saying otherwise are making perfect the enemy of the good.

                          1. 2

                            But for what? What is the gain from designing a giant stack of transformers?

                            1. 3

                              Monad transformers are one option to control possible program effects using the type system. They work by allowing the combination of multiple monads via transformer types associated with particular monads. For example, if you have a system that needs to both perform IO and read from some sort of global configuration (held in a type Config, we’ll say), you would want some way to combine the IO and Reader monads together. This is accomplished with ReaderT, resulting in ReaderT Config IO (), where Config is the thing to read from, IO is the inner monad, and () is the return type. There are a few different libraries that exist to make using these transformers easier.

                              Monad transformers are not the only option for this sort of problem. There are other options like Extensible Effects and Freer Monads which provide different ergonomics and may be preferable depending on the situation.

                      1. 1

                        Only a couple of orders of magnitude faster than the fastest human?

                        1. 4
                          1. 4

                            It’s 3x3 BLD (the record in that video) that just blows my mind.

                        1. 1

                          Doesn’t New York have about the same climate and the tall buildings that Chicago has? Why doesn’t New York have as many revolving doors?

                          1. 3

                            As someone who lives in Chicago and visits NYC for work, the average difference may not seem like much (Chicago has an average January low of 18F and NYC has an average January low of 26F), but it certainly feels much different.

                            Maybe humans just perceive those lower lows more strongly? From my experience, the change from 0F to 15F feels like a lot more noticeable than a change from 30F to 45F.

                            1. 2

                              Interesting, to me, the change from 0F to 15F is almost nothing, but the change between 30F and 45F feels much different, because the air feels different above freezing as opposed to below. This could just be me though.

                              1. 2

                                I’ve got the same thing although in the Netherlands. I prefer it to be either above 10C or below 0C than in between. Maybe because there’s more water in the air while also being cold between 0C and 10C?

                              2. 2

                                I moved from Boston (very similar climate to New York) to Chicago for university, and was shocked by how much colder it was. Of course, them I moved to Minneapolis, and learned what real cold feels like. Ye cats.

                                1. 2

                                  Eh you get used to it, we’ve got nothing compared to places like anchorage. The wind is what makes cold cold. -20 with no wind? No problem. 10mph wind? Ok now you got my attention.

                              3. 2

                                When I first moved to NYC I was struck by the prevalence of revolving doors. I figured the reason was just that with so many people coming in and out it was more efficient in terms of the HVAC bill and I never thought of the pressure effect. I don’t know how it compares to Chicago, but I can tell you that NYC definitely has a lot of revolving doors compared to anywhere else I have lived.

                                1. 1

                                  Ah, ok. The article seemed to be saying that NYC had hardly any rotating doors:

                                  Minneapolis might be colder and New York may have tall buildings, but Chicago uniquely combines all the important factors.

                                  1. 1

                                    As someone that lives in the twin cities, there really aren’t that many revolving doors even in the tall buildings. And yes we’re colder than Chicago most of the time. I’m actually hard pressed to come up with a skyscraper in Minneapolis or st paul with revolving doors for the entrance. None jump out at me but I’ll be honest I haven’t paid much attention.

                                    Generally though we tend to have 2 sets of doors on buildings, so that might mitigate the pressure situation somewhat. I’ll have to ask my architect drinking buddy what the deal is. I always heard they reduced the cooling/heating bill more than the pressure situation.

                                    1. 1

                                      I think you missed a sentence. “Chicago and New York are the biggest markets for revolving doors.”

                                      Though quite a few places in New York don’t have space for revolving doors. They don’t have space for double doors, either. They just hang a curtain inside the door, which is pretty useless.

                                1. 3

                                  This talk gives one of the best descriptions I’ve ever seen of the motivations for why FRP (Functional Reactive Programming) is useful. All the other explanations I’ve seen are too much in the weeds, but this is clear, concise, and understandable.

                                  To avoid cluttering the front page, here’s the link to part 2: https://www.youtube.com/watch?v=3qfc9XFVo2c