1. 22

    There are already a couple of resources to discover personal sites (like this, this or this)

    I think it is much better to use a descriptive link label. Please consider the same sentence, without using this.

    There are already a couple of resources to discover personal sites (like personalsit.es, awesome personal blogs or iwebthings.com)

    Originally I was reading your post on tablet and figuring out what URL this points to was not easy.

    Please have a look at this https://www.w3.org/QA/Tips/noClickHere

    1. 3

      Mozillas anchor documentation and Google docs on links say that your suggestion is better for screen readers that list links out of context.

      While I don’t have documentation, I have heard it is useful for SEO optimization too because you’ve now strongly associated a description with a page.

      1. 1

        I’ve always felt that way, but I never had a source. Thanks for the link.

        1. 1

          You’re right, I will keep this in mind in the future!

        1. 6

          I internalize the story as an argument for pager duty and on-call support roles.

          The problem that upper management faces is that QA can be kind of bad and is reflected in the large scale metrics on customer impact. The cost of bad QA can absolutely be real to the bottom line but not evident in the people in the process. Either you pay it in customer support, reputation, or a user exodus. In this way, it’s no different than what I work on where services or products sometimes go down.

          The solution they created is actually like a system status pager duty. When a detectable error occurs, manual intervention occurs. This applied pressure to certain people in the pipeline to deal with the issues. It sucks to shutdown a processing pipeline and might even be not cost effective, but it forces the pain onto an internal individual instead of your external customers. I.e. we should be catching these problems before our customers realize it’s a problem. Along those lines, while I hate pager duty and on call support roles, I think I’ve also felt empowered to fix some of the worst parts of our system because I now have a concrete goal with my work, to reduce my pages. It turns out necessity ins the mother of invention. I end up solving problems when those problems are on me.

          1. 5

            Along those lines, while I hate pager duty and on call support roles, I think I’ve also felt empowered to fix some of the worst parts of our system because I now have a concrete goal with my work, to reduce my pages. It turns out necessity ins the mother of invention. I end up solving problems when those problems are on me.

            I’ve found this true as well. It’s easy as a developer to become isolated from the actual code that you’re writing, even at a small company. Sure the bugs bother you and you fix them as quickly as you can, but for me at least that always feels pretty abstract. Being forced to deal with an actual customer’s real life problem that was caused because you were being a little lazy one evening two months ago is an eye opener.

            3.5% of today’s users experienced a minor bug

            feels a lot less impactful than

            Jan in Brooklyn is having trouble putting in her data because someone broke the uploader code and she really needs it done by the end of the day because she’s got a big meeting tomorrow and needs to present the results.

          1. 7

            I’m surprised no one has mentioned there’s a “show” tag, which I think is used for sharing projects one has worked on and would very much be a form of self-promotion.

            1. 11

              What’s with this assumption of being a worldwide authority or known entity that’s so popular in blog posts or internet comments?

              My thoughts on…

              I’ve always maintained that…

              Like many people know…

              People who know me know that…

              I’m infamous for…

              Nobody knows who you are - just write your content without the preamble.

              1. 60

                I don’t think a blogger owes anyone being overly modest on their own blog. They can write however they like. I’m going to read it as long as it’s useful and/or entertaining.

                1. 29

                  I thought it was perfectly fine? They have discouraged and discussed this kind of online tooling, and eventually decided to write it up as a blog post. It’s perfectly reasonable to frame this article as the author’s reasoning behind doing what they’re doing.

                  In fact, I’d argue it’s more modest than something like “why online tooling is bad”. With the author’s framing as it is, they’re not pretending to have the objectively correct view; they’re upfront about how this is their opinion on the matter.

                  1. 2

                    That’s true as well. “JWT.io considered harmful” would be a worse post, and the personalisms clearly draw the line between “this is my opinion” and “I speak for everybody”.

                    My original post probably crossed wires between “authority” vs. “familiarity”

                  2. 16

                    You seem like you must be a worldwide authority on how to write preambles for blogs. ;)

                    1. 1

                      Why would he need to be?

                      1. 4

                        He wouldn’t, but as others have cited, being overly critical of someone’s writing because of their particular language choices and not commenting at all on the content being presented is A) Of questionable constructive value and B) Potentially not in the spirit of this very technology oriented forum.

                    2. 14

                      I’m sorry that you read it like so - would you mind explaining what wording made me sound like I think I’m a worldwide authority on the matter?

                      1. 9

                        You’re all good, you have your own voice. It’s some BS that this is the feedback you’re getting unsolicited instead of talking about the actual topic.

                        1. 4

                          Given the reaction, I’m probably in the wrong here. It’s a minor nit that I magnified into a big deal.

                          Buuut, to explain my rationale, it’s specifically your first paragraph. The content was fine (and I use jwt.io often).

                          Something my colleagues know well is how little I trust online tools like jwt.io, online JSON validators or online tooling in general, but it also bleeds into comments I make online and in my blog posts, too, and I thought I’d share a little bit of a reason as to why.

                          I’m not familiar with your coworkers, your online comments, or your blog posts. And I don’t mean that offensively, like “you’re a nobody” - it’s just that in this case I would rather tailor the article for what’s probably the larger group (people who don’t know you) vs. the smaller group (people who know you).

                          My reaction was overblown, and contained more of a general rant towards every instance of this I’ve seen, not your specific violation.

                          To be frank I’m surprised that others disagree (although it’s probably more about me sounding like a dick than my opinion). I genuinely find it strange to read public content that’s written as if I’m this person’s best friend and remember the thing they said in the kitchen last Tuesday.

                        2. 5

                          On the other hand, I dislike when people speak for me on my behalf with phrases like “the python community agrees that” or “all java developers think that”.

                          I also think it’s important to separate things that are factual from opinions. It’s not that my opinion is important but that it’s just an opinion, and everyone can have one. Disagreeing does not necessarily make you wrong when it comes to opinions, but more so when it comes to facts.

                          1. 1

                            “Or, as I’ve lately taken to calling it, …”

                            It’s weird though — these phrases didn’t start out as imitation of people with actual authority, as far as I can tell. A lot of fake authority starts as imitatiion (e.g. dressing like the king/CEO/next-rung manager), but I can’t recall widely respected people like DHH (recently) or JKH (decades ago) ever using phrases like “Like many people know”. These phrases were always fake.

                          1. 4

                            I’m a big fan of “rolling your own crypto” and here I’m talking about implementing known algorithms.

                            Isn’t this article a great example of why NOT to roll your own crypto?

                            1. 4

                              When I read the full two paragraphs around that sentence, I get the feeling it’s for educational purposes, not for real security use, which is why they encourage a security disclaimer.

                              I might be projecting my own views though because I think “rolling your own crypto” is a fantastic way of learning how the system works and how things can fall apart. I’ve learned how easy it is to make mistakes and I’ve never read papers and documentation more thoroughly than with cryptography and compression algorithms since both are so incredibly hard to debug. I’ve also learned a lot about tooling to mitigate these issues.

                              I’m a big fan of “rolling your own crypto” and here I’m talking about implementing known algorithms. I do it myself. I even think making it available on GitHub or similar, to ask for feedback, is good (if users are warned that no security can be expected).

                              However, a problem arises when projects that don’t even uphold the bare minimum of testing test vectors, are published with no warnings at all. Had there been used test vectors in this case, it wouldn’t have left IdentityModel completely broken.

                              1. 2

                                When I read the full two paragraphs around that sentence, I get the feeling it’s for educational purposes, not for real security use, which is why they encourage a security disclaimer.

                                Yes, this is exactly what I mean. And I totally agree with your benefits, that come from exploring it for educational purposes.

                              2. 2

                                Isn’t this article a great example of why NOT to roll your own crypto?

                                Not why. How. Avoiding most mistakes only requires following a few rules. Those rules aren’t easy to follow, but they are pretty easy to know about.

                                1. 1

                                  Exactly, I was going to post the same thing.

                                  One reason it’s not a good idea: After showing a snippet of code that calls some XChaCha20-Poly1305 crypto functions, the author notes:

                                  This is not a XChaCha20-Poly1305 construction.

                                  In other words, the APIs exposed by low-level libraries are like bags of loose components. They have to be wired up correctly in order to work right, and it’s not always obvious how to do so. Even if you know about padding and nonces, a specific cipher can have its own limitations you also need to be aware of.

                                  That’s why I’m a fan of the higher-level libraries stemming from and inspired by Daniel Bernstein’s NaCl (libSodium, Monocypher, CryptoKit, etc) which give you bigger building blocks like “cryptoBox” that do a specific thing and do it right, and choose appropriate algorithms under the hood. That makes it a lot easier to successfully implement a crypto construction, and in a way that’s compatible with other programs that use the same construction.

                                  1. 3

                                    That’s why I’m a fan of the higher-level libraries stemming from and inspired by Daniel Bernstein’s NaCl (libSodium, Monocypher, CryptoKit, etc) which give you bigger building blocks like “cryptoBox” that do a specific thing and do it right, and choose appropriate algorithms under the hood.

                                    Thanks for citing my work, appreciated. :-)

                                    Working on Monocypher had me realise that the NaCl family ((Tweet)NaCl, Libsodium, Monocypher) is actually fairly low level. Yes, providing authenticated encryption and clean key exchange out of the box was a huge improvement. But my work on authenticated key exchange told me that high-level protocols are often fairly delicate, and require significant effort for untrained people to get them right. (Implementing an existing protocol like Noise isn’t too bad, though.) That’s in my opinion a big reason why Latacora’s Cryptographic Right Answers still recommends freaking TLS for client/server security.

                                    I’d say the NaCl family of APIs is a good start. More work is needed to provide even higher-level facilities: full authenticated key exchange, PAKE, encrypted file formats (I’m leering at PURB), certificates… On top of those, we should then provide fully fledged network libraries, that actually handle the I/O (so far I’ve limited myself to manipulating buffers, to minimise dependencies and maximise portability). My, I’m afraid I still have a couple years of work ahead of me…

                                1. 2

                                  I feel like the first example can be solved more elegantly by doing something like

                                  l = [0] * 10;
                                  i = 0;
                                  
                                  rate_limit(l, i):
                                    if now() > l[i]:
                                      l[i] = now() + 1 minute
                                      i += 1
                                      if i == l.size:
                                        i = 0
                                      return false
                                    return true
                                  
                                  1. 2

                                    It’s roughly the same as in the post. The main difference is using a circular array to keep track of the times instead of a linked list:

                                    l = new Queue()
                                    
                                    def rate_limit():
                                        while l.peek() < now():
                                            l.pop()
                                    
                                        if l.len() > 10:
                                            return false
                                        else:
                                            l.push(now() + 10 minutes)
                                            return true
                                    

                                    In fact, you can replace the while loop with an if statement and it will still work.

                                    1. 1

                                      You’re only allowing one call per minute, you need to allow N calls per minute, but the spirit is the same.

                                      1. 1

                                        There are n calls per minute.

                                        1. 1

                                          Oh I see, n = 10 in this case.

                                    1. 9

                                      if you’re the author, don’t you have a non-twitter link?

                                      1. 3

                                        Not at the moment - I just made it and tweeted about it. However, I plan on putting it under “X in One Picture” series on https://roadmap.sh

                                        1. 2

                                          I posted it elsewhere, for posterity, or something:

                                          https://i.postimg.cc/k9m1CkpF/bigO.jpg

                                          1. 2

                                            I also wondered whether tweets are endorsed here…

                                            1. 4

                                              I think most of the backlash against Twitter is that it’s a poor format for reading long form writing, content is usually light or unsubstantiated (rumors), it’s a redirect to a better primary source.

                                              For the most part, Twitter links do pretty well in Lobster.rs: https://lobste.rs/domain/twitter.com

                                          1. 2

                                            Do we really want the map to be screaming bright red? Red is a very emotive colour. It has meaning. It can connotates danger, and death, which is still statistically extremely rare for coronavirus.

                                            I remember hearing/reading that associating red with danger and violence is a western thing and that other cultures have their own associations. Maybe you could show a different colored map based on the geographic location of the viewer?

                                            1. 3

                                              A common example is in China Japan and Korea, red is associated with fortune so when a stock increases in price, that increase is red, and a decrease is in green. This is opposite of how it’s done in the US.

                                            1. 3

                                              I did a facepalm at the “It turns shadowing from a frequent cause of bugs into something that prevents bugs!”

                                              1. 5

                                                I think it’s really not quite as bad because you have the semantic information through the variable name and a strong type system backing you. There are definitely times where I’m taking the same piece of data but transmuting it over a sequence of types for different reasons like encodings and such and it’s a pain to perform that ceremony of Hungarian notation. If the semantics remain the same and the type encoding is the only difference, maybe shadowing is the right thing, especially with lifetimes.

                                                1. 1

                                                  I think the mentality is, that a variable isnt anIdentifier, but kind of apair (anIdentifier, aType), so repeating the information contained in the type in the identifier is redundant and sometimes even bad, because after a refactoring the type might have changed (from a vector to an iterator for example, etc).

                                                  Of course this shouldn’t be the opportunity to name all local variables x, but it can make sense for a chain of transformations, filtering down a result list for example.

                                              1. 1

                                                Can SIGSTOP be used with similar effect?

                                                1. 2

                                                  PTRACE_ATTACH sends SIGSTOP to this thread.

                                                  http://man7.org/linux/man-pages/man2/ptrace.2.html

                                                  I’m not clear on what the benefits of using PTRACE_ATTACH over SIGSTOP is but I think it’s that you actually get a tracer connection to the thread/process?

                                                1. 12

                                                  What is this? A “news” website that quoted a twitter post with an inline screenshot of an email from a google groups list?

                                                  Here’s a direct link to the email: https://groups.google.com/d/msg/lisalist/aIo6cNu54xM/_Ck_CsmSBgAJ

                                                  1. 5

                                                    Wow, this is going to be cool! One of the biggest gripes I have with both Ruby and Python is that it’s so hard to understand what is happening when your program is no longer making forward progress and your logs just stop. When I try to sample the process, I just get code from the interpreter executing some generic byte code operations. If I’m lucky, the code is calling into some C library or implementation and I can infer where in the code the program has halted or is looping over or is spending most of it’s time.

                                                    1. 3

                                                      Have you tried DTrace? Ruby has been instrumented since 2.0. Most of the popular language runtimes are!

                                                      1. 2

                                                        My vague impression is that Python code “ought” to be easy to pull a stack trace out of, without needing to modify your program, provided you have debug symbols for the interpreter, because you can walk the Python stack automatically in gdb with a script that knows which C functions correspond to bytecode evaluation and which of their local variables correspond to line numbers and function names - see py-bt on https://wiki.python.org/moin/DebuggingWithGdb

                                                        1. 1

                                                          Visual studio made some really impressive stuff for seamlessly switching between c++ and python callstacks. https://docs.microsoft.com/en-us/visualstudio/python/debugging-mixed-mode

                                                        2. 2

                                                          Agreed! One of our Ruby apps has a section that seems far too slow for no apparent reason. Last time I worked on it, I spent a day or so fiddling with profilers, to no avail. Anything that makes that easier is a good thing for the Ruby ecosystem.

                                                        1. 2

                                                          Usually Excellent but sometimes Average. But this is not true for a large number of people I work with. I work at a very large and successful brand name company and I’m 2.5 years out of college.

                                                          Most days call into standup from my car at 10:15. Standup is my cue to start driving to work. I get to one of my work’s parking lot at 10:45 and take 15 minutes to walk the half-mile to my building/office. I work from 11 to noon where I then get lunch until 1. I work until 4 when I get a bit tired and start studying Japanese and Mandarin at the lunch table. I study until 6 where I then either go to my language class or the gym or a sports game. I get home at around 9, chill out, and go to bed.

                                                          Some days I work at home a bit at night or the weekends whenever I feel like I can get some productive work going on something interesting or when the load on our infrastructure is a bit lower and I can take over more of our device fleets.

                                                          Once every three or six months there’s some massive fire where I actually work from home at 9 to 11, go to work, get lunch for an hour, and work until about 6, and do my regular after work debauchery. Then I work a bit from home at night like check my tests, fix some stuff, submit for more tests, go to bed to check them the next day.

                                                          I’ve been very successful in my career working this due to a combination of being the most senior person on my team at 2.5 years, being an extremely efficient engineer because I only allocate a few hours to work a day, and having very clean development. I also hate doing work so I push back on anything I find dumb or a waste of time or doing things that will lead to more work later. I notice a lot of other people even more senior than me fail to communicate issues like this and usually fail to push back on things that make no sense. Many people I work with end up either doing 9-5 but many also do 8-6 or 8-7. I try to get them to stop overworking but they always retort that there’s so much work left. I hate that mentality because there’s always more work to do. I’ve historically had very lenient managers and my newest manager seems to accept the fact with a disgruntled look on his face. But hey, he loves that he doesn’t actually have to manage me and I’m a free spirit who provides strong feedback.

                                                          1. 39

                                                            The argument seems to rely on the cost of static typing, which is stated in the following four points that I challenge:

                                                            It requires more upfront investment in thinking about the correct types.

                                                            I don’t buy this argument at all. If you don’t think about correct types in a dynamic languages, you will run into trouble during testing (and production, when your tests aren’t perfect). You really have to get your types right in a dynamic language too. Arguably, with a statically typed language, you have to think less because compiler will catch your error. I think that’s the whole point of statically typed languages (performance concerns aside).

                                                            It increases compile times and thus the change-compile-test-repeat cycle.

                                                            I’d have to see some proof to show that static typing plays a significant role in compile time. I’ll buy that you can make a very complicated (perhaps turing complete) type system and that would have a big impact. But there are statically typed languages that compile really fast, and most of the compile time is probably not spent on types. I’d argue that it is likely for the compiler to catch your error with types faster than you could compile, run, and test to find the same error with no types.

                                                            It makes for a steeper learning curve.

                                                            That may or may not be true. Sure, a type system can be very complicated. It doesn’t have to be. On the other hand, a dynamic language will still have types, which you need to learn and understand. Then, instead of learning to annotate the types in code, you learn to figure out type errors at run time. Is that so much easier?

                                                            Either way, I don’t believe type systems are an insurmountable barrier. And I think some people give the learning curve way too much weight. Maybe they are working on throwaway software on a constantly changing faddy tech stack, in a place with high employee turnover. It’ll matter more. I suppose there’s a niche for that kind of software. But I’m more into tech that is designed for software that is developed, used, and maintained for years if not decades. A little bit of extra learning up front is no big deal and the professionals working on it will reap the benefits ever after.

                                                            And more often than we like to admit, the error messages a compiler will give us will decline in usefulness as the power of a type system increases.

                                                            That might be the case with the current crop of languages with clever type system, though I don’t know if it’s inherent. Do static type system need to be so powerful (read: complicated) however? A simpler system can get you just as much type safety, at the expense of some repetition in code.

                                                            I think there are dimnishing returns, but not due to the cost of static typing as such, but rather due to the fact that types just don’t catch all errors. Once the low hanging fruit is out, there’ll be proportionally more and more logic errors and other problems that aren’t generally prevented with types. Or you could catch these with extensive type annotation, but the likelihood of preventing a real problem becomes small compared to the amount of annotation required. And then there’s the usual question: who checks the proof?

                                                            There have been some famous bugs that resulted from systems using different units. So if these numeric quantities were properly typed, these bugs would have been prevented. However, what if we change the scenario a little, and suppose we’re measuring fuel or pressure, in the right units. But we read the wrong quantity – spent fuel instead of stored fuel, or exterior pressure instead of interior pressure? Sure you can add more types to prevent such misuse, but it gets more and more verbose, and then you’re moving closer and closer to re-expressing (and thus enforcing) the program logic in the language of the type system; we could consider that to be a language of its own.

                                                            Now you have two programs, and one can prevent bugs in the other, but both could still be buggy. And the other program starts to grow because you start needing explicit conversions to enable the code to actually perform a computation on internal-pressure-in-pascal. Of course you are subverting the type system when you say you really want to convert internal-pressure-in-pascal to just pressure-in-pascal or whatever. Bugs ahoy?

                                                            1. 18

                                                              A simpler system can get you just as much type safety, at the expense of some repetition in code.

                                                              I agree with most of the rest of your comment, but this part is untrue. Stronger type systems do allow you to enforce more powerful laws at compile time. At one end of the curve we have a type system like C’s, which barely buys you anything, and then at the other end we have full dependent types where you can prove arbitrary invariants about your code (this function always terminates, this value is always even, etc.) that you cannot prove in a weaker type system. In between is a huge spectrum of safety checking power.

                                                              1. 8

                                                                The C type system can actually be quite powerful if you wrap basic types in one element structs. struct meter { int v; } and struct foot { int v; } can’t be added by mistake, but can still be worked with using one line inline functions with no performance penalty. It’s just work (which nobody likes).

                                                                1. 5

                                                                  I would not describe that as “quite powerful” at all. That’s one of the most basic things a type system can give you.

                                                                  You can’t really prove any interesting properties until you at least have proper polymorphism. Java doesn’t, for example, because every object can be inspected at runtime in certain ways. In a sensible type system, there are no properties of objects except those which are explicitly stated in the type of the object.

                                                                  In such a type system, you can prove interesting properties like that a data structure does not “depend” in any way on the objects in contains. For example, if you could implement a function

                                                                  fmap :: (a -> b) -> f a -> f b
                                                                  

                                                                  Which “mapped over” the contents of your object with some function, this would prove that your object never inspects its contents and therefore its structure does not depend on the values of its contents (because this function is universally quantified over ‘b’, and therefore you could map every ‘a’ to a constructed type which cannot be inspected in any way).

                                                                  You can prove all sorts of useful properties like this (often without even realize you’re doing it) once you have proper quantification in your type system. One of the coolest quantification-based proofs I know of is that Haskell’s ST monad is extrinsically pure.

                                                                  As you add more power to your type system (up to full dependent types, linear types, etc.) you can prove more and more useful things.

                                                                  1. 2

                                                                    As long as you like all your types disjoint, sure. But I’ll pass.

                                                                    1. 2

                                                                      So what’s wrong with disjoint types?

                                                                      1. 2

                                                                        It doesn’t you have rationals and floats that are both numbers for example.

                                                                        1. 2

                                                                          In Ocaml ints and floats are different types and operators like (+) only apply to ints, one has to use (+.) for floats. It’s not a problem IME.

                                                                          1. 1

                                                                            I think automatic type conversion of ints to reals was the original sin of FORTRAN.

                                                                          2. 1

                                                                            In mathematics the system Z of integers and the system R of reals are different. The number 3 has different properties depending on system context - for example 3x = 1 has a solution in the second context.

                                                                      2. 0

                                                                        But it lacks a keyword connection to category theory.

                                                                    2. 12

                                                                      I don’t buy this argument at all. If you don’t think about correct types in a dynamic languages, you will run into trouble during testing (and production, when your tests aren’t perfect). You really have to get your types right in a dynamic language too. Arguably, with a statically typed language, you have to think less because compiler will catch your error. I think that’s the whole point of statically typed languages (performance concerns aside).

                                                                      That’s a good point and one that took me a long time to learn: if a concept cannot be expressed in a language, it doesn’t magically disappear and absolve the programmer from thinking about it. Types are one example as you mention; similarly, in many discussions about Rust, some people mention that the borrow checker is an impediment to writing code. It’s true that some programs are rejected by the compiler, but lifetime and ownership are also concerns in C programs as well. The main differences are that in Rust you have rules and language constructs to talk about those concerns while in C it’s left to documentation and convention.

                                                                      1. 7

                                                                        But there are statically typed languages that compile really fast, and most of the compile time is probably not spent on types.

                                                                        OCaml is a good example of this.

                                                                        1. 3

                                                                          I don’t buy this argument at all. If you don’t think about correct types in a dynamic languages, you will run into trouble during testing (and production, when your tests aren’t perfect). You really have to get your types right in a dynamic language too. Arguably, with a statically typed language, you have to think less because compiler will catch your error.

                                                                          It’s true that you have to get the types right in a dynamic language, but the appeal of dynamic languages isn’t that you don’t have to think about types. It’s that you don’t have to think about the shape of types. For example:

                                                                          def make_horror_array(depth: int):
                                                                              arr = []
                                                                              deepest_arr = arr
                                                                              
                                                                              for i in range(depth):
                                                                                  deepest_arr.append([])
                                                                                  deepest_arr = deepest_arr[0]
                                                                              deepest_arr.append(depth)
                                                                              return arr
                                                                          

                                                                          What type should that return? Contrived, but it’s not the gnarliest type problem I’ve run into. Sometimes it’s nice to have a language where I can give up on getting the types right and rely on tests and contracts to check it.

                                                                          1. 4

                                                                            It’s that you don’t have to think about the shape of types.

                                                                            How do you use a value without thinking about it’s type or shape?

                                                                            In your example, you can’t just blindly apply numerical operation to first element of that horror array since it might be another array. So, if you wanted to get to the value inside of those nested arrays, you’d need to think about how you would “strip” them off, wouldn’t you? And wouldn’t it mean that layers of nesting have some special meaning for us?

                                                                             

                                                                            Taking your implementation as reference:

                                                                            >>> make_horror_array(0)
                                                                            [0]
                                                                            >>> make_horror_array(1)
                                                                            [[1]]
                                                                            >>> make_horror_array(5)
                                                                            [[[[[[5]]]]]]
                                                                            >>> make_horror_array(10)
                                                                            [[[[[[[[[[[10]]]]]]]]]]]
                                                                            

                                                                            we can write a Haskell version that distinguishes between a value nested in a “layer” and a value by itself:

                                                                            λ> :{
                                                                            λ> data Nested a = Value a | Layer (Nested a)
                                                                            λ>
                                                                            λ> -- just for presentation purposes
                                                                            λ> instance Show a => Show (Nested a) where
                                                                            λ>   show (Value a) = "[" ++ show a ++ "]"
                                                                            λ>   show (Layer a) = "[" ++ show a ++ "]"
                                                                            λ> :}
                                                                            λ>
                                                                            λ> mkHorror n = foldr (.) id (replicate n Layer) $ Value n
                                                                            λ> :type mkHorror
                                                                            mkHorror :: Int -> Nested Int
                                                                            λ>
                                                                            λ> mkHorror 0
                                                                            [0]
                                                                            λ> mkHorror 1
                                                                            [[1]]
                                                                            λ> mkHorror 5
                                                                            [[[[[[5]]]]]]
                                                                            λ> mkHorror 10
                                                                            [[[[[[[[[[[10]]]]]]]]]]]
                                                                            

                                                                            and if we don’t need layers anymore, we can get value out pretty easily:

                                                                            λ> :{
                                                                            λ> fromNested :: Nested a -> a
                                                                            λ> fromNested (Value a) = a
                                                                            λ> fromNested (Layer a) = fromNested a
                                                                            λ> :}
                                                                            λ>
                                                                            λ> fromNested (mkHorror 0)
                                                                            0
                                                                            λ> fromNested (mkHorror 5)
                                                                            5
                                                                            
                                                                            1. 4

                                                                              Assuming it’s correct, it should return whatever the type inference engine chooses for you :)

                                                                              1. 1

                                                                                This is because type theory is confused about what programs do - which is operate on bit sequences (or, these days, byte sequences). These sequences may be representations of mathematical objects or representations of things that are not mathematical objects, but they remain representations, not actual ideal mathematical objects.

                                                                              2. 1

                                                                                Now you have two programs, and one can prevent bugs in the other, but both could still be buggy.

                                                                                Aren’t a lot of type systems proven type-correct nowadays?

                                                                                1. 3

                                                                                  The type system can be fine but the rules you define with the types could be flawed. Thus, you can still write flawed programs that the type system can’t prevent because the types were defined incorrectly.

                                                                                  1. 1

                                                                                    Can you give an example? I’m not sure exactly what breed of incorrect types you’re referring to.

                                                                                2. 1

                                                                                  It requires more upfront investment in thinking about the correct types.

                                                                                  I don’t buy this argument at all. If you don’t think about correct types in a dynamic languages, you will run into trouble during testing (and production, when your tests aren’t perfect).

                                                                                  One thing I am learning from working with inexperienced developers is that even thinking about which container type you are using is a challenge. Should your function return a Seq? An Array? An Iterator? A Generator? And what if your new library returns a Generator and the old one returned an Iterator and now you have to rewrite all your declarations for seemingly no reason at all? Some kind of “most general type” restriction/requirement/tool would help with this…

                                                                                  1. 2

                                                                                    This is one of the things I think Go does really well (in spite of having a generally quite weak type system) - thanks to implicit interfaces, you can just return the concrete type you’re using and the caller will automatically pick up that it ‘fits’.

                                                                                    1. 1

                                                                                      This sort of works – but even with that system, it’s easy to declare one’s types too tightly.

                                                                                      It depends in part on how granular the collection library’s interfaces are (ditto for numeric tower, effects tracking, monad wizard tool).

                                                                                    2. 1

                                                                                      I’m unclear what you mean. Many languages offer two solutions. You can declare the variable IEnumerable or whatever as appropriate. Or you declare the variable as “whatever type the initializer has”.

                                                                                      1. 3

                                                                                        When in doubt, use the inference!

                                                                                        1. 1

                                                                                          It is sometimes easy to choose wrong. Iterable vs Iterator vs Enumerable

                                                                                    1. 5

                                                                                      Is this interesting if it doesn’t have any features to be able to process English and extract semantic understanding rather than just have its own new completely fixed syntax that you have to learn? you may as well just learn the thing you’re trying to do directly instead of the betty syntax…

                                                                                      here is how it matches if you want to count something.

                                                                                      match = command.match(/^count\s+(?:the\s+)?(?:total\s+)?(?:number\s+of\s+)?(words?|lines?|char(?:acter)?s?)\s+in\s+(.+)$/i) ||
                                                                                              command.match(/^how\s+many\s+(words?|lines?|char(?:acter)?s?)\s+are(?:\s+there)?\s+in\s+(.+)$/i)
                                                                                      

                                                                                      .. so with any other natural English syntax other than the fixed ones it’s programmed for, it won’t work.

                                                                                      1. 4

                                                                                        Makes me think of old adventure games.

                                                                                        “Get ye flask.” “You cannot get ye flask”

                                                                                        ..but I agree. It would make more sense to try and use something like NLTK or ParseyMcParseFace. Maybe an idea for future versions?

                                                                                        1. 0

                                                                                          Regex and yacc are the new NLP.

                                                                                        2. 2

                                                                                          That code snippet immediately disappointed me in Betty. I thought it was using a service like https://api.ai/ to match patterns. Could’ve beaten looking up a command on stackoverflow for one-off jobs.

                                                                                          1. 1

                                                                                            Uhm… Would you like to have a tool send all commands to remote host? I agree that the simple text approach is not much different from stackoverflow.com search but sending everything I type to some web service would be a lot worse for me.

                                                                                            1. 2

                                                                                              sending everything I type to some web service

                                                                                              That is what you’re doing when you’re searching on stackoverflow.

                                                                                              1. 2

                                                                                                The other key is “everything I type”. I sanitize my queries to the outside internet pretty thoroughly at my work.

                                                                                                1. 1

                                                                                                  The key is “some web service”. I trust stackoverflow.com with programming questions, and even if I don’t there is a dump of all answers available.

                                                                                            2. 1

                                                                                              Even if it did use some kind of NLP, why would I want this? “OK, Google” misinterprets what I want maybe 25% of the time. Why would I want that kind of ambiguity on the command line. That’s literally why I use a command line, because there is no ambiguity, when I type X, Y happens. Every. Single. Time.

                                                                                            1. 9

                                                                                              I strongly disagree with this from a business standpoint. Sure, MacOS might be better documented by some collaborative effort but it very well may not be supported. Collaborative documentation ends up describing the current state of systems and processes instead of the intended flow. Documentation is a pseudo-contract between consumers and producers where consumers know what to hold producers to and producers know what they must provide to consumers. By pushing the documentation to only the consumer side, you start seeing documentation that solidifies bugs into something people start depending on because that is how it was documented. When that bug gets fixed, all of a sudden, you have nothing to point to that says you were allowed to use it in that way. Fundamentally, it doesn’t solve the problem that there is no support provided by the producing side and we are just pushing the problem a little further down the investment pipeline.

                                                                                              1. 4

                                                                                                The first `demo’ crashed my laptop. I haven’t had to restart my computer in a long time.

                                                                                                1. 1

                                                                                                  Worked for me on my MacBook Pro 2017 in Safari. Pretty impressed that it can take down your system. Probably worth a bug report.

                                                                                                1. 1

                                                                                                  Is it a present-day 0-day that’s been fixed in iOS/Android?

                                                                                                  (For those who haven’t the time to read through all the details of the post?)

                                                                                                  1. 1

                                                                                                    Should be fixed in July updates.

                                                                                                    1. 1

                                                                                                      Should be fixed in July updates.

                                                                                                      What does that mean? July is almost over. Apple did release some security updates recently, are you saying those included fixes to this?

                                                                                                      EDIT: Ah yes, appears they did at the bottom here, CVE-2017-9417.

                                                                                                      1. 2

                                                                                                        https://source.android.com/security/bulletin/2017-07-01

                                                                                                        Also for android. I just double checked my Pixel has this update so it’s distributed and available.