Posts

  • Weird Ruby: Single-quoted Heredocs

    By default heredocs in Ruby behave like double-quoted strings when it comes to interpolation and escape characters:

    land = 'Mordor'
    
    verse = <<-TEXT
    One Ring to rule them all,
    One Ring to find them,
    One Ring to bring them all,
    and in the darkness bind them,
    In the Land of #{land} where the Shadows lie.
    TEXT
    
    # => "One Ring to rule them all,\n" +
    # "One Ring to find them,\n" +
    # "One Ring to bring them all,\n" +
    # "and in the darkness bind them,\n" +
    # "In the Land of Mordor where the Shadows lie.\n"
    

    There’s a way to suppress this behavior and make heredocs behave like single-quoted strings, but it’s a little bit… weird:

    land = 'Mordor'
    
    verse = <<-'TEXT'
    One Ring to rule them all,
    One Ring to find them,
    One Ring to bring them all,
    and in the darkness bind them,
    In the Land of #{land} where the Shadows lie.
    TEXT
    
    # => "One Ring to rule them all,\n" +
    # "One Ring to find them,\n" +
    # "One Ring to bring them all,\n" +
    # "and in the darkness bind them,\n" +
    # "In the Land of \#{land} where the Shadows lie.\n"
    

    This works for both normal and squiggly heredocs (<<~). Notice that you have to put only the opening delimiter within single quotes.

    That’s all I have for you today! Keep hacking and keep Ruby weird!

    Articles in the Series

  • A Modular RuboCop

    Last year at RubyKaigi I spoke about the past and the future of RuboCop. This talk marked the birth of the RuboCop HQ organization and the first time I spoke about RuboCop 1.0. There were 3 primary areas of work I outlined for RuboCop 1.0 back then:

    • Safe auto-correct (that doesn’t break your code)
    • Safe upgrades (that don’t introduce new offenses)
    • Modular design

    We’ve already made a lot of progress on the first point and I wrote about that a while ago. Safe upgrades are currently in the works and I expect we’ll wrap them up fairly soon.

    Today I’m going to focus on modular design. What do I mean by modular design? Historically RuboCop has bundled Ruby style checks, Rails style checks and performance checks. This worked out well for a while, but as the project grew bigger and more popular the number of the checks in each department skyrocketed and it became harder and harder to keep track of everything. There’s also the fact that the Ruby style checks are fairly stable, but the Rails and performance ones are constantly in flux, as many of them are relevant only to specific versions of Rails and the Ruby runtime. Naturally, there’s also the problem of not being able to release updates to Rails or performance checks independently of RuboCop itself. For me it had become clear that we were way past the point of the “majestic monolith” and we had to take some measure to prevent things from escalating any further.

    So, what are we doing about all of this? The solution is pretty simple - we’ve decided to break the original RuboCop into 3 gems:

    RuboCop Performance went live recently, and in RuboCop 0.68 we’ve removed all performance cops from RuboCop. Today I’m happy to announce the inaugural release of RuboCop Rails! RuboCop 0.71 will issue a warning about the pending removal of Rails-related cops from the core project and they will be deleted in RuboCop 0.72. Note that the initial version of the rubocop-rails gem is 2.0. It might seem a bit odd, but there’s a good story behind this. You are advised to switch to the new gem right away - it will take precedence over the Rails cops bundled with RuboCop itself. The core project will stop updating the Rails cops that are part of it effective immediately.

    This announcement is the culmination of an entire year of hard work by the amazing Koichi Ito, who spearheaded the extraction of both the performance and the Rails cop departments. Going forward Koichi will be the primary steward of the new gems, while I’ll keep my attention mostly on the core project. I’ve long wanted to focus more on improving RuboCop’s internal, performance and default configuration, and I hope my reduced responsibilities will allow me to spend more time ruminating on how to build a better RuboCop core experience.

    The extraction process had one nice side effect - it helped us improve RuboCop’s internals and provide a better extension API in general. There’s a lot of work left on the extension API front, but things are certainly moving in the right direction. The RuboCop ecosystem has been steadily growing for the past several years and I hope that soon we’re going to see more great additions to it (e.g. rubocop-minitest, rubocop-hanami, etc). Fingers crossed!

    I know this transition means another (somewhat) painful upgrade for some of you, but I promise you that the pain is going to be worth it. We’re now at a striking distance from RuboCop 1.0 and the era of stability it should bring. I’ll write a bit more on that subject in the weeks to come. That’s all I have for you today! Keep hacking!

  • Meta Reduce, Volume 2019.2

    About a month has passed since the last “Meta Reduce” update I wrote. I’ve kept pretty busy in the mean time and now I have quite a few things to share with you. Where do I begin…

  • Hard CIDER: REPL Shortcuts

    One common struggle people have with CIDER (and Emacs in general) is that there are way too many keybindings to remember, and some of them require pressing a lot of keys. While there are many ways to address those common problems in Emacs, today I’ll focus on one that’s really simple and CIDER specific.

    CIDER’s REPL provides a neat trick inspired by SLIME - REPL shortcuts. They are extremely easy to use - just press , while at the REPL prompt and you’ll get a completing read allowing you run one of the CIDER commands that are bound to REPL shortcuts. Let’s now revisit tidying up our REPL in the context of REPL shortcuts, so you can get a better idea of how this actually works:

    CIDER REPL Shortcuts

    Note that this example uses the ivy library to display the list of commands that are available. You’ll get different visuals if you’re using some other minibuffer completion library (e.g. ido or icomplete).

    If you don’t like using , as the trigger key you can change it to some other key easily. Just put this in your Emacs configuration:

    (setq cider-repl-shortcut-dispatch-char ?\!)
    

    The above example changes the trigger key to !. Be careful what you set here, as it shouldn’t be something with which a Clojure form might start. If you selected ', for instance, you’ll have a really hard time entering quoted forms in your CIDER REPL.

    There are many commonly used commands that are bound to REPL shortcuts out-of-the-box. You can examine them by selecting help after pressing ,. The shortcuts functionality is user-extensible and you can easily add more commands there:

    (cider-repl-add-shortcut "clear-output" #'foo-cmd)
    (cider-repl-add-shortcut "clear" #'bar-cmd)
    (cider-repl-add-shortcut "clear-banners" #'baz-cmd)
    

    That’s all I have for you today. Simple, sweet and maybe even useful! Keep hacking!

  • Hard CIDER: Keeping your REPL Tidy

    Only one of the following two statements is correct:

    • Working with CIDER is hard!
    • Hard cider is the best cider!

    I’ll let you decide which one yourselves.

    “Hard CIDER” is a new blog series dedicated to demystifying the dark art of using CIDER effectively and convincing you that the second statement is the correct one. I was thinking that a more appropriate name for the series might have been “Effective CIDER” or “A Pint of CIDER”, but I’m not a particularly appropriate person. And naming is hard!1

    Here we go…

    The Problem

    CIDER’s REPL buffer is known to experience slowdowns when a lot of output accumulates in it. That’s not a CIDER-specific issue, but more like a general Emacs issue. We’ve tried hard to tune the REPL’s performance in CIDER 0.21 (New York), but it would still grind to a halt if you dump a few megabytes of output in it.

    I’ve noticed that many CIDER users would simply restart either CIDER or Emacs when faced with this issue, but there are a few small simple steps you can take to mitigate the problem.

    The Solution

    Clear the Most Recent Output

    If you happen to evaluate something that produced a huge result or a lot of console output there’s a very simple solution to that. Just press C-c C-o (or M-x cider-repl-clear-output). Running the command in this REPL:

    ;; That's not going to end well...
    user> (take 5000000 (repeatedly (fn [] "Emacs Forever!")))
    ("Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     "Emacs Forever!"
     ;; Five more million lines of output
    user>
    

    Will result in:

    user> (take 5000000 (repeatedly (fn [] "Emacs Forever!")))
    ;; output cleared
    
    user>
    

    An epic mistake has been undone and your REPL is back to normal!

    Note: This command will remove both the value produced by the last evaluation plus any console output that originated from it.

    Clearing the REPL Completely

    From time to time it’s a good idea to just clear your REPL buffer completely. CIDER naturally has a command for that - C-u C-c C-o (M-x cider-repl-clear-buffer). I usually run it every few hours, as I rarely care much about things I’ve evaluated a while ago (plus I can easily retrieve them from the REPL history).

    This command nukes everything in the REPL buffer and resets it to pristine brand-new state. It’s the ultimate recipe to combat REPL sluggishness.

    Interrupting Evaluations

    If you notice that some evaluation is producing a lot of output it’s usually best to kill it right away, instead of waiting for the output to cripple your REPL. Let’s revisit this example:

    ;; That's not going to end well...
    user> (take 5000000 (repeatedly (fn [] "Emacs Forever!")))
    

    Your best course of action after seeing that the result is huge is to press C-c C-c (M-x cider-interrupt). That way you’d get only a few hundred (thousand) lines of output instead of 5 million.2 Typically I’ll follow such an interrupt with C-c C-o to clear the partial output, which may still be fairly substantial.

    Epilogue

    That’s all I have for you today. Hard CIDER is off to a simple start! I might add some short screencasts and animated gifs to future episodes, but I won’t be making any promises. The format is brand new and it will take me a while to find the optimal recipe for it. Your feedback will be instrumental in that process!

    Until next episode! In the mean time - keep hacking!

    1. Just like good cider. 

    2. It all depends on your reflexes and your hardware. 

  • Weird Ruby: Double Negation

    Welcome to another installment of the “Weird Ruby” series! Today we’re going to continue exactly where we left off last time. In other words - we’re going to discuss this bit of slightly weird Ruby code:

    !!foo
    

    This is a somewhat popular idiom to convert a value to a boolean (true or false).1 Believe it or not the idiom is known as “double negation”. Let’s take a look at how this behaves:

    !!10
    # => true
    
    !!true
    # => true
    
    !!false
    # => false
    
    !!nil
    # => false
    

    There’s nothing really special about the code once you know that ! is just a regular method in Ruby. Double negation is nothing but a syntactic sugar for:

    foo.!.!
    

    It’s important to understand that !! are just two negations combined and not some special operator. I’ve seen people confused about this, so I wanted to highlight it here.

    Another source of confusion about double negation is that in some programming languages you can’t use ! with non-boolean values:

    // Java
    // syntax error
    var foo = 5;
    !!foo;
    
    // double negation works only for boolean values
    // which renders it useless
    var foo = true;
    !!foo;
    

    So, now we understand how !! works, but you might be wondering if it’s any useful. After all, we know that in Ruby every object except false and nil is logically true (a.k.a. truthy). This means it’s unlikely we’ll need to convert objects explicitly to boolean values. Just consider this trivial example:

    # redundant conversion
    do_something if !!foo
    
    # idiomatic Ruby
    do_something if foo
    

    In practice there’s just one place where we really want to convert something to a boolean and that’s the return value of predicate methods. While it’s not strictly mandated by Ruby, there’s a strong convention that a predicate method should return true or false and the !! trick is useful there:

    def awesome?
      # ...
      !!result
    end
    
    # an alternative approach
    def awesome?
      # ...
      !result.nil?
    end
    

    I’ve never had any issues writing !foo.nil?, so I rarely use !!, but the option is there if you need/like it.

    This discussion reminded me that it would have been nice if Ruby had a to_bool method or something like this. Something as simple as:

    class Object
      def to_bool
        !!self
      end
    end
    
    5.to_bool
    # => true
    
    nil.to_bool
    # => false
    

    Simple enough, but probably an overkill given the limited usage of “real” boolean values in Ruby.

    That’s all for today! I hope it was weird and useful enough for you! Keep hacking!

    Articles in the Series

    1. This idiom is also popular in the JavaScript world. 

  • Weird Ruby: Positive and Negative Strings

    Recently I saw the following Ruby code:

    content = +"\n"
    content << "## #{title}\n"
    content << "\n"
    content
    

    My initial reaction was WTF! The + before "\n" seemed like some potential typo to me. A moment later I was enlightened and I told myself - “Wow! That’s weird enough for Weird Ruby!”. And here we are:

    Turns out that when frozen string literals were introduced in Ruby 2.3 a couple of unary methods were added to the String class - namely unary + and -. They made it possible to have “positive” and “negative” string literals. What does this mean exactly? Let’s figure this out together!

    Positive Strings

    Let’s first take a look at String#+@. Here’s its description from the official API docs:

    If the string is frozen, then return duplicated mutable string. If the string is not frozen, then return the string itself.

    Simple enough, right? Here are a couple of examples to help illustrate this:

    # frozen_string_literal: true
    
    foo = "string"
    foo.upcase!
    # => FrozenError - can't modify frozen String
    (+foo).upcase!
    # => "STRING"
    

    What’s the practical application of this weird notation? I think the number one usage would to be to give you an unfrozen string that you can use as the receiver for mutating string methods (e.g. concatenation):

    # frozen_string_literal: true
    
    # Doesn't work because you can't modify a frozen string literal
    content = "\n"
    content << "## #{title}\n"
    content << "\n"
    content
    
    # Common workaround
    content = "\n".dup
    content << "## #{title}\n"
    content << "\n"
    content
    
    # The new method in action
    content = +"\n"
    content << "## #{title}\n"
    content << "\n"
    content
    
    # A non-destructive alternative
    content = "\n"
    content += "## #{title}\n"
    content += "\n"
    content
    

    You’ll be the judge of how useful this is for you. Concatenation is obviously more memory efficient, but in simple scenarios you don’t gain much by using it.

    Negative Strings

    Now, let’s turn our attention to String#-@. Here’s its description from the official API docs:

    If the string is frozen, then return the string itself. If the string is not frozen, return a frozen, possibly pre-existing copy of it.

    And here are a few examples:

    foo = "string"
    foo.upcase!
    # => "STRING"
    (-foo).downcase!
    # => FrozenError - can't modify frozen String
    

    Generally, I don’t think you’ll find any use for it if you’re leveraging the frozen_string_literals pragma, but it’s an useful shorthand to freeze a string otherwise.

    Closing Thoughts

    A word of caution - the positive and negative string literals result in code that’s pretty weird, so you should use them sparingly.

    Until next time! Keep hacking!

    Articles in the Series

  • Always be Closing

    One of the biggest mistakes that an open-source project maintainer can do is to allow the backlog of their projects to grow to a size where it’s unmanageable. That something I’ve seen many times and it always happens in more or less the same fashion, and leads to more or less the same result.

    You start a small personal project driven by your own interests and needs. The scope of the project is tiny at the time - just a handful of features, no plans for world domination. At some point the project gains some traction.1 Users (understandably) start reporting bugs that you never encountered and requesting new features you never envisioned. You’re excited that someone found your small hobby project useful and you are eager to oblige and expand the scope to keep the new users happy. If you’re extra lucky2 you start receiving lots of pull requests from contributors who are willing to help move the project forward. World domination is at hand!

    Fast forward a few years into the future. Unless by some miracle you’ve got all the free time in the world or your project became your full-time job, you’re probably facing now hundreds of open tickets and dozens of open pull requests. No matter how hard you try you can never manage keep up with them. And you try really hard. You’re so busy these days that you can’t even keep up with the contributions you’re getting, let alone find some time to trim the backlog, label tickets accordingly, respond to everyone and handle a couple of tickets yourself.

    And in those rare moments you find some time to peruse the backlog, so you can pick some tickets for yourself, you’re just getting depressed by its sheer size (e.g. 100+ open tickets) and you don’t know where to begin. You spend all of your time considering which ticket to start working on and then you’re out of time. No progress. Lots of frustration.

    I happen to be the steward a few somewhat popular projects and I’m saying all of this from experience. I know that focus in the key to success in everything, but I’ve been finding it harder and harder to find my focus when it comes to OSS projects, as so much work has piled on my plate there that I constantly wonder where to begin. Time to make some changes.

    Yesterday I’ve decided to enable a bot that automatically flags stale issues and pull requests on my major projects (e.g. RuboCop, CIDER, Projectile) after a certain period of inactivity and closes them later if they remain dormant. I always feel bad when I’m closing valid bug reports and interesting feature requests, but I think it’s much more important to be realistic about what’s actually feasible versus relying on wishful thinking and giving fake promises. If a ticket is not handled in a reasonable amount of time that usually means two things:

    • Probably it’s not something super important.
    • It’s unlikely that it will ever be handled (lack of bandwidth, the maintainers don’t feel it’s particularly important, it’s something super complicated, etc).

    I’ve noticed that really important topics always tend to resurface and there’s always someone willing to tackle those. That’s why I’m not particularly worried about something major slipping between the cracks, when relying on an automated ticket clean-up strategy.

    I hope that the outcome of this experiment is going to be a clean and focused roadmap for my projects resulting in better pace of development and happier users in the end of the day. Time will tell. At least I’m glad that I’ve finally tried to beat the vicious cycle I was trapped in, as you know what they say about people who keep doing the same things expecting different results…

    Never forget that “less is more”. Keep closing!

    1. No users, no problems. 

    2. Or unlucky, depending on your perspective. 

  • Weird Ruby: Pure Object-Oriented Negation

    I’m kicking off a new series of posts dedicated to some fun and weird aspects of our beloved Ruby programming language. I was torn apart between “Fun Ruby” and “Weird Ruby” for the name of the series, but I’ve opted for the latter for no real reason.

    Today we’re going to talk about object-oriented negation, which probably sounds rather weird, right? Let’s start with something familiar. In Ruby negation typically looks like this:

    !something.foo
    not something.bar
    

    Pretty straightforward stuff - you just use one of the negation operators ! or not and you’re in business. But are they really negation operators? Well, not certainly is, but ! is actually a rather ordinary method defined in the not so ordinary BasicObject class.

    # Try these expressions in a Ruby REPL like irb or pry.
    method(:!)
    # => #<Method: main.!>
    
    method(:!).owner
    # => BasicObject
    

    BasicObject is at the root of Ruby’s class hierarchy, which means that methods defined in it are available in every Ruby class. Which leads us to the twist - you can actually do negation in Ruby as a regular method call:

    something.foo.!
    # double negation
    something.bar.!.!
    
    (x == y).!
    (x == y).!.!
    10.!
    

    Admittedly that looks extremely weird, and it’s pretty easy to misread such code as foo! or 10 factorial. I’m certainly not advocating that someone should be writing such code - quite the opposite actually.1 Still, it’s fun how Ruby’s purely object-oriented nature exposes in a uniform manner functionality that’s usually special in most programming languages. Of course, most operators in Ruby are actually regular methods (e.g. +, -, ==, !=, etc) and this gives us as programmers the flexibility to redefine them for particular classes. Now let’s abuse this knowledge to make 10.! compute factorial for real:

    # Don't do this at home!
    class Integer
      def !
        (1..self).reduce(:*)
      end
    end
    
    5.!
    # => 120
    
    !5
    # => 120
    

    Remember that writing code like this is a bad idea in general, but it’s cool that the option exists.

    Note that !something and something.! are completely identical as far as Ruby is concerned. Ruby has some special provisions2 for unary and binary operator methods that allow for using them with a more human-friendly (math inspired) notation:

    something.foo.!
    !something.foo
    
    5.+(5)
    5 + 5
    
    x.==(10)
    x == 10
    
    x.<(5)
    x < 5
    

    That’s all I had for you today! I hope it was weird enough, fun and not totally useless! Keep hacking!

    Articles in the Series

    1. We should probably add a rule in the community Ruby style guide to advise against writing such code. 

    2. Many people call this “syntax sugar”. 

  • Discovering Runtime Function References in Clojure

    Cognitect recently released a new version of REBL that has a cool “find function references (usages)” feature. Rich was kind enough to answer some questions about the new feature’s implementation on Slack, and he even shared one central bit of it - namely the fdeps function that discovers the runtime dependencies of any function:

    (defn fdeps [val]
      (set (some->> val class .getDeclaredFields
                    (keep (fn [^java.lang.reflect.Field f]
                            (or (and (identical? clojure.lang.Var (.getType f))
                                     (java.lang.reflect.Modifier/isPublic (.getModifiers f))
                                     (java.lang.reflect.Modifier/isStatic (.getModifiers f))
                                     (-> f .getName (.startsWith "const__"))
                                     (.get f val))
                                nil))))))
    

    How does this work in practice? Here’s a simple example:

    (defn foo []
      (map inc (range 10)))
    
    (fdeps foo)
    ;; => #{#'clojure.core/map #'clojure.core/range #'clojure.core/inc}
    

    Basically, you get a set of all the vars that are used (depended on) in the body of the target function. There are few things to keep in mind:

    • This function relies on Clojure implementation details (although it’s unlikely those are going to change).
    • You’re relying on runtime information, which means the function you’re analyzing must be loaded and you won’t see inlined functions or macros.
    • fdeps operates on function values, not vars or symbols (although it’s trivial to make it more generic).
    • You’ll get only the direct dependencies of the function. In other words - you won’t get any transitive dependencies (including the dependencies of nested lambdas).
    (defn bar [x]
      (map #(+ % 1) (range 10))
    
    (fdeps foo)
    ;; => #{#'clojure.core/map #'clojure.core/range}
    ;; Notice that #'clojure.core/+ is missing.
    

    You might be wondering what good is such a function, and more importantly - how does it relate to something like “find references”, which admittedly is way more useful. While I don’t know how exactly this functionality is implemented in REBL, I can share with you a very simple implementation of “find references” that’s built on top of the fdeps idea:

    (defn all-vars []
      ;; definition omitted
      ;; Returns a list of all currently loaded vars.
      )
    
    (defn frefs
      [var]
      (let [all-vars (all-vars)
            all-vals (map var-get all-vars)
            deps-map (zipmap all-vars (map fdeps all-vals))]
        (map first (filter (fn [[k v]] (contains? v var)) deps-map))))
    

    And here’s how to use it:

    (frefs #'fdeps)
    ;; => (#'some.ns/frefs)
    
    (frefs #'clojure.core/map)
    ;; => a ton of results
    

    Now that’s something pretty useful! I don’t know about you, but I’ve often resorted to grep and friends when I needed to find where some function has been used, and frefs is definitely is more robust than grep (at least when it comes to finding false positives). Notice that I’ve conveniently omitted the implementation of all-vars, so we can keep our focus on frefs.1 You can find some slightly more sophisticated implementations of both fdeps and frefs in Orchard. This leads me to the fun part…

    Those functions are going to be used for a new nREPL middleware (part of cider-nrepl) that’s finally going to provide some form of “find references” in CIDER out-of-the-box.2 And this actually brings me to the reason why I wrote this blog post in the first place. It has been long believed that the best (only?) way to approach this type of functionality is by doing static analysis of the code. This is a good approach in general, although it comes with some added complexity stemming from the fact you’re no longer relying simply on REPL state introspection (e.g. you have to constantly keep your code and its AST in sync). There’s nothing bad with that approach, but as far as I’m concerned it’s great to be able to provide a really useful form of “find references” that’s trivial in nature, pretty fast and REPL-powered. Sure, it’s not super reliable (as noted above), but it yields good results and it plays well with the whole idea of REPL-powered introspection that tools like CIDER are built upon.

    I already have a running prototype of “find references” in CIDER based on the code I’ve shared in this post and it’s looking pretty sweet so far. I hope I’ll have something to share with everyone on the subject next week. Until then - keep hacking! May the Source be with you!

    P.S. It’d be really great if someone figured out how to do this for ClojureScript as well. I bet there must be a way to implement something similar using only the compiler’s state.

    1. You can find a real implementation in Orchard’s orchard.query namespace. 

    2. Currently you can get this type of functionality from clj-refactor.el and refactor-nrepl

  • The RSpec Style Guide: Reloaded

    I think for many years the gold standard for RSpec best practices has been Better Specs. Eventually the original site was abandoned and Better Specs found a new home at Lelylan. Further down the line it was superseded by an RSpec style guide maintained by ReachLocal.1 Unfortunately at some point the new style guide stagnated as well… I guess you sense where this story is going, right? Fast forward to the happy end…

    I’m delighted to announce that ReachLocal were kind enough to contribute the RSpec style guide to the RuboCop HeadQuarters organization, where it joins the ranks of the popular and widely adopted Ruby and Rails community style guides.2 RuboCop HQ is becoming a focal point for all sort of initiatives related to promoting and refining Ruby-related best programming practices and that certainly pleases me, as this was the single most important idea behind the creation of RuboCop HQ.

    Filipp Pirozkov has assumed the editor-in-chief duties for the RSpec guide and he updated it carefully to match the structure of the Ruby and Rails guides, and recent RSpec developments. The team behind rubocop-rspec is also involved in the ongoing support of the guide. All in all - I’m reasonably certain that RuboCop HQ is going to be its home for many years to come. It’s nice to break a vicious cycle, isn’t it?

    If you’re into RSpec I encourage you to check out the updated guide. I’m confident that it’s going to be a very useful resource for most RSpec users. We’re also really eager to get feedback and suggestions for improvements from all of you! After all it’s called a “community” guide for a reason - it doesn’t reflect the preferences of any single individual, but the collective knowledge and experience of many members of our fine community.

    That’s all great, but for me the real point of the story is something completely different - all of this happened with almost no involvement from me. That’s the biggest testament to the fact that RuboCop HQ is much bigger than me or any individual for that matter. Today there are many style guide editors and many maintainers of the various RuboCop projects. That’s just another manifestation of that beautiful idea that the Ruby community can achieve everything, when they set their mind to it. No single points of failure, endless enthusiasm, lots of hard work and a constant drive to do better. Seems that the community is really big on solid coding standards and tools to enforce them these days, and I’m happy that I played a small part in the early days of that movement. I’m also super excited to see what the future holds for us!

    Keep hacking! And keep writing beautiful specs!

    Update (2019-04-28) The article sparkled an interesting conversation on Reddit. Unfortunately, there was a lot of bitterness and negativity in some of the comments, so I’ll take a moment to address those.

    Both the new RSpec style guide and rubocop-rspec are projects that could really benefit from your feedback and your help. There’s no status quo, there’s nothing set in stone, and we truly value collaboration and seek broad consensus. Unfortunately achieving broad consensus on every topic is close to impossible, so people should also understand that some compromises have to be made. Adopting a hard stance against any efforts to standardize and promote good stylistic practices doesn’t help anyone. You can be part of the problem or part of the solution - the choice is yours!

    I also encourage everyone to check out Filipp’s comments, as they are quite insightful.3 The struggles that Better Specs experienced with their custom publishing pipeline are a good reinforcement of the decision we made to keep things as simple as possible going forward - and nothing is simpler than publishing the guide as a single text file. This approache served well the community Ruby and Rails style guides, and I’m pretty sure it’s going to work well for the RSpec guide as well. Is the end of the day I think it’s much better to have great content than beautiful visuals, right?4

    1. Frankly, I’m not quite certain about how things went down between Better Specs and ReachLocal’s style guide. Please, forgive any inaccuraries in the background story. 

    2. Technically speaking all of this happened about a year ago, but I completely forgot to do a proper announcement back then. 

    3. Especially the one on the history of Better Specs, and how we ended up where we are today. 

    4. Although having them both would be ideal for sure. 

  • The Curious Case of Clojure Contrib

    Do you know what’s the common thing between Clojure Contrib, microservices and DevOps? Everyone thinks they know and understand them, but most people have a different idea about what they are.1

    For many years people have believed that Contrib is one of the following:

    • A staging ground for functionality that will eventually make its way to Clojure.
    • A standard library for Clojure.
    • A set of (superior) libraries maintained/blessed by Rich/Cognitect.

    Contrib has a long history and I think that in the course of it the vision for the project changed a few times.2 Unfortunately for quite a while the only official description of Contrib was one really outdated article on Clojure’s Confluence.

    I’ve wanted to share my perspective on Contrib for a very long time, as I felt it had a somewhat harmful effect on the broader Clojure community, but I’ve been putting this off as I don’t enjoy writing such articles much. I finally found the inspiration that I needed after a recent conversation I had on GitHub with Sean Cornfield, Alex Miller and Stu Halloway about Contrib’s philosophy. I won’t reproduce here everything that we discussed there - after all you can just go and read the discussion or peruse the excellent new documentation that conversation resulted in.

    1. Usually the wrong idea. 

    2. Chas Emerick told me once the only reason he agreed to transfer nREPL to Clojure Contrib was a promise that it can end up as part of Clojure once it stabilizes. 

  • Meta Reduce, Volume 2019.1

    Time to recap what I’ve been up to lately. Admittedly this post is a bit overdue1, but there has been a lot on my plate lately and I had little time for blogging.

    1. I was hoping I’d write one each week. 

  • Meta Reduce, Volume 2019.0

    Prelude

    For a while now I’ve been thinking of starting some form of online journal, following mostly my open-source work and programming exploits, but not limited strictly to that. I know that a blog is supposed to be just that (an online journal), but many of the things I’m working on are not really worthy of dedicated blog posts (and won’t fit in a tweet), and still I feel that they deserve to be shared with a broader audience.1

    Lately every edition of Alex Miller’s excellent InsideClojure Journal has been a constant reminder for me to get something done about my idea. And finally here we are - “Meta Reduce” is my version of such a journal - a reduction of my recent activities in writing. I’m not quite certain on the exact format yet, but I guess I’ll sort it out along the way.

    It’s very hard for me to write this first post simply because a lot has happened since I returned from my OSS “sabbatical” about a month ago. A lot of things have piled up in my absence and I literally don’t know where to begin. Here we go…

    1. Twitter threads are also an option. 

  • Ruby's Creed

    Every programming language has some fundamental idea(s) that drives its design and evolution. For Haskell that’s functional purity and state-of-the-art static typing, for Erlang that’s distributed programming and fault tolerance, for Clojure that’s simplicity and stability. What all these examples have in common is that they are relatively easy to understand and map to design decisions in the languages. This, in turn, makes it possible to determine down the road whether a language sticks to its core values or deviates from them.

    Ruby, however, is very different. It’s world famous for its unique creed - “optimizing for programming happiness”. But what does this really mean? How does one optimize for happiness?

    Unfortunately I’ve never heard Matz speak about this, so I’ll offer you my perspective instead - happiness is simplicity, readability, consistency, expressiveness and flexibility. If I have to describe happiness via Ruby code I’d probably do it like this:

    3.times do
      puts "Ruby Rocks!"
    end
    
  • New York, New York

    Start spreadin’ the news, I’m releasin’ today
    I want to be a part of it
    New York, New York
    These vagabond forms, are longing to eval
    Right through the very REPL of it
    New York, New York…

    Following the long overdue overview of nREPL 0.6 I’ve got a new one for you! Brace yourselves for an overdue overview of the recently released CIDER 0.21 (New York)!

    It terms of volume of changes it’s a pretty small release. If you consider their impact, however, you’ll see it packs quite the punch! In fact it’s probably one of the most significant releases CIDER has had in the past couple of years.

  • The Missing Ruby Code Formatter

    Ever since Go made popular the idea of having one canonical way of formatting the code for a particular programming language (by bundling the gofmt tool with the language), programmers in every community have been trying (with various degree of success) to replicate this. JavaScript’s Prettier became a huge hit and is very widely used today. Elixir 1.6 bundled a standard formatter out of the box. Many similar initiatives are underway.

    In the Ruby community the quest for the One True Formatter has been going on for quite a while and at this point there are already several projects to chose from:

    And, of course, last but (hopefully) not least, there’s RuboCop - a project that I’ve started way back in 2012. Most people probably think of RuboCop as a lint tool only, but it actually has an entire department (type) of cops (code checks) dedicated to inspecting and fixing code layout (a.k.a. code formatting).

    Having options to chose from is generally a good thing, but it also implies that you have to make some thinking, and perhaps even a bit of research, to make sure you’ve chosen the right thing.1 So, which code formatting tool should you use? Have we solved by this point the problem of Ruby’s missing code formatter?

    As I’m the author of RuboCop it’s obvious that I’m biased. It’s fair for you to assume that I’ll be praising RuboCop and extolling its virtues and advantages over the competition for the remainder of this post. Well, I’ll do my best to surprise you, at least a bit.

    1. One has to appreciate the irony - after all this formatter tools should spare from having to make certain decisions. 

  • nREPL 0.6

    nREPL 0.6 was released almost two months ago, but it never got the attention it deserved. At the time of the release I was enjoying some time off from development, and when I got back home I was swamped with work. Still, I had a created todo item to write a blog post detailing the important improvements in nREPL 0.6 and I’m finally doing this.

  • The Clojure Style Guide Redux

    Prelude

    Recently I’ve noticed that the Community Clojure Style Guide has turned 6! According to git log the project started its life on the 3rd of January, 2013!

    commit 3abbcfb8b536999d0b1d64b531a9c57b49b4562a
    Author: Bozhidar Batsov <bozhidar@batsov.com>
    Date:   Thu Jan 3 10:09:53 2013 -0800
    
        Initial commit
    

    Time sure flies fast!

    After the initial announcement of the guide, I never really revisited the topic, so it seems to me that this “birthday”, is as good of an opportunity as any, to do so.

  • CIDER 0.20 (Oslo)

    Hot on the heals of yesterday’s article I’ve got a new one for you! This one is going to be short and sweet - just a few notes about the release of CIDER 0.20 (Oslo).

    I guess some of you are surprised by the news - after all wasn’t CIDER 0.19 (Raleigh) released only a couple of weeks ago? Usually CIDER releases are (many) months apart. Well, while that’s normally the case, I’ve always wanted to do more focused and frequent releases and it seems that I managed to succeed this time around.

    CIDER 0.20 includes very few changes overall.1 I’ll cover them briefly here.

  • CIDER's Orchard: The Future

    Prologue

    This post is part of the mini-series “CIDER’s Orchard”. That’s intended to be the final article in the series, but this might change depending on my inspiration.

  • nREPL: Beyond Clojure

    Prelude

    Many people think of nREPL as a Clojure-specific REPL server and that’s perfectly fine. After all the project started its life in the realm of Clojure and the canonical and most widely used implementation is written in Clojure. However, nREPL is much more than its reference implementation and a recent conversation with Phil Hagelberg, reminded me of the significance of this.

    The default network protocol (socket-based communication with messages encoded using bencode) used is simple, depending neither on JVM or Clojure specifics, thereby allowing (encouraging?) the development of non-Clojure REPL clients. The REPLs operational semantics are such that essentially any non-JVM Clojure implementation should be able to implement it, with allowances for hosts that lack the concurrency primitives to support e.g. asynchronous evaluation, interrupts, etc.

  • Happy New CIDER!

    What can be a better start of 2019 than some freshly brewed CIDER’(0.)19? Consider the release of the latest CIDER my attempt to keep the New Year festivities going for a while longer. It’s also an attempt to clear some overdue items from my (humongous) personal todo list at the start of the new year (other overdue items I tackled today were shaving and taking a shower).

  • (reduce summarize year)

    Year’s end is neither an end nor a beginning but a going on, with all the wisdom that experience can instill in us.

    – Hal Borland

    Another year is almost behind us and I guess it’s time for all of us to take some time to look back on it. For me 2018 was a pretty mixed year both professionally and personally. On one hand I finally managed to re-ignite my desire to work on OSS projects and I’ve managed to get a lot done on so many projects, but on the other hand I ran into some health issues, combined with burnout, and I’ve started pondering a lot about the meaning of everything that I’m doing (and the meaning of life in general). Yeah, yeah - I’m one deep and profound individual. I know.

  • CIDER's Orchard: The Periphery

    Prologue

    This post is part of the mini-series “CIDER’s Orchard”. Currently I’m planning 3 installments in the series, but this might change depending on my inspiration.

  • CIDER's Orchard: The Heart

    Prologue

    This post is part of the mini-series “CIDER’s Orchard”. Currently I’m planning 3 installments in the series, but this might change depending on my inspiration.

  • Managing Multiple JDKs on macOS

    Prologue

    Installing JDKs wasn’t something I needed to do often in the past - after all, Java releases were usually 3-4 years apart. Recently, however, this has changed1 and I find myself installing a new JDK every 6 months. There’s also the problem that now I have to switch between more JDKs to test things…

    I did a bit of research into streamlining my workflow with multiple JDKs and I thought I might share some of my findings with you. My workflow is macOS-specific, but I think that users of other Unix-like operating system can easily adapt it to their environment.

    Another thing to note about my workflow is that it’s very lightweight and doesn’t depend on the usage of any third-party tools. You won’t find here anything about using SDKMAN! and jEnv. You can think of this post as something in the spirit of the awesome talk Programming with Hand Tools - sometimes the journey is way more important than the destination itself.

  • nREPL Redux

    Prologue

    Naming is hard! It truly is! I’ve spent a lot of time ruminating on the title for that particular post, before coming up with “nREPL Redux”. I could have just as easily gone with something like “nREPL Reborn”, “nREPL Returns”, “nREPL Forever”, “nREPL Strikes Back” or “The Revenge of nREPL”.1 Anyways, the name doesn’t matter that much - what matters is the story I’m about to tell you. Namely the story of the rise, fall and re-birth of the most important tool in the Clojure ecosystem today.

    If you’re into Clojure development you probably know that I’m the author of CIDER - a (somewhat) popular Clojure programming environment. Most people think of CIDER as an Emacs project, but it’s much bigger than this - there are so many moving pieces that make the whole thing work, that I should probably write separately on this subject (and I totally plan to do so). One piece is special, though. It’s the very heart of CIDER and it’s the nREPL server which powers all the magic that happens behind the scenes - code evaluation, code completion, debugging and all that jazz.

    nREPL is, very simply put, a network REPL server, which aims to provide a common ground for Clojure tool authors who need access to a REPL. This post is mostly about nREPL, but it’s also about some bigger topics like building inclusive communities, avoiding past mistakes and driving progress forward. So, here we go…

    1. Probably by now you’ve realized I’m a huge Batman and Star Wars fan. 

  • A Better Way to Compare Versions in Ruby

    Very often we need to compare version strings in the Ruby code we write - e.g. we need to handle something differently if some library is newer than some version (perhaps because it changed its API). As versions are often represented as strings many Rubyists would write code like this:

    if version > '2.3.4'
      # ...
    else
      # ...
    end
    
  • A Safer RuboCop

    I’ll assume that if you’re reading this post, then you probably already know what RuboCop is, so I won’t go into any details on that subject.1

    Yesterday the project reached a very important milestone2 on its way to the “magic” 1.0 release - namely the introduction of extended cop3 metadata and the ability to run only cops and auto-corrections that can’t possibly break your code by changing its meaning. We call such cops and their auto-corrections “safe”. Making use of the new functionality is very easy:

    # Run only safe cops.
    $ rubocop --safe
    
    # Perform only safe auto-corrections.
    $ rubocop --safe-auto-correct
    
    # Run only safe cops and perform only safe auto-corrections.
    $ rubocop --safe --safe-auto-correct
    
    1. For those of you who don’t know - it’s a popular Ruby static code analyzer and formatter. 

    2. RuboCop 0.60. The complete release notes are here

    3. RuboCop’s lingo for a check. 

  • nREPL's Secret TTY Transport

    Ever since I took over the development of nREPL a few months ago, I’ve been spending a lot of time learning about its inner workings and documenting them meticulously.1 I’ve learned a ton so far, and I’d like to share some of my findings. I hope this post is going to be the first of a series of posts on nREPL internals, but I won’t make any promises. So, let’s get to the point!

    1. I plan to write a lot more down the road about the process of migrating nREPL out of Clojure Contrib and creating its new site/manual. 

  • Going Meta

    Writing is hard. As is naming stuff.1

    Meta Redux is a re-boot of my blogging endeavours that failed miserably so far due to a combination of poor choice of tools and lack of vision, time, and writing skills. I believe this time around I got the tooling2 and the vision right, but I can make no promises about the rest.

    1. The name of this blog is, of course, a tribute to Emacs (in particular to its legendary Meta-x keybinding). 

    2. It’s just Jekyll. No bells, no whistles, no nonsense. 

subscribe via RSS