1. 1

    Non-Ruby developer here. Is there any difference between a Ruby yield and just passing in a lambda as an argument?

    1. 2

      Yes, though there are a few aspects in play here. First, a block parameter is a special argument and in order to pass a lambda in as a block parameter you must use the & operator (this operator will attempt to coerce non-proc objects to procs, so this is why symbols are sometimes used in this way).

      When you have a block in ruby, the lifetime of the lexical context is tied to the call-frame that is created upon invocation. This might sound like an implementation detail but it allows the runtime to avoid allocating a proc object to hold the closed over lexical environment (aka. faster and lighter). Generally, if you know you’re receiving a block, it can be an advantage to stick with yield and the implicit parameter rather than pull out the proc as a value and use #call (or an alias of #call like #[]) on the object (this has been optimized more recently in some cases to allow lazy allocation of the object if you only forward it to another call).

      The other difference is around parameter behavior. Blocks and Procs don’t require the arity of the block and the yield to match. So you can take fewer or more arguments than are passed and the extra fields will either be dropped or set to nil. Lambdas however, require the arity to match, much like a method call (distinctly constructed using lambda or -> “stabby” syntax). This can be a good thing but I’ll avoid writing half an article here.

      One more advanced case that many are unaware of, you can capture a proc using the constructor without a block, so these end up working in a similar way:

      def a_is_42(a, &callable)
        callable.call if a == 42 && callable
      end
      
      def b_is_42(b)
        Proc.new.call if b == 42 && block_given?
      end
      

      Of course, it’s a contrived example on the second because we could just use yield there, but it does show that we can build the proc object lazily which can be a big win in some hot paths for Ruby code. There are some more optimization techniques but this gives a little taste of the range of differences between the proc world and the block world. If people are curious, I can write up more about this stuff.

      TL;DR, you can avoid a lot of allocation and call overhead by keeping things in block form.

      1. 1

        That makes sense, thanks!

      2. 2

        The only difference is that your lambda will be an instance of the class Proc which is in charge of storing and executing the piece of code associated to your lambda.

        It’s a bit more complicated than this, but let’s keep it simple if you’re not familiar with Ruby. ;-)

        I invite you to read this article to dive into the specificities of the Proc class and lambdas in Ruby.

        1. 1

          Which article?

            1. 1

              Thanks!

      1. 4

        I just reimage yearly. It also provides good stress testing for my backups.

        1. 3

          I also found that using ripgrep was much faster and easier than using the Visual Studio Code search tool

          Visual Studio Code uses ripgrep to do code search, so you can easily and directly measure how much of the time taken is VS Code overhead, which is pretty interesting to me.

          1. 3

            GVFS relies on a Windows filesystem driver we call GVFlt. Until now, the drop of that driver that we made available was unsigned (because it was very much a work in progress). That clearly creates some friction in trying it out. Today, we released a signed version of GVFlt that will eliminate that friction (for instance, you no longer need to disable BitLocker to install it). Although we have a signed GVFlt driver, that’s not the long term delivery method. We expect this functionality to be incorporated into a future shipping version of Windows and we are still working through those details.

            Interesting. It would be nice if it could work for virtualizing things other than Git, but I’m not holding my breath.

            1. 2

              Update: still only for git, but it looks like it’s no longer only for Windows: https://arstechnica.com/gadgets/2017/11/microsoft-and-github-team-up-to-take-git-virtual-file-system-to-macos-linux

            1. 4

              I wrote the compiler used internally by mumble company for their mumble language targeting their mumble product.

              That compiler had plenty of bugs. :)

              And one time (at a different company) we were having an issue with database updates to a SQLite database bizarrely failing in random circumstances. Turns out we found a bug in SQLite.

              1. 7

                “Turns out we found a bug in SQLite.”

                Holy shit.

                (For those not aware of SQLite’s reliability, this article is might interesting: https://www.sqlite.org/testing.html)

                1. 5

                  This was the bug:

                  http://www.sqlite.org/src/info/6bfb98dfc0c

                  Found by an engine generated by this:

                  https://github.com/deadpixi/giles

                  which produces some hairy SQL.

              1. 10

                The long mug and wide teapot actually go together fairly well. They’d make a fun novelty set.

                1. 1

                  But how would you drink from the long mug?

                  1. 10

                    Carefully.

                1. 1

                  I tried OCaml for a bit but the weirdness got to me after awhile. There was a ton of magic around project setup and compilation that I didn’t understand and couldn’t find properly explained, and the fact there is more than one “standard” library bugged the heck out of me. I’m hoping that once the Linux story solidifies a bit more around .NET I’ll be able to reasonably give F# a shot.

                  1. 3

                    I’ve been using F# on Linux for a few years now using Mono. It’s a bit more manual than .NET Core, but it’s stable.

                    1. 3

                      If you’re interested in trying again, I created a build system (yes, yet another one) specifically designed for getting going fast in most cases. I have a blog post here:

                      http://blog.appliedcompscilab.com/2016-Q4/index.html

                      Short version: all you need is a pds.conf which is in TOML so fairly straight forward, a specific directory structure (src/<project>) and GNU Make. Then you run pds && make -f pds.mk and you’re done. Supports tests as well as debug builds.

                      1. 5

                        I’m not sure it is worth pushing yet another build system that seemingly nobody uses (at least I haven’t yet run across a package which uses it) when jbuilder seems to be gaining so much momentum in the OCaml world lately.

                        1. 3

                          Maybe, but pds is pretty easy to port away from for most builds and it’s so trivial to get started and much less confusing than jbuilder’s config, IMO. My personal view is that jbuilder is a mistake but I’ll wait to switch over to it once it’s gained enough momentum. At that point, I can just switch pds over to producing jbuilder configs instead. But I’m a symptom of the problem rather than the solution unfortunately. I also use @c-cube’s containers, so yet another stdlib replacement/extension :)

                          1. 4

                            My personal view is that jbuilder is a mistake

                            Could you elaborate on why? IMO jbuilder is not perfect either but if we get a modern, documented build system which is hopefully easy to setup, it would be a massive win over all the other solutions we currently use.

                      2. 1

                        I agree, the different choices in tooling is sort of disorienting and it can lead to analysis-paralysis. For a toy compiler project I started working on, I tried to find the most basic tooling that would work: whatever ocaml compiler came with my distro, ocamlbuild, make, and then eventually, extlib, ocpindent, and then after some more time, opam, ocamlfind, utop. It may make sense to use the tooling outlined in this article if future maintainability is a big concern, but to get started and to learn ocaml, I don’t find it necessary (and definitely not appealing). Having done this, I don’t pine so much for standardization (;

                        1. 1

                          There’s more than one standard library in a lot of languages, though. Why does that bother you?

                          1. 4

                            It bothers me because it makes the language more difficult to learn. It also wasn’t always clear to me that an alternative was in use because, IIRC, they’re not (always) clearly namespaced. I have run into this in Haskell as well, FWIW.

                            1. 2

                              Typically it’s visible when you use an alternative stdlib because you start your files with open Batteries or open Core or open Containers. I agree it’s annoying that the stdlib is not richer, and it’s a bit slow to accept contributions, but in a way the existence of alternative stdlibs/extensions shows how easy it is to roll your own :-)

                            2. 4

                              You can’t have two standards, that’s a double standard!

                              1. 1

                                Which languages?

                                1. 1

                                  Haskell, C, and D come to mind. You could also argue that Python has multiple standard libraries because it has different implementations that effectively can’t use some aspects of the normal stdlib (PyPy). Then there’s Java: SE, EE, and ME are the same language with different sets of functionality in the standard libraries.

                              2. 1

                                Out of curiosity, have you tried OP’s project setup?

                                Also, there is only one OCaml standard library–the one that comes bundled with OCaml. The other ‘standard libraries’, Batteries Jane Street’s Core, are optional add-ons made for specific purposes.

                                1. 2

                                  I haven’t tried OP’s setup, but honestly it seems even worse than what I had. I pretty much followed this: https://ocaml.org/learn/tutorials/get_up_and_running.html. I ended up using Oasis, which was just awful, every time I added a file or dependency I had to fiddle with the config until everything would build again, but at least there wasn’t an entirely separate language.

                                  From OP:

                                  (jbuild_version 1)
                                  
                                  (executable
                                    ((name main)                 ; The name of your entry file, minus the .ml
                                     (public_name OcamlTestProj) ; Whatever you like, as far as I can tell
                                     (libraries (lib))))         ; Express a dependency on the "lib" module
                                  

                                  Note the comment, “as far as I can tell”. To me, that’s a terrible sign. A person who has gone to a reasonable amount of effort to explain how to set up a project can’t even figure out the tooling completely.

                                  1. 2

                                    Jbuilder is quite nicely documented (see http://jbuilder.readthedocs.io/en/latest/). The public_name defines the name of the produced executable in the install context. It does not take much effort to read it from there

                                    1. 2

                                      Of course you still have to find out that Jbuilder exists, which the official site doesn’t seem to mention… I am lazy, I don’t like choices, I just want one, blessed tool that works more or less out-of-the-box if you follow a set of relatively simple rules (I’m even OK with wrapping the tool in a simple, handwritten Makefile, which is what I do in Go). I’m not arrogant enough to think that the way I prefer is the “right” way, in fact in some cases it would be dead wrong (like for extremely complex, multi-language software projects), but that explains why I dropped OCaml for hobby stuff.

                                      1. 1

                                        OK, but your criticism is that you have to find out that JBuilder exists, commenting on a post that tells you about JBuilder.

                                        1. 1

                                          To be fair, jbuilder is very young (not even 1.0 yet actually) but it might become the “standard” build tool the OCaml community has been waiting for for years (decades?). Then clearly there will be more doc and pointers towards it.

                                          1. 1

                                            Well obviously I know about it now, but it still isn’t terribly discoverable for someone new to the language. My actual point, and I probably didn’t make this as clear as I should have, sorry, is that in my experience OCaml isn’t very friendly to beginners, in part because its tooling story is kind of weak and fragmented.

                                            1. 2

                                              Yeah. This is true. Especially on Windows. People are working on it but it’s slow and it’s taking time to consolidate all the disparate efforts. I myself am not getting terribly excited about OCaml native but funnily enough I am about BuckleScript (OCaml->JS compiler) because of its easy setup (npm i -g bs-platform) and incredible interop story.

                                              Others are getting equally into ReasonML ( https://reasonml.github.io/ )because it’s coming from a single source (Facebook) is starting to build a compelling tooling/documentation story.

                                              1. 2

                                                I didn’t know about either of these, thanks!

                                      2. 1

                                        OP here: I didn’t really make any effort to pursue documentation re: the public_name field, and I have really almost no production experience with OCaml whatsoever. I certainly have complaints about OCaml’s tooling, but I can assure you that any argument against it appealing to my authority is certainly flawed.

                                        1. 1

                                          I wasn’t really appealing to your authority, in fact kind of the opposite. I don’t like using systems that converge to copy-paste magic, and that seems to be what you did, and is likely what I would do. I don’t want to use a weird programming language to configure my project, I want something simple, with happy defaults, that can be understood easily.

                                          I guess I generally prefer convention over configuration in this case, and that doesn’t seem to be what the OCaml community values, which is why I gave up on it. I’m not saying anyone is right or wrong, it’s just not a good fit for me, particularly for hobby projects.

                                  1. 1

                                    This usage of the else keyword seems like an occasional useful but of semantic sugar, but dang, could they have at least chosen a different keyword? The word “else” makes absolutely no sense here! Fully exhausting a for loop doesn’t seem like an “else,” that seems like the normal usage of a for loop. In my opinion, it should have been called something like “then” to make it clear that it’s a continuation. Before I read this article, I assumed that the else keyword after a for loop would only execute if the loop never ran.

                                    1. 3

                                      The most common use case is searching for a particular value using the for loop. If found, a break is then executed and the else block is skipped. If no value is found, the else block is executed. This makes “else” make a little more sense as the keyword.

                                      1. 3

                                        Think of for/else like an if statement where the condition is evaluated multiple times. It’s basically just a more expressive version of:

                                        if any(c for c in conditions):
                                            # at least one condition is True
                                        else:
                                            # no condition is True
                                        

                                        In your mind, just replace for with if and it makes a sort of sense.

                                        1. 2

                                          I can’t seem to find a link, but I vaguely remember Guido remarking that he wishes he’d named it “nobreak”, which makes a lot more sense for me.

                                          1. 1

                                            Python is unfortunately heavy with syntax. Expressing for/else in a language like Haskell, Ocaml, and I assume Rust, is something more likely (and easily) done in a library.

                                          1. 38

                                            I know of a situation where a Red Team member broke an engineer’s car window to steal their laptop.

                                            Jesus Christ. Are pentesters not legally liable for stuff like this? The article describes this as a grey area, but this seems downright criminal.

                                            In one of those cases, the pentester did this repeatedly (about a half-dozen times), to the point that the staffer thought she was being stalked and called the police. She later quit; the company’s lucky she didn’t sue.

                                            For fuck’s sake. Again, this behavior isn’t inappropriate: it’s illegal (or at the very least borderline so).

                                            These are just useless and uninteresting results. I don’t have to pay for a pentest to know that my organization is vulnerable to phishing attacks, because all organizations are vulnerable to phishing attacks. And if “employees can be phished” is the finding I’m trying to remediate, well, that’s not a risk that can really be effectively addressed.

                                            This is wonderfully put.

                                            (As a bonus, this technique also simulates insider threats, and the remediation you’ll do helps protect against them, too.)

                                            Didn’t even think about that. This article is fascinating.

                                            1. 16

                                              yeah you could just telllll the business, “Hey I saw the laptop in the car, someone could break a window and grab the laptop”

                                              1. 11

                                                They are fully liable unless the legal framework was set (which in no way happened in the window breaking case), and often times the clients don’t really understand what they are signing up for nor do they actually seem to care until the bad things start to happen. I’m not defending that shitty pentest group, because they should be shamed, but sometimes I’ve had clients not understand what they adamantly declare that they need for a pentest. For example, I had a client sysadmin who wanted an external and internal pentest, but only gave me the info for the external hosts. After stepping him through the ROE and making him understand clearly that he was keeping the scope for internal infrastructure fully open and what that would mean we got the ball rolling. After cracking the perimeter it was a massacre. We stepped him through our process with updates along the way and he was enraged when we got domain admin. It’s not the first time I’ve seen the “they won’t be able to get in, so I’ll just make this ROE draft easy on myself and doing it as lazily as possible”. Some people just don’t take it seriously.

                                              1. 5

                                                Is this really fuzz testing? It feels more like property-based testing, since you’re comparing outputs at the end instead of just making sure that your test didn’t crash.

                                                1. 1

                                                  In the article, he or she equates the two - what is the difference you know of?

                                                  1. 4

                                                    They might be similar when stating the property or whatever to check the output. In general, though, the basic concepts are opposite on input side. In property-based testing, we keep the test generation close to what the developer specifies trusting their intuition to find the issues in the implementation of that specification. When fuzzing, we assume the developer might have the wrong specification in mind and the program might have issues. That’s why the input is really random (i.e. unconstrained vs property-based).

                                                    Empirical evidence shows both get results with them sometimes getting different results. We still don’t fully understand where we can predict which method is good enough. The great thing is it’s cheap to do both. So, that’s the current recommendation in even medium-assurance systems where verification costs still must be low. Just do both. And if you have spare cycles, throw other forms of automated testing or analysis at anything that passed those two just in case something turns up.

                                                    1. 2

                                                      Unlike fuzzing, property-based testing has shrinking – if a PBT library’s input generation finds any failures, it has built-in heuristics for generating simpler variants on that input. That way, it can turn a random failure with lots of irrelevant detail into nearly minimal input to reproduce the bug.

                                                      1. 3

                                                        Widely-used fuzzers (eg AFL) also do this.

                                                        1. 2

                                                          In afl-fuzz’s case, it’s because it’s instrumenting the executable to measure branch coverage.

                                                          There’s overlap, but fuzzing and property-based testing seem to be coming from different directions and meeting in the middle.

                                                  1. 5

                                                    This is a decent enough Graphs 101, but I was expecting it to have more actual problems that can be solved by graphs.

                                                    1. 5

                                                      One thing I rarely see called out in these logging posts: log messages should either contain file name and line number or they should be something unique enough to be greppable. It should never take more than a few seconds to go from a log line to the place it was logged from, because there’s no telling how well the on-call reading this logs knows your service and being able to look at the log right next to the code is immensely useful.

                                                      1. 3

                                                        In particular, there is a special Hell for anyone who makes two different lines of code both log exactly the same error message with different root causes no way to distinguish which occurred.

                                                        This special Hell is called having to debug something which you made ambiguous on purpose.

                                                      1. 7

                                                        i tried. i really wanted to like it, but the tooling and dev environment under linux is still pretty miserable, and to make matters worse, all the blog posts and tutorials seem to assume you’re using visual studio.

                                                        (if someone wants to play with it, i started a project to make life a little easier)

                                                        1. 3

                                                          We’re an F# shop, and we have 1 guy learning F# using VS Code / Ionide in Linux exclusively. Frankly, he is kind of struggling without the good debugger in Visual Studio. Ionide has the advantage of being “light weight”, and I use it daily for some purposes, but the debugger and better intellisense in full VS just make the experience so much better.

                                                          1. 3

                                                            Is the project targeting Mono or .NET Core? If they’re using Mono, there’s a plugin that provides decent (but admittedly not amazing) support for the Mono debugger.

                                                            1. 1

                                                              Mono. Thanks, I’ll mention that to him.

                                                        1. 3

                                                          This is good, but I really wish there were more “why F#” tutorials that weren’t aimed at C# developers.

                                                          1. 1

                                                            Yeah it’s really tragic that Microsoft really doesn’t seem to get how good F# is. They treat it like a toy they can pitch to C# devs.