Underscores for vars


#1

Why do I have to refer to scoopables from bakery.core as _scoopables in my baking namespace?


#2

See https://github.com/brentvukmer/clojureintro/blob/master/src/clojureintro/baking.clj#L46


#3

For whatever reason, _scoopables is the actual name of the set as it is declared in bakery.core. See https://github.com/lispcast/bakery/blob/master/src/bakery/core.clj#L21

Now, as for why it was named that way, I don’t know. I am not familiar with any Clojure symbol naming convention that starts with an underscore, and I just skimmed the Library Coding Standards and community Clojure style guide to confirm that I hadn’t forgotten one.

As an aside, I’d recommend avoiding :use in your namespaces, it makes it harder to keep track of where things came from. If you instead started with (require [bakery.core :as core]) then you would write things like (contains? core/_scoopables ingredient), making it clear when you are referring to something in from the library. But perhaps since this is an introduction they took this shortcut to save you typing, and that’s fine, I just wanted to make sure you were aware of a better way long term.

As a second aside, when you are dealing with a set like your _scoopables, the contains? invocation is redundant; a set, when used as a function, checks whether it contains the argument, so simply calling (_scoopables ingredient) is equivalent to (contains? _scoopables ingredient). But now I am probably getting far ahead of this introductory material…


#4

Hi @brentvukmer,

This is a great question. Wow, that was a long time ago that I wrote that code. A lot has changed since then.

At the time, I never intended anyone to use that variable. It was not part of the spec, which included a lot of functions but no sets. You’re free to use it, of course, but notice in the course I never mentioned sets. And because I recommended using :use, then anyone defining their own scoopables would have to deal with collisions, which I wanted to avoid.

I’m all for people going off the track, and of course asking questions. Thanks!

@brunchboy is right. There’s no coding standard for using underscores. I made it up.

As for using :use, it was still common at the time I made the videos. Now it is not common. (:require [bakery.core :refer :all]) is better, and giving something a namespace alias (:require [bakery.core :as bakery]) is preferred. However, I did not want to go into namespaces so soon.

And about using contains? on a set. @brunchboy is right that it is unnecessary since sets can act as functions. However, I like to use contains? because it calls out what is going on. At that point in the program, it’s hard to know what _scoopables is, so treating it like a function might add to the confusion.

Thanks for the great question!
Eric


#5

Thanks, @ericnormand, that all makes sense, and I know how impossible it is to introduce topics you want to focus on without leaving some things unexplained! I think your worry about not wanting to conflict with other people’s names is the crux of why :use and :refer :all fell out of favor—namespace aliases and :refer with a specific list of symbols chosen by the new namespace give its author control over exactly what gets imported. So this digression turns out to be a great chance to talk about important topics.

To clarify, I wasn’t trying to say that one should never use contains?, I agree that it can provide useful clarity, especially when you don’t know something is a set. I might well leave it in this case, and almost didn’t say anything, but couldn’t resist pointing out an alternative, and hopefully helping to explain what was going on when later in life a form like (#{:red :green :blue} color) shows up. But it was probably too much of a side-trip here.

To make up for that, let me add that as a beginning Clojurist (and even occasionally today) I found myself confused about what was syntax and what was convention when it came to symbols and special characters. I found The Weird and Wonderful Characters of Clojure a useful reference while I was getting used to them, and the Clojure reader reference. But even those are incomplete, for example, I just recently learned that you can use #= in front of a form to tell the reader to evaluate it at read time, to pull an expensive constant expression evaluation out of a function so that it happens at compile time. I don’t know where that is even documented!

So it is a long journey of learning I am on, but I’ve found it very rewarding.


#6

Hey @brunchboy,

You’re awesome! I love it when people answer questions here, so thanks for that!

You’re absolutely right about using namespace aliases. It’s a great point for discussion.

Eric


#7

Thanks for the feedback!


#8

I like contains? for the reason you give, @ericnormand.

I definitely need to restrain my tendency to jump ahead and/or wander - in this case I was looking at the code in video1.clj. There’ll be plenty of time to explore, I just need to get through these introductory lessons.

@brunchboy - I really appreciate your feedback. Definitely feel like I’m getting value for money by signing up for this.