8.5 C
New York
Thursday, June 26, 2025
Blog Page 28

Guide to starting with Clojure

Guide to starting with Clojure

This guide is aimed to the developer who’s interested in Clojure and want to install it and start using it right away.

It will cover the installation of Clojure, some of the build tools and how they work, the configuration of an editor, of the REPL and a small hello world demonstrating how things like build, and test works.

If you’re new to Clojure, at the end of this guide you should be able to start your project.

Table of contents

Installing

Java

First you’ll need to make sure that Java is installed on your computer, you can run a Terminal and run the following command to check if it’s already installed:

You’ll need at least Java 8, but you can install Java 11, Java 12 or even Java 13.

If you don’t have Java, or want to upgrade it you can either go download it directly from the Oracle website, or you can use Adopt OpenJDK and select the version that you wish to install.

Once you installed or upgraded java run again java -version in your terminal to check that it’s been correctly installed, for example this is a sample output after having downloaded and installed Java 11 (here in Ubuntu via Windows SubLinux) :

$ java -version
openjdk version "11.0.5" 2019-10-15
OpenJDK Runtime Environment (build 11.0.5+10-post-Ubuntu-0ubuntu1.118.04)
OpenJDK 64-Bit Server VM (build 11.0.5+10-post-Ubuntu-0ubuntu1.118.04, mixed mode, sharing)

Clojure Tooling

There are different Clojure tools that you can use to build your project.

  1. Clojure CLI + tools.deps
  2. Leiningen
  3. Boot

You can use the one you want.

Hey I’m new to Clojure and you want me to make a choice? Seriously?

I agree with you, humble imaginary visitor.

In this guide I will cover tools.deps, and we’ll also install Leiningen so that you have it on your system when you need to, and because I’ve never used Boot myself even if I’ve heard good things about it, you can try it if you want.

From my point of view you should start with tools.deps because I feel like the community is really invested in it right now, and they are building some cool stuff.

Nevertheless it helps knowing how Leiningen works because you’ll find a lot of projects using it. But for your project just stick with one of the alternative, don’t try to mix the two.

Edit: I’ve just found this article What are the clojure tools which goes into more details regarding how the Clojure CLI & tools.deps actually work, so read it later if you need to know more about it.

MacOS

You can install Clojure using homebrew:

First update your brew, then install Clojure CLI, and verify that it works:

$ brew update
$ brew install clojure/tools/clojure
$ clj
Clojure 1.10.1
user=> (println "Hello, world!")
Hello, world!
nil
user=> 

With these 3 commands you have Clojure CLI + tools.deps already installed.

Now let’s install Leiningen, you just need to download the lein script make it executable and put it somewhere on your disk.

I personally install all my dev tools in ~/dev/tools/, but you can install it wherever you want like in /usr/local/bin/, for example

$ curl https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > lein
$ sudo mv lein /usr/local/bin/lein
$ sudo chmod +x /usr/local/bin/lein
$ lein version
Leiningen 2.9.1 on Java 11.0.5 OpenJDK 64-Bit Server VM

Linux + Windows

On Windows I personally use the Windows Sub Linux (WSL), I chose the Ubuntu distribution but you can take anyone you prefer, then open your Ubuntu terminal and follow the steps.

You can install Clojure by downloading an installer from the clojure.org website

$ curl -O https://download.clojure.org/install/linux-install-1.10.1.536.sh
$ chmod +x linux-install-1.10.1.536.sh
$ sudo ./linux-install-1.10.1.536.sh
$ clj
Clojure 1.10.1
user=> (println "Hello, world!")
Hello, world!
nil
user=> 

Now you have Clojure CLI + tools.deps installed correctly.

To install Leiningen, you’ll do the same as on Mac OS X

$ curl https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > lein
$ sudo mv lein /usr/local/bin/lein
$ sudo chmod +x /usr/local/bin/lein
$ lein version
Leiningen 2.9.1 on Java 11.0.5 OpenJDK 64-Bit Server VM

IDE

Now that Clojure is installed, let’s write some code using your IDE and the REPL integration.

Obviously I cannot explain how every IDE / text editor works with Clojure, I’m not a Emacs or Atom user, I do use mainly IntelliJ, but I’ve used VSCode extensively also.

As with the Linux distribution, you can chose to use the editor you like most, like Emacs, or Vim + fireplace, or Sublime or any other you can find.

This is why I will cover both IntelliJ and VSCode in this guide.

IntelliJ + Cursive

Since I’m from the Java world, I’m used to IntelliJ and the Cursive plugin for Clojure development.

If you don’t have IntelliJ installed, just grab a version, the community version is free and works fine with Cursive, otherwise just follow the steps for VS Code below.

Run the installer then run IntelliJ.

Type Shift Shift then type Plugins then Enter or you can go to File > Settings... > Plugins.

In the Plugins window type Cursive and then install it, finally restart the IDE, you’ll be good to go for the next section.

VSCode + Calva

Regarding VSCode, you can use the Calva plugin, to install it you just run VSCode and the go to the Extension market place, search for Calva and then install it, you’re good to go.

Playing with the REPL from your IDE

The Clojure REPL is fantastic, and I urge you to make it part of your work-flow right from the beginning.

If you want a demo of how the REPL can help you write your code when you know how to use it (and it’s quick to get going), just take a look at What makes a good REPL? from Valentin Waeselynck.

Note: for this part I will cover opening a project based on tools.deps, but the IDE support opening Leiningen projects also, and it doesn’t affect the REPL in any way.

There are two ways to work with the REPL, either you run a REPL from the command line, and then you attach your IDE to it, or you run a REPL directly from your IDE.

I usually chose the first solution using nREPL and then attach my Cursive within IntelliJ to it. We’ll see both solutions for both of the IDE and how we can do some trivial things with the REPL to get you going.

In order to have the same little project to test from both IDE, let’s just create a simple file named deps.edn and put the following content in it.

{:paths ["resources" "src"]
 :deps {org.clojure/clojure {:mvn/version "1.10.1"}
        nrepl/nrepl {:mvn/version "0.5.3"}}}

Then create a simple file named src/playground.clj with the following content:

Ok, we’re good to go.

IntelliJ + Cursive

Importing this project in IntelliJ

Just go through File > Open and select the directory where you’re working, then open as a New Project.

IntelliJ will open a new window with your project.

Now let’s see how to use the REPL from within IntelliJ.

Run a REPL from your IDE

Click the Add Configuration… button next to the green hammer.

Then click the + button and chose Clojure REPL > Local, in the new Run/Debug Configurations window name it Local REPL and click OK.

Now instead of the Add Configurations button, select Local REPL and click run.

You can evaluate Clojure from the text editor in the bottom right (where I wrote (println "Hello, world!") then press Enter.

You can also directly evaluate forms from your editing, for example place your cursor at the end of (+ 40 2) and press Alt + Shift + P.

For example type a new Clojure code (map inc [0 1 2 3]) put your cursor at the end, then press Alt + Shift + P it will send it for evaluation into the REPL, which will respond with => (1 2 3 4).

Now in the text editor in the bottom right, type (map inc *1) then press Enter, it will output => (2 3 4 5). Because in the REPL, *1 means the last evaluated result.

Cursive let’s you load a file to the REPL (Alt + Shift + L), synchronize the files to the REPL (Alt + Shift + M), switch the REPL to the current namespace you’re editing (Alt + Shift + R).

One interesting binding to set with a custom shortcut is the Send form before carret to REPL that you can assign in the Keymap preferences of Intellij like this:

Then with your cursor at the end of a Clojure form just press Ctrl + Enter and it’s sent to the REPL for evaluation. You can set any shortcut you want, like Alt + Shift + E (for evaluate).

I’ll let you play with the different options that you can find in the Tools > REPL menu.

Attach to a running REPL

In order to attach to a REPL you must have one running elsewhere, if you followed the section above, stop the REPL by clicking the red square.

Now in a terminal go to the directory where your code is located then type the following.

$ clj -m nrepl.cmdline
nREPL server started on port 63812 on host localhost - nrepl://localhost:63812

Take a look at the port on which nREPL is running, for me it was 63812.

In IntelliJ, click the Add Configuration… button next to the green hammer.

Then click the + button and chose Clojure REPL > Remote, in the new Run/Debug Configurations window name it Remote REPL, select nREPL then type localhost for the host and 63456 for the ** port**, finally click OK.

Now instead of the Add Configurations button, select Remote REPL and click run.

As for the previous section you can evaluate into the remote REPL as if it was running locally. A remote REPL has advantages, you could imagine that you connect to a running REPL in production and check what’s going on live.

VSCode + Calva

Importing this project in VSCode

In VSCode, just go to Open > Folder, select the folder where your code is located and click OK.

Run a REPL from your IDE

Right click in the editor and select Jack-in or Connect to REPL Server

Select Start a REPL server and connect (a.k.a Jack-in), then select Clojure CLI.

Like Cursive in IntelliJ, it will display a REPL on the right side of your IDE, where you can evaluate Clojure forms.

You can select a form using Ctrl + Alt + C, Ctrl + S, and evaluate it using Ctrl + Alt + C V, the result is directly appended next to your form in your IDE.

Calva has plenty of shortcuts like loading the current file in the REPL (Ctrl + Alt + C Enter), load the current namespace in the REPL (Ctrl + Alt + C, Ctrl + Alt + N).

I’ve lost my finger muscle memory regarding the default shortcuts on Calva, but I think they can be customized to your need (I’m more of a Cursive guy).

If you want to disconnect from the REPL, just right click then select Disconnect from the REPL server.

Attach to a running REPL

Right click in the editor and select Jack-in or Connect to REPL Server

This time select Connect to a running REPL server in your project then Clojure CLI then type localhost:63812 if your previous REPL is still running, otherwise run it again and get the actual nREPL port.

Accept by pressing Enter and you’re good to go (see the green text saying REPL connected.).

All right you’re now ready to rock!

Clojure 101 in 5 minutes

Tables Cool
Numbers Integers, doubles, floats, fractions
String "foo"
Character A
Keyword :foo
List '(1 2 3)
Vector [1 2 3]
Map {:name "Alex" :age 35}
Sets #{1 2 3}
Regexp #"d+"
Variable (def foo 123)
Function clojure (defn add [a b] (+ a b)
Anonymous function (fn [a b] (+ a b))
Also more concise #(+ %1 %2)
Java JavaScript Clojure
String "foo" "foo" or 'foo' "foo"
Boolean true, false true, false true, false
Nothing null null nil
Keywords Nope Nope :name
Numbers 1 1 1
Decimals 1.2 1.2 1.2
Comments //comment //comment ; comment
Regexp "\d+" /d/ #"d+"
Arrays/Vectors new int[] {1, 2, 3} [1, 2, 3] [1 2 3]
Maps Map.of("one", 1, "two", 2) {one: 1, two: 2} {:one 1 :two 2}
Sets Set.of(1, 2, 3) new Set(1, 2, 3) #{1 2 3}
Functions int sum(int x, int y) { return x + y; } function sum(x, y) { return x + y; } (defn sum [x y] (+ x y))
Shorthand sum = (x, y) -> x + y; const sum = (x, y) => x + y; (def sum #(+ %1 %2))
Function call sum(1, 2) sum(1, 2) (sum 1 2)

Project specific steps

I want to build my project

Note: for this example I just created an src folder, but you’ll often see src/main/clojure deriving from Maven standard directory layout, in such a case you just need to change the path in deps.edn.

Let’s say you have written a super program which SHOUT the text you’re giving to it.

(ns playground
   (:require [clojure.string :as str])
   (:gen-class))

(defn shout [text]
   (as-> (seq text) $
     (interpose   $)
     (concat $ (repeat 3 !))
     (apply str $)
     (str/upper-case $)))

(defn -main [& args]
    (->> args
         (map shout)
         (apply str)
         println))

You can run it with the clj utility:

$ clj -m playground "Clojure is fun"
C L O J U R E   I S   F U N!!!

But we’d like to build this to a fat JAR (some call them uber JAR also). A fat JAR is a Java Archive (a zip) containing all the needed dependencies so that you just have to call the java executable on it to execute the code it contains.

We call them Jean-Michel at work since years, because of Jean-Michel Jarre. Hey, t’as buildé le Jean-Michel ?

There are multiple tools which can do it in Clojure land, but we’ll be using uberdeps by Nikita Tonsky, one of the Clojure community that you should definitely follow, but you’ll see more at the end of this article.

Modify your deps.edn file to add uberdeps :

{:paths ["resources" "src"]
 :deps {org.clojure/clojure {:mvn/version "1.10.1"}
        nrepl/nrepl {:mvn/version "0.5.3"}}
 :aliases {:fatjar {:extra-deps {uberdeps {:mvn/version "0.1.10"}}
                    :main-opts  ["-m" "uberdeps.uberjar" "--target" "target/shout-0.1.jar"]}}}

Essentially we’re just adding an alias named fatjar that needs an extra dependency uberdeps and which command line to run is clj -m uberdeps.uberjar --target target/shout-0.1.jar.

In order to run an alias you have to use clj -A{alias-name}, so just do it like this, and then run the JAR:

$ clj -Afatjar
Downloading: uberdeps/uberdeps/0.1.10/uberdeps-0.1.10.pom from https://repo.clojars.org/
Downloading: org/clojure/tools.deps.alpha/0.8.677/tools.deps.alpha-0.8.677.pom from https://repo1.maven.org/maven2/
...
[uberdeps] Packaging target/shout-0.1.jar...
+ resources/**
+ src/**
+ nrepl/nrepl 0.5.3
.   nrepl/bencode 1.0.0
+ org.clojure/clojure 1.10.1
.   org.clojure/core.specs.alpha 0.2.44
.   org.clojure/spec.alpha 0.2.176
[uberdeps] Packaged target/shout-0.1.jar in 572 ms

$ java -cp target/shout-0.1.jar clojure.main -m playground "Clojure is fun"
C L O J U R E   I S   F U N!!!

Working as expected, now you can just send your JAR to anyone having Java 8+ installed, and they can use it. How cool!

And tests? Everyone say tests are great and all

Like for the fat JAR, just add an alias to your deps.edn so that we can use kaocha from lambdaisland (one more to follow) as a test runner.

{:paths ["resources" "src"]
 :deps {org.clojure/clojure {:mvn/version "1.10.1"}
        nrepl/nrepl {:mvn/version "0.5.3"}}
 :aliases {:test   {:extra-paths ["test"]
                    :extra-deps  {lambdaisland/kaocha {:mvn/version "1.0-612"}}
                    :main-opts   ["-m" "kaocha.runner"]}
           :fatjar {:extra-deps {uberdeps {:mvn/version "0.1.10"}}
                    :main-opts  ["-m" "uberdeps.uberjar" "--target" "target/shout-0.1.jar"]}}}

Now just create a test directory, and add a file named playground_test.clj write a simple test:

(ns playground-test
  (:require [clojure.test :refer :all]
            [playground :refer :all]))

(deftest shouting
  (is (= "H E L L O!!!" (shout "hello"))))

Note that the file is named playground_test with an underscore but the namespace is named playground-test with a dash.

Then run kaocha with clj and your newly created test alias.

$ clj -Atest
[(.)]
1 tests, 1 assertions, 0 failures.

Great we have created a powerful test, and we can now ensure our program works before building it and send it to friends!

I’m a beginner, I make mistake, is there something to help me?

You can use a linter. In Clojure there are plenty of options, but the most recent is clj-kondo by Michiel Borkent (one more to follow).

You can install the binary, or use it directly from your deps.edn, this is what I will cover below, but don’t hesitate to read the README of clj-kondo.

{:paths ["resources" "src"]
 :deps {org.clojure/clojure {:mvn/version "1.10.1"}
        nrepl/nrepl {:mvn/version "0.5.3"}}
 :aliases {:test   {:extra-paths ["test"]
                    :extra-deps  {lambdaisland/kaocha {:mvn/version "1.0-612"}}
                    :main-opts   ["-m" "kaocha.runner"]}
           :fatjar {:extra-deps {uberdeps {:mvn/version "0.1.10"}}
                    :main-opts  ["-m" "uberdeps.uberjar" "--target" "target/shout-0.1.jar"]}
           :kondo  {:extra-deps {clj-kondo {:mvn/version "RELEASE"}}
                    :main-opts  ["-m" "clj-kondo.main"]}}}

For the purpose of the article, modify the playground.clj to add an unused binding:

(ns playground
   (:require [clojure.string :as str])
   (:gen-class))

; ...

(defn -main [& args]
  (let [foo "foo bar"]
    (->> args
         (map shout)
         (apply str)
         println)))

Then run clj-kondo:

$ clj -Akondo
src/playground.clj:13:9: warning: unused binding foo
linting took 60ms, errors: 0, warnings: 1

You’ll notice that clj-kondo took 60ms to execute, but it took more than that to execute clojure and everything related, that’s why clj-kondo can also be installed as a native binary.

Let’s install it, and run it to see that the execution is instant.

$ bash <(curl -s https://raw.githubusercontent.com/borkdude/clj-kondo/master/script/install-clj-kondo)
$ clj-kondo --lint src
src/playground.clj:13:9: warning: unused binding foo
linting took 9ms, errors: 0, warnings: 1

That seems about very usable directly from your IDE, you can achieve this by following the great guide on the clj-kondo GitHub wiki.

Is there any way my code looks the same everywhere?

Sure use a code formatter, they are built-in your IDE, in IntelliJ I belive it’s Ctrl + Alt + L (or Menu > Code > Reformat code), but maybe you want to reformat the code in a git pre-hook?

For this you can use cljfmt by weavejester (again someone to follow).

Modify your deps.edn and add both a fmt-fix and fmt-check aliases:

{:paths ["resources" "src"]
 :deps {org.clojure/clojure {:mvn/version "1.10.1"}
        nrepl/nrepl {:mvn/version "0.5.3"}}
 :aliases {:test      {:extra-paths ["test"]
                       :extra-deps  {lambdaisland/kaocha {:mvn/version "1.0-612"}}
                       :main-opts   ["-m" "kaocha.runner"]}
           :fatjar    {:extra-deps {uberdeps {:mvn/version "0.1.10"}}
                       :main-opts  ["-m" "uberdeps.uberjar" "--target" "target/shout-0.1.jar"]}
           :kondo     {:extra-deps {clj-kondo {:mvn/version "RELEASE"}}
                       :main-opts  ["-m" "clj-kondo.main" "--lint" "src"]}
           :fmt-fix   {:extra-deps {com.jameslaverack/cljfmt-runner
                                    {:git/url "https://github.com/JamesLaverack/cljfmt-runner"
                                     :sha "97960e9a6464935534b5a6bab529e063d0027128"}}
                       :main-opts ["-m" "cljfmt-runner.fix"]}
           :fmt-check {:extra-deps {com.jameslaverack/cljfmt-runner
                                    {:git/url "https://github.com/JamesLaverack/cljfmt-runner"
                                     :sha "97960e9a6464935534b5a6bab529e063d0027128"}}
                       :main-opts ["-m" "cljfmt-runner.check"]}}}

Now modify the playground.clj to make it look weird on purpose.

(ns playground
  (:require [clojure.string :as str])
  (:gen-class))

(defn shout [text]
  (as-> (seq text) $
              (interpose   $)
    (concat $ (repeat 3 !))
                       (apply str $)
           (str/upper-case $)))

(defn -main [& args]
                 (let [foo "foo bar"]
    (->> args
                      (map shout)
         (apply str)
                        println)))

And run cljfmt:

$ clj -Afmt-check
src/playground.clj has incorrect formatting
--- a/mnt/c/temp/starter/src/playground.clj
+++ b/mnt/c/temp/starter/src/playground.clj
@@ -4,14 +4,14 @@

 (defn shout [text]
   (as-> (seq text) $
-              (interpose   $)
+    (interpose   $)
     (concat $ (repeat 3 !))
-                       (apply str $)
-           (str/upper-case $)))
+    (apply str $)
+    (str/upper-case $)))

 (defn -main [& args]
-                 (let [foo "foo bar"]
+  (let [foo "foo bar"]
     (->> args
-                      (map shout)
+         (map shout)
          (apply str)
-                        println)))
+         println)))
No such file: project.clj

Pretty neat, now ask cljfmt to fix it:

$ clj -Afmt-fix src/playground.clj
Reformatting src/playground.clj

Done, your code looks like normal again:

(ns playground
  (:require [clojure.string :as str])
  (:gen-class))

(defn shout [text]
  (as-> (seq text) $
    (interpose   $)
    (concat $ (repeat 3 !))
    (apply str $)
    (str/upper-case $)))

(defn -main [& args]
  (let [foo "foo bar"]
    (->> args
         (map shout)
         (apply str)
         println)))

This is using cljfmt-runner for deeper integration with tools.deps.

Clojure core library is so full of awesome bits, sometimes I forget them

Of course Clojure comes with batteries included, really included, even in years you’ll discover some gems, but for a starter you can lean on kibit which will inspect your code and propose you some ways you can improve it with built-in function you forgot existed.

Modify your playground.clj to look like this:

(ns playground
  (:require [clojure.string :as str])
  (:gen-class))

(defn handle-empty [s]
  (if (nil? s)
    (seq "Please talk to me")
    s))

(defn shout [text]
  (as-> (seq text) $
    (handle-empty $)
    (interpose   $)
    (concat $ (repeat 3 !))
    (apply str $)
    (str/upper-case $)))

(defn -main [& args]
    (->> (or args [""])
         (map shout)
         (apply str)
         println))

Test it still works:

$ clj -m playground "Hello"
H E L L O!!!
$ clj -m playground ""
P L E A S E   T A L K   T O   M E!!!
$ clj -m playground
P L E A S E   T A L K   T O   M E!!!

You can also add a test to your playground_test.clj

(ns playground-test
  (:require [clojure.test :refer :all]
            [playground :refer :all]))

(deftest shouting
  (is (= "H E L L O!!!" (shout "hello"))))

(deftest shouting-empty
  (let [expected "P L E A S E   T A L K   T O   M E!!!"]
    (is (= expected (shout nil)))
    (is (= expected (shout "")))))

Then run the tests:

$ clj -Atest
[(...)]
2 tests, 3 assertions, 0 failures.

Ok let’s get back to kibit.

Add it to your deps.edn like this:

{:paths ["resources" "src"]
 :deps {org.clojure/clojure {:mvn/version "1.10.1"}
        nrepl/nrepl {:mvn/version "0.5.3"}}
 :aliases {:test      {:extra-paths ["test"]
                       :extra-deps  {lambdaisland/kaocha {:mvn/version "1.0-612"}}
                       :main-opts   ["-m" "kaocha.runner"]}
           :fatjar    {:extra-deps {uberdeps {:mvn/version "0.1.10"}}
                       :main-opts  ["-m" "uberdeps.uberjar" "--target" "target/shout-0.1.jar"]}
           :kondo     {:extra-deps {clj-kondo {:mvn/version "RELEASE"}}
                       :main-opts  ["-m" "clj-kondo.main" "--lint" "src"]}
           :fmt-fix   {:extra-deps {com.jameslaverack/cljfmt-runner
                                    {:git/url "https://github.com/JamesLaverack/cljfmt-runner"
                                     :sha "97960e9a6464935534b5a6bab529e063d0027128"}}
                       :main-opts ["-m" "cljfmt-runner.fix"]}
           :fmt-check {:extra-deps {com.jameslaverack/cljfmt-runner
                                    {:git/url "https://github.com/JamesLaverack/cljfmt-runner"
                                     :sha "97960e9a6464935534b5a6bab529e063d0027128"}}
                       :main-opts ["-m" "cljfmt-runner.check"]}
           :kibit     {:extra-deps {tvaughan/kibit-runner {:mvn/version "0.1.0"}}
                       :main-opts  ["-m" "kibit-runner.cmdline"]}}}

And run kibit

$ clj -Akibit
At ./src/playground.clj:15:
Consider using:
  (clojure.string/join $)
instead of:
  (apply str $)

Kibit can also report the changes to be made in Markdown

$ clj -Akibit -- --reporter markdown
----
##### `./src/playground.clj:15`
Consider using:
​```clojure
  (clojure.string/join $)```
instead of:
​```clojure
  (apply str $)```

And you can ask it to replace with what it thinks best alone (add --interactive for an interactive terminal session)

$ clj -Akibit -- --replace
Replacing
  (apply str $)
 with
  (clojure.string/join $)
in ./src/playground.clj:15

Now your code looks like this

(ns playground
  (:require [clojure.string :as str])
  (:gen-class))

(defn handle-empty [s]
  (if (nil? s)
    (seq "Please talk to me")
    s))

(defn shout [text]
  (as-> (seq text) $
    (handle-empty $)
    (interpose   $)
    (concat $ (repeat 3 !))
    (clojure.string/join $)
    (str/upper-case $)))

(defn -main [& args]
    (->> (or args [])
         (map shout)
         (apply str)
         println))

Awesome, isn’t it?

Where to go from here?

Now that your IDE is configured and you have some tooling ready to rock some code, how do you start your Clojure journey?

I’ll link to you some website and tutorials to read, and also people to follow.

Websites

Conferences

  • Clojure/north
  • :clojureD
  • IN/Clojure
  • ClojuTRE
  • Clojure/conj

Follow

Last word

Clojure is awesome, there’s even love letters written to it,
the community is fantastic, the projects are of great quality.

I’ve been doing Clojure for around 6 years, that’s my favorite language, it made me learn a lot, and changed how I program
in other languages (my primary language at work being Java).

I hope you’ll enjoy your Clojure journey, this is just the beginning ❤

Until next time!

Read More

The Svelte Compiler Handbook

The Svelte Compiler Handbook

Who is this for?

Anyone who

  • is interested in the Svelte compilation process
  • wants to get started in reading Svelte source code

Overview




The Svelte compilation process can be broken down into 4-steps

  • Parsing source code into Abstract Syntax Tree (AST)
  • Tracking references and dependencies
  • Creating code blocks and fragments
  • Generate code

Which sums out by the following pseudocode:

const source = fs.readFileSync('App.svelte');


const ast = parse(source);


const component = new Component(ast);


const renderer =
  options.generate === 'ssr' ? SSRRenderer(component) : DomRenderer(component);


const { js, css } = renderer.render();

fs.writeFileSync('App.js', js);
fs.writeFileSync('App.css', css);

1. Parsing source code into AST





const ast = parse(source);

The Svelte syntax is a superset of HTML. Svelte implements its own parser for the Svelte syntax, which handles:

  • HTML syntax

  • Curly brackets { data }
  • Logic blocks {#each list as item}

The Svelte parser handles specially for and

tags.

When the parser encounters a tag, it uses acorn to parse the content within the tag. When the parser sees a

tag, it uses css-tree to parse the CSS content.

Besides, the Svelte parser differentiates instance script, , and module script, .

The Svelte AST look like:

{
  html: { type: 'Fragment', children: [...] },
  css: { ... },
  instance: { context: 'default', content: {...} },
  module: { context: 'context', content: {...} },
}

You can try out the Svelte parser in ASTExplorer. You can find the Svelte parser under HTML > Svelte.

Where can I find the parser in the source code?

The parsing starts here, which the parser is implemented in src/compiler/parse/index.ts.

Where can I learn about parsing in JavaScript?

My previous article, “JSON Parser with JavaScript” introduces the terminology and guides you step-by-step on writing a parser for JSON in JavaScript.

If this is the your first time learning about parser, I highly recommend you to read that.

2. Tracking references and dependencies





const component = new Component(ast);

In this step, Svelte traverses through the AST to track all the variable declared and referenced and their depedencies.

a. Svelte creates a Component instance.

The Component class stores information of the Svelte component, which includes:

b. Traverse the instance script and module script AST

Component traverses the instance script and module script AST to find out all the variables declared, referenced, and updated within the instance script and module script.

Svelte identifies all the variables available before traversing the template. When encountering the variable during template traversal, Svelte will mark the variable as referenced from template.

c. Traverse the template

Svelte traverses through the template AST and creates a Fragment tree out of the template AST.

Each fragment node contains information such as:

– expression and dependencies

Logic blocks, {#if}, and mustache tags, { data }, contain expression and the dependencies of the expression.

– scope

{#each} and {#await} logic block and let: binding create new variables for the children template.

Svelte creates a different Fragment node for each type of node in the AST, as different kind of Fragment node handles things differently:

d. Traverse the instance script AST

After traversing through the template, Svelte now knows whether a variable is ever being updated or referenced in the component.

With this information, Svelte tries make preparations for optimising the output, for example:

  • determine which variables or functions can be safely hoisted out of the instance function.
  • determine reactive declarations that does not need to be reactive

e. Update CSS selectors to make style declarations component scope

Svelte updates the CSS selectors, by adding .svelte-xxx class to the selectors when necessary.

At the end of this step, Svelte has enough information to generate the compiled code, which brings us to the next step.

Where can I find this in the source code?

You can start reading from here, which the Component is implemented in src/compiler/compile/Component.ts.

Where can I learn about traversing in JavaScript?

Bear with my shameless plug, my previous article, “Manipulating AST with JavaScript” covers relevant knowledge you need to know about traversing AST in JavaScript.

3. Creating code blocks and fragments





const renderer =
  options.generate === 'ssr' ? SSRRenderer(component) : DomRenderer(component);

In this step, Svelte creates a Renderer instance which keeps track necessary information required to generate the compiled output. Depending on the whether to output DOM or SSR code (see generate in compile options), Svelte instantiates different Renderer respectively.

DOM Renderer

DOM Renderer keeps track of a list of blocks and context.

A Block contains code fragments for generate the create_fragment function.

Context tracks a list of instance variables which will be presented in the $$.ctx in the compiled output.

In the renderer, Svelte creates a render tree out of the Fragment tree.

Each node in the render tree implements the render function which generate codes that create and update the DOM for the node.

SSR Renderer

SSR Renderer provide helpers to generate template literals in the compiled output, such as add_string(str) and add_expression(node).

Where can I find the Renderer in the source code?

The DOM Renderer is implemented in src/compiler/compile/render_dom/Renderer.ts, and you can check out the SSR Renderer code in src/compiler/compile/render_ssr/Renderer.ts.

4. Generate code





const { js, css } = renderer.render();

Different renderer renders differently.

The DOM Renderer traverses through the render tree and calls the render function of each node along the way. The Block instance is passed into the render function, so that each node inserts the code into the appropriate create_fragment function.

The SSR Renderer, on the other hand, relies on different node handlers to insert strings or expressions into the final template literal.

The render function returns js and css which will be consumed by the bundler, via rollup-plugin-svelte for rollup and svelte-loader for webpack respectively.

Svelte runtime

To remove duplicate code in the compiled output, Svelte provide util function which can be found in the src/runtime/internal, such as:

  • dom related utils, eg: append, insert, detach
  • scheduling utils, eg: schedule_update, flush
  • lifecycle utils, eg: onMount, beforeUpdate
  • animation utils, eg: create_animation

Read More

Bread Scheduler – Bread recipes, planner and timer for better sourdough

Bread Scheduler – Bread recipes, planner and timer for better sourdough

Bread Scheduler – Bread recipes, planner and timer for better sourdough
Read More

Why build an entire computer on breadboards?

Why build an entire computer on breadboards?

More on breadboards: https://www.eater.net/breadboards
More on the 6502 project: https://www.eater.net/6502

Here are the graphing calculator models if you’d like to play with them:
https://www.desmos.com/calculator/txl…
https://www.desmos.com/calculator/i75…

Support these videos on Patreon: https://www.patreon.com/beneater or https://eater.net/support for other ways to support.

——————

Social media:
Website: https://www.eater.net
Twitter: https://twitter.com/ben_eater
Patreon: https://patreon.com/beneater
Reddit: https://www.reddit.com/r/beneater

Special thanks to these supporters for making this video possible:
Adam Lininger, Adrien Friggeri, Alexander Wendland, Andrew Miller, Andrew R. Whalley, Anthony Cuccia, Armin Brauns, Ben Dyson, Ben Kamens, Ben Williams, Bill Cooksey, Bouke Groenescheij, Bradley Pirtle, Bryan Brickman, Carlos Ambrozak, Charles Haseltine, Christopher Blackmon, Clayton Parker Coleman, Daniel Jeppsson, Daniel Struthers, Daniel Tang, Dave Walter, David Boardman, David Brown, David Clark, David H. Friedman, David House, David Sastre Medina, David Turner, Dean Winger, Dirk Lentzen, Dmitry Guyvoronsky, Dzevad Trumic, Eric Brummer, Eric Busalacchi, Eric Dynowski, Eric Twilegar, Erik Broeders, Eugene Bulkin, fxshlein , George Miroshnykov, Harry McDow, HaykH , Hidde de Jong, Ian Tait, Ingo Eble, Ivan Sorokin, Jason DeStefano, Jason Specland, JavaXP , Jay Binks, Jayne Gabriele, Jeremy A., Jeremy Wise, Joel Jakobsson, Joel Messerli, Joel Miller, John Fenwick, John Meade, Jon Dugan, Jordan Scales, Joshua King, Kefen , Kent Collins, Koreo , Lambda GPU Workstations, Lucas Nestor, Lukasz Pacholik, Maksym Zavershynskyi, Marcus Classon, Martin Roth, Mats Fredriksson, Matt Alexander, Matteo Mohr, Matthäus Pawelczyk, Michael , Michael Burke, Michael Garland, Michael Tedder, Miguel Ríos, Nicholas Counts, Örn Arnarson, Örper Forilan, Paul Pluzhnikov, Paul Randal, Pete Dietl, Philip Hofstetter, Randy True, Ric King, Richard Wells, Rob Bruno, Robert Butler, Robert Diaz, Sachin Chitale, Sam Rose, Sam Soffes, Scott , Sergey Ten, SonOfSofaman , Stefan Nesinger, Stefanus Du Toit, Stephen Riley, Stephen Smithstone, Steve Jones, Steve Gorman, Steven Pequeno, Tom Burns, Vladimir Kanazir, Warren Miller, xisente , Ziggy L

Read More

Vuln Cost

Vuln Cost

Security scanner for VS Code

Vulnerability scanning in VS Code

Find security vulnerabilities in open source npm packages while you code. Receive feedback in-line with your code, such as how many vulnerabilities a package contains that you are importing. And the best thing is, it’s FREE.

Detect vulnerabilities in third-party open source packages automatically while you code.

Find security vulnerabilities in the npm packages you import:

See the number of known vulnerabilities in your imported npm packages as soon as you require them!

See your project vulnerabilities inline,
as you code:

See feedback directly in your editor. Vuln Cost displays the number of vulnerabilities your packages add to your project.

Find security vulnerabilities in your JavaScript packages from well-known CDNs:

Vuln Cost scans any HTML files in your projects and displays vulnerability information about the JavaScript packages you download from your favorite CDN.

See in-depth information about your vulnerabilities:

Access relevant resources that will give you deeper information about the vulnerabilities that directly affect your project.

“Connecting the Vuln Cost plugin to a FREE Snyk account gives you even targeted and detailed information about the vulnerabilities you include in your projects.”

When you connect using a free Snyk account from the Vuln Cost extension we provide you with an even better experience, including more actionable information on the package you import.

A vulnerability severity level

Some vulnerabilities are more dangerous than others. With Snyk powering Vuln Cost we will instantly show you the severity levels of all your vulnerabilities.

Direct and indirect issues

Vuln Cost provides you a detailed overview of where the security issues exist in your project. This might be in a direct or a transitive dependency

Remediation advice

Where possible we provide you with package upgrade advice to the closest version containing a fix for your vulnerabilities.

Read More

Bose QC 35 Firmware 4.5.2 Noise Cancellation Investigation Report

Bose QC 35 Firmware 4.5.2 Noise Cancellation Investigation Report

Hello everyone, 

To preface this post, the content you will find below is a rich summary of the testing and history regarding our QC35 Acoustic Noise Cancelling performance and firmware 4.5.2. Our community members spent many hours providing us with feedback and we wanted to make sure we provided a comprehensive and detailed summary on our approach to evaluating your concerns and testing the product to understand if there was an issue.  

When we launched QC35 I and II, we set stringent specifications for Noise Cancelling performance. Through all of our investigation and testing, we’re confident that firmware 4.5.2 did not affect the noise cancelling feature. As with any of our products, if you are not satisfied with the performance of your QC35s, please go to your regional support site to review the service options available to you.

With that being said, the newest information on the actions we have taken since our last communication are towards the bottom of this post. If you are interested in our findings from our in-home visits click here. If you would like to see the results of our engineering analysis from the returned Headphones we received, click here. If you are interested in what we are doing about it, click here.

An Overview of Bose Noise Reduction Technology

History

Initial Engineering Evaluation for Firmware 4.5.2 Feedback

Extended Engineering Evaluation

What are we doing about it

Conclusion

An Overview of Bose Noise Reduction Technology

Bose QC35 Noise Cancelling Headphones use a combination of both passive and active noise reduction technologies to deliver a high level of performance. This section provides a brief introduction to this technology and describes each of the different components as context for the balance of our findings.

Passive noise reduction is the result of the physical presence of the headphone covering your ears. Things like the fit and sealing of the headphones to the head, the earcup materials, as well as the design and attachment of the earcushions, which include a proprietary silicone gel layer, contribute directly to passive performance on our QC35s. Passive reduction generally increases as a function of frequency, with best reduction occurring at high frequencies.  

Feedback cancellation is achieved by the presence of a microphone near the ear inside the headphone. The system reacts in real-time to the instantaneous pressure inside the earcup, generating an opposing signal to cancel out noise. The system works best at lower frequencies.

Feedforward cancellation is achieved by microphones on the outward facing surface of the headphone. This system gives advanced notice of the noise environment before it reaches the ear, allowing the electronic system to predict and generate a matched cancellation signal. This system works best at low and mi frequencies.

Total noise reduction is the combination of all of these systems working together in harmony. If any of these systems are not functioning as designed, the impact on performance can be significant.

Note the terms “Noise Cancellation” and “Noise Reduction” are used throughout. Cancellation always refers to the performance component achieved with active electronics. Reduction doe not indication a specific method, but instead refers to the overall removal of noise, combining feedback, feedforward and passive technologies.

History

How we got here

On January 19, 2017, we released firmware 1.2.9.  We saw reports on the Bose Community Forum soon after that some users were having a poor audio experience. Some thought there was an issue with the Noise Cancelling feature. We investigated and found that their QC35s were connecting to the wrong Bluetooth profile, which was causing the poor experience. 

In response to that, we released firmware 1.2.10 on February 7, 2017. Following this release, some people were still concerned about the Acoustic Noise Cancelling featureWe took these reports seriously and our engineering team conducted a thorough analysis of all field reports collectedinitiated a product sampling program to test customer units, reexamined our software changes, and performed A/B testing using various product development and manufacturing validation test methodologies. We heard your concerns and did everything we could to confirm that the Acoustic Noise Cancellation technology on our QC35 headphones was working the way it should. 

Similar concerns resurfaced with subsequent firmware releases post firmware 1.2.10 but the feedback never reached the magnitude we saw during the first releaseEach time we always worked with the community to address the concerns and monitored the situation closely. The feedback never reached the magnitude we saw during the first release. 

However, this changed on June 12, 2019 with our latest firmware update 4.5.2 , even though no firmware changes were made to the noise cancelling feature. Many community members shared their concern on our forum.  

Initial Engineering Evaluation for Firmware 4.5.2 Feedback 

Bose has read every post on the subject and we want to thank all of those who provided important and descriptive feedback of their experiences. We use this information to help replicate customer issues, identify software bugs, modify existing features and also implement new ones.  

 
Here are the most common things we heard from the Bose forum: 

  • Updating to the new firmware results in reduction of Active Noise Cancelling performance 
  • Inability to toggle between Noise Cancelling “High”, “Low”, and “Off” 
  • Some outlets are claiming that there is a change in Active Noise Cancelling 
  • During phone calls, the Active Noise Cancelling does not work, is broken, or amplifies the world. 
  • Bose reduced the ANR performance of QC35 ANR to encourage upgrades to Bose Headphones 700. 

QC35 headphones are engineered to deliver world-class Noise Cancellation and we would never intentionally downgrade the performance of our products in the field. Our firmware update strategy is focused on improving product performance, adding new features, fixing bugs and maintaining interoperability. 

Engineering Deep Dive – Firmware 4.5.2

Bose immediately set up an engineering team to review the software qualification test results and our code to determine if we had unintentionally made changes which could impact our Noise Cancelling feature. During our investigation we: 

  • Conducted an extensive review of the firmware code (internally and with an outside contractor) 
  • Reviewed and repeated manual and automated firmware Quality Assurance testing 
  • Dedicated dozens of hours from our firmware Development and Quality Assurance teams attempting to replicate customer issues 

Conclusion 

After completing this deep dive into the codebase and validation process, we confirmed that no changes were made to the firmware related to the noise cancelling featureconcluded that none of the firmware changes affected the Noise Cancelling feature indirectlyand that the new firmware passed all our test procedures. We also compared the noise cancelling performance running firmware version 4.5.2 to previous versions on new out-of-box units and existing ones and found no discernible differences. 

Customer Headphone Sampling and Testing

Given the history and the millions of units in the field, we continued to monitor the forum closely. As reports of issues with QC35 Noise Cancellation continued to grow into July, we began questioning whether our investigation truly covered all possible scenarios. Therefore, we initiated an effort to directly contact forum members in order to obtain the QC35 headphones they claimed were having issues 

This proved to be challenging and we only were able to get small number of headphones. Nevertheless, these units were put through a robust test process and were compared against known good reference samples.  Tests included the following: 

  • Controlled A/B Testing on Test Fixtures  Comparing noise cancelling performance between different headphones or under uncontrolled test conditions can be extremely challenging given the number of variables which can impact results. At Bose, we use very precise methods, repeatable measurement sequences and noise environments, and acoustically controlled test fixtures. We can also switch firmware versions back and forth on a test unit without disturbing the setup. 

An example of one type of QC35 Test Fixture
 

  • Real-World Performance Measurements on Human Subjects  Noise cancellation performance was measured on multiple human test subjects using tiny microphones placed inside the ear canal.  This produces a quantified measurement of the reduction of noise at a user’s ears when wearing and operating the headphones.  
  • Critical Listener Evaluation – In addition to objective performance measurements, Bose maintains a team of trained critical listeners to judge subjective performance of all audio products. Members of this team performed subjective testing of the headphones in controlled noise environments.  Evaluations were performed running each firmware revision in various states (High/Low/Off) of the returned headphones. 

Conclusion 

This robust evaluation of customer-returned units did not reveal any issues with noise cancellation performance, and Bose was not able to replicate the concerns of our customers. Even still, wvalued your feedback and remained determined to continue our investigation to understand why our results did not match the reports from the community 

Extended Engineering Evaluation 

In an effort to better understand why our results were not matching the feedback we were receiving from some members on the forum, we began a new set of activities to dig deeper.  This next phase of our investigation included 3rd party independent testing, direct customer engagement, and an initiative to get back as many headphones as possible from customers. 

3rd Party Testing

To gain an independent assessment, we commissioned a third-party acoustics test laboratory to conduct a set of measurements of the impact of firmware 4.5.2 on noise cancellation performance. 

Michael & Associates is the only test lab in the US accredited by the National Institute of Standards and Technology (NIST) National Laboratory Voluntary Accreditation Program (NVLAP) for the purposes of measuring hearing protection. 

Without Bose involvement, Michael & Associates purchased 5 new QC35 headphones, running 4.1.3 firmware, to evaluate.  The measurements were taken using a GRAS 45CA ANSI Acoustic Test Fixture, a device designed to the requirements of ISO 4869-3 for use in measuring hearing protectors, primarily for quality assurance purposes. 

The headphones were placed on the test head, measured first in their initial out-of-box state, and then again after updating the firmware to 4.5.2.  The headphones were updated using the Bose Connect app and were not moved or disturbed during the test.   

Conclusion 

For all 5 headphones, both Left and Right earcups, no loss of noise cancellation performance was measured after updating the firmware to 4.5.2.  A small change was observed, with slightly higher performance for the post-update condition, by on average 0.4dBA, an imperceptible amount.  Bose engineering does not believe that this increase was due to firmware changes, but rather was an artifact of the test sequence and fixturing, which could not control for all variables. 

 Test results show no loss of noise cancellation after updating firmware to 4.5.2 

In-Home Visits

In the past, when our data did not match the experiences our customers were reporting, we have found tremendous value in learning directly from those customers and experiencing the product in their environment. At times, this can reveal unique findings that could not have been easily replicated in a lab setup 

We created a survey on the Community that screened customers to find those who identified they were experiencing issues with the noise cancellation function still had the headphones in their possession, and were open to a visit from Bose. We heard from over 150 customers, all of whom were contacted directly by our customer service team. We followed up with 60 of the 150 customers for more in-depth interviews, and then ultimately visited 5 customers for 2-hour in-home sessions. 

For these 5 in-home visits, we put together a set of interview questions and activities to try to understand these participants’ experiences better.  

Our goals for the in-home visits were:  

  1. Understand specific details of the customer’s experiences using QC35s 
  2. Understand if the customer’s paired device and updating method resulted in a defective update or produced an unexpected device state (for example, the product is stuck in Low noise cancellation mode even if High mode is selected) 
  3. Give Bose engineering a firsthand experience with the customer’s headphones
  4. Give customers the opportunity to experience a knowngood QC35 in their home environment 
  5. Exchange customer’s headphones for a brand-new pair, and bring suspect headphones back to Bose for detailed engineering analysis 

During the home visits, Bose representatives – a senior acoustical engineer and a user experience researcher – brought two pairs of QC35s with 4.1.3 firmware (as manufactured). One of these headphones was set aside to be used as the reference.  For the second pair, the participants were asked to update the firmware to 4.5.2 using the same method and device that they used when updating their personal QC35s.  

While the update process was running, the participant and the Bose researcher engaged in an in-depth conversation about the participant’s headphones, their typical usage behaviors, their firmware updating experience, and their expectations with the noise cancelling function. Each participant was asked to describe in detail the circumstances where they first noticed a change in performance, providing as many specifics to the researcher as possible.   

Following the completion of the headphones’ update, both the participant and the Bose engineer completed a series of A/B listening tasks with the three pairs of QC35s: 

The Bose team set up a simulated airplane cabin noise environment using a Bose S1 speaker and a sound level meterThis noise environment was chosen for its low frequency contentwhere the active noise cancellation technology is most effective, making it easier to detect changes with this function.  Four use states were demonstrated to the participant to use as anchors for comparison using the reference headphones and the scale below.  These anchor points represent the noise levels experienced under the following conditions: 

  • User is not wearing the headphones 
  • Headphones are worn on head, but noise cancellation is Off 
  • Noise cancellation on, set to Low mode 
  • Noise cancellation on, set to High mode 

Note that no audio was played through the headphones during the evaluation. 

The reference scale used for A/B testing. 

After the participants were accustomed to the reference headphones and the four anchor points on the scale, A/B comparisons began.  

Participants were asked to evaluate the following A/B pairings: 

  • Reference QC35 (4.1.3) vs. Live Updated QC35 (4.5.2) at High Noise Cancellation 
  • Reference QC35 (4.1.3) vs. Live Updated QC35 (4.5.2) at Low Noise Cancellation 
  • Reference QC35 (4.1.3) vs. Participant’s QC35 (4.5.2) at High Noise Cancellation 
  • Reference QC35 (4.1.3) vs. Participant’s QC35 (4.5.2) at Low Noise Cancellation 

Participants alternated between the two pairs of headphones, repeating the process as many times as needed to make an assessment. 

An example of the A/B test setup. 

Following this listening experience, participants discussed what they heard, and then rated how the updated headphones sounded relative to the reference headphones.  

Throughout this session, the Bose engineer also listened to the pairs of headphones and made comparisons but did not share this information to ensure that the participant’s ratings were made independently. 

At the end of the in-home visit, we exchanged the participant’s headphones for a brand-new pair of QC35s.  The participant’s headphones were brought back to Bose for a detailed engineering analysis to determine if the headphone hardware was still performing according to factory specs. 

Conclusion 

Based on what we learned, the following items were determined to not be a factor for these customers: 

  • Updating method 
  • Device type interactions 
  • Bluetooth pairing list device quantity 
  • Problems with headphone fit and seal due to changes in hairstyles, headware, jewelry, etc. 
  • No observations of unintended mode switching, or locked out controls of noise cancellation modes 

The noise environment where a product is used can influence the perception of noise reduction.  Some customers did report changes to their noise environments such as changing jobs and working in a new open office or commuting on a different train after moving. One such customer reported hearing more office voice noise while not playing music. 

In several conversations with customers, there was some confusion about noise cancellation function during a phone call or other Bluetooth HFP connection.  QC35 contains a feature called Self Voicesometimes referred to as Sidetone, where the audio from the voice pickup microphones is amplified and added into the audio stream.  This enables you to better hear your own voice while speaking during a phone call, giving you the ability to monitor the volume of your voice.  The result is a more natural conversation, which helps prevent you from talking too loudly.  While noise cancellation remains active and unchanged during phone calls, a customer may perceive the added Self Voice audio as a degradation of noise cancellation function, especially when in a noisy environment. 

As expected with any subjective audio test, there was some variation in how the participants perceived the noise reduction on the different headphones, but generally, the participants thought that the three headphones all sounded similar.  Neither any participant nor the Bose engineer observed noticeable changes in performance after updating the headphone firmware to 4.5.2 live during the visits. 

For the participant’s’ own headphones, however, there was one visit where a more substantial difference was observed.  Both Participant-2 and the Bose engineer scored this participant’s personal headphones as sounding similar to the reference for Low mode performance while operating in High mode.  Switching between Low and High for this headphone produced only a small change in performance, much less than with the reference headphones.  Subsequent engineering analysis, covered in the next section, found an explanation for this result unrelated to product firmware. 

We found the home visits to be insightful and are always appreciative of the opportunity to learn more directly from our customers. We thank everyone whom we visited and those who volunteered through our survey.  

Engineering Analysis of Returned Headphones

In order to maximize the number of samples, we used the interview process described earlier to retrieve additional headphones from community members who had reported having issues and combined these with the exchanged participant units obtained during our visits. 

In total, 5 headsets were taken directly from participants, and another 5 headsets were returned to the engineering team through the phone interview process.  These 10 headsets were running firmware 4.5.2, as updated by the customers themselves.  A reference headphone, with measured average performance, was included for comparison.  For these headsets, a series of tests were conducted including: 

  • Electrical system evaluation 
  • Mechanical system evaluation 
  • Acoustic hardware function 
  • Microphone and driver function and health 
  • Factory endofline testing on the full headphone for both feedback and feedforward noise cancellation systems and music playback performance 
  • Independent measurements on all contributing systems to noise reduction performance 
  • Real world noise reduction measurements on human heads in controlled noise environment 
  • Bose critical listener evaluation for noise reduction performance 

Key findings: 

Of the 10 customer headphones evaluated, 8 performed within specification limitsand 2 were found to be out of spec. Subjective critical listening at Bose confirmed that these 2 headphones were noticeably different from the reference QC35, and that the others were performing within the normal range of expected product variation.  Measurements of noise reduction performance on human subjects was particularly revealing, showing the following results when measured in High mode: 

 Test results of total noise reduction performance on the 10 headphones returned by customers, compared to a reference QC35 headset.  Lines showing typical performance for High and Low noise cancellation modes are shown for illustration. 

Root cause analysis was conducted on the 2 lower-performing headphones, revealing the following issues: 

  • Participant2 Headphone 
    • This headphone had one earcushion that was not fully snapped on (one snap was undone on the Right earcup) 
    • In addition, this headphone had replaced the original Bose earcushions with 3rd party aftermarket earcushions.  These aftermarket cushions negatively impacted passive reduction performance and affected the headphone’s acoustic output to be out of spec on both the Left and Right sides. 
    • This headphone also had suffered mechanical damage.  The acoustic subsystem responsefor both Left and Right sides remained out of spec even when Bose authentic earcushions were attached. 
    • This participant noted that they did not use the case to store and transport their headphones while commuting every day.  
  • Return-4 Headphone 
    • This headphone had one earcushion that was not fully snapped on (one snap was undone on the Left earcup) 
    • Normal performance was recovered when the snap was fully engaged 

  

One snap undone as observed on a customer returned QC35 

A Bose authentic earcushion on the left, an aftermarket earcushion on the right.  Though the appearance is similar, the aftermarket cushions do not contain the proprietary design features to deliver the acoustic performance and passive noise reduction benefits that authentic Bose cushions provide.

Conclusion 

After evaluating customer returns from forum members and through in-home visits, we concluded that some customers’ headphones did demonstrate reduced overall noise reduction performance. However, our full engineering analysis determined that the degradation in all cases was the result of hardware related issues with earcushions, aftermarket parts, or mechanical integrity. Once again, the firmware update 4.5.2 was not found to be the cause of any degradation in overall noise reduction performance. 

What are we doing about it

Updated test procedures

Even though we could not attribute any noise reduction performance loss to the QC35 4.5.2 firmware, during our exploration of the issue we did uncover some new use cases and gained additional insights from how customers update our products in the field. As a result, we performed these new tests as part of our investigation and have already updated our firmware qualification test process to include these for all new releases.  

Service Videos

We learned a lot from reading your comments on the forum, speaking to those who completed the survey, and visiting some customersAs such, we decided there was an opportunity to supplement our service videos with additional information. Our newest video on our website or our support page on YouTube covers the following topics: 

  • Headphone Maintenance/Storage  how to properly store and maintain your headphone to prevent mechanical damage. 
  • Proper Cushion Attachment – it is critical that all 10 snaps on the cushion structure are properly inserted into their respective hooks on the ear cups.  Even one single unsnapped cushion can noticeably reduce noise cancellation performance. 
  • Use of Authentic Bose Replacement Cushions  QC35 replacement cushions are the same ones we use in manufacturing – they’re just packaged differently for service. This means they utilizes our proprietary protein leather and silicone-gel technologyas well as our precision design and manufacturing tensure a reliable seal when properly installed on a Bose QC35 headphone, thereby delivering the same acoustic characteristics for optimum performance.  
  • Self-Voice – During a phone call, the headphone uses a Bluetooth mode called Hands-Free Profile (HFP).  In this mode, the headphones utilize the Self-Voice feature to improve the communication experience.  Under these circumstances, it may appear that noise cancellation performance has been compromised. 

 Please watch the video below!

BTU Updater Site

During our customer visits, we realized there was some confusion around the version of firmware on a product and the version of the Voice Prompts. Our over-the-air updates via the app are able to update the headphone firmware, but for QC35, it does not update the Voice Prompts. To update to the latest Voice Prompts, customers can use the Bose Updater tool.  

To reduce confusion, we have updated our messaging to more clearly explain the difference. We also tested all combinations of firmware and Voice Prompt versions to ensure this didn’t impact our noise cancelling performance and added this to our standard testing procedure for all future code releases. 

Downgrade

An important piece of feedback we’ve received from the community during this discussion is that you want the ability to downgrade the firmware on your Bose QC35 product. Today, we’re re-introducing the ability to downgrade firmware QC35 II to 4.3.6 and QC35 series 1 to 2.5.5 via the Bose BTU site for a limited time. Further communication regarding the availability of the downgrade option will be posted to the community at a later date, but if you wish to take advantage of this downgrade option, we advise you to do so as soon as possible.  

Just to reiterate, based on our findings and testing to date, we are confident the QC35 firmware does not impact noise cancelling performance. If you are experiencing any noise cancelling-related concerns, please contact us directly if you haven’t done so already.  

We strive to continuously improve our products through software updates that fix software bugs, ensure continued interoperability as companies launch new phones and operating systems, enhance existing features, and add new ones. We encourage customers to remain on the current version of firmware and always upgrade when new releases are available to benefit from these improvements. 

Self Voice

We are exploring options to allow you to modify how this feature works via the Bose Connect app. If this is an area of interest to you, please stay tuned as we hope to provide an update on feasibility and timing for this work. 

Conclusion

We want to thank our wonderful Bose community for sticking with us through this process and reading this post. As we hope you can tell, we take customer feedback very seriously and we’re dedicated to making sure the QC35s you hold in your hand are the best possible product we can make. When you said you disagreed, we listened. We tested. We came to you. 

We understand this is a lot to take in and we’re sure that you have plenty of thoughts. And we want to hear them. You can click here to go to a thread where you can discuss our findings and what’s to come with other members of the Bose community. 

Thanks, 

The Bose QC35 Engineering team 

Read More

iPhone 12 may get this huge Siri upgrade

iPhone 12 may get this huge Siri upgrade



(Image credit: Future)

Siri is so far behind the competition that we left Apple’s digital assistant out of our recent Alexa vs Google Assistant face-off. Not only does Siri have a lot less skills than its rivals, it often has difficulty understanding listeners and processing requests. But help is on the way in the form of Apple’s shiny new purchase.

As reported by Bloomberg, Apple has acquired Voysis, a Dublin-based AI startup that should be able to help Siri better understand natural language. There’s no timetable for Voysis getting integrated into Siri, but this secret weapon would certainly help the upcoming iPhone 12 and other iPhones stand out versus the best Android phones.

What could Siri help you do better? Shopping is definitely high on the list. A now-removed Voysis company webpage gave the example of how users could narrow product search results by combining parameters. So you could say “I need a new LED TV” and “My budget is $1,000.”

In a video that’s still on YouTube — for now — Voysis describes itself as a “complete voice AI platform.” And it shows a furniture retailer example where a person uses natural language while shopping online. The shopper first says, “I’m looking for coffee tables.” Then he follows up with “show me modern ones with round glass tops.”

To further narrow his search, the shopper says “Just show me ones that are lighter.” And he also adds his price range, saying “My budget is only $500.” With each command the search results further narrow.

I could easily see Apple integrated Voysis into its own apps, such as the App Store for finding specific types of games or in Apple TV Plus for discovering shows to watch. But things will get a lot more interesting if Apple opens up this platform to developers.

Voysis was already providing its AI to other companies to incorporate it into their apps and voice assistants, so it’s reasonable to assume that Apple would integrate this technology directly into Siri and then allow iOS developers to tap into it.

As Bloomberg reports, Voysis would take up very little room. The company’s co-founder said in 2018 that he shrunk the system down to the point that the software uses just 25MB of memory. Perhaps this will allow Apple to put more of Siri’s intelligence directly into its phones and rely less on the cloud, as the latter leads to much greater latency.

Google Assistant already has a huge head start in this regard. The latest version of is slim enough to run directly on Android phones and can process requests up to 10 times faster than before. 

It’s unlikely that this newly acquired technology would be ready in time for iOS 14, which will be shown off for the first time at Apple’s all-digital WWDC 2020 event. But it’s possible that Apple could deliver at least some Voysis features via a subsequent update to Apple devices in time for the iPhone 12 launch this fall.

Read More

Sony battles to scrub leaked The Last of Us 2 footage from the internet

Sony battles to scrub leaked The Last of Us 2 footage from the internet

Just days after its indefinite delay.

Sony is battling to scrub leaked The Last of Us 2 footage from the internet just days after announcing an indefinite delay to the hotly-anticipated game.

Yesterday, two videos containing previously unseen footage of Naughty Dog’s next hit the internet, and as you’d expect they were pounced upon by the series’ fans.

THERE MAY BE SPOILERS AHEAD.

One of the clips shows Ellie and Dina riding horses in the snow while having a chat about a movie series.

The more interesting video shows what looks like a guitar-playing mini-game. We see Ellie practice guitar, with the player able to play chords via a command wheel and strum via swiping on the DualShock touchpad.

The original YouTube uploads are now offline, the first made private, the second the result of a copyright claim by Sony Interactive Entertainment LLC. Sony is currently moving to delete mirrors of the footage, although it faces an uphill battle. I suspect the two videos embedded above will be pulled offline sooner rather than later.

While it’s worth noting these clips are supposedly test footage and may not represent any sequence in the final game, it’s an unfortunate leak for Naughty Dog, which only a few days ago announced an indefinite delay to The Last of Us 2 as a result of the ongoing coronavirus pandemic.

“Logistically, the global crisis is preventing us from providing the launch experience our players deserve,” Sony said, before Naughty Dog added development on The Last of Us Part 2 is “nearly done” and that the studio is currently “in the midst of fixing our final bugs”.

Read More

Forget Zoom: Skype unveils free ‘Meet Now’ video calls

Forget Zoom: Skype unveils free ‘Meet Now’ video calls



(Image credit: Skype)

There’s no question that Zoom has quickly become the leader in video meetings and video calls during the coronavirus pandemic. It offers free, 40-minute conference calls with up to 100 attendees, and lots of people are using this tool to stay in touch and have fun with features like swapping out Zoom backgrounds.

But there’s also serious questions about Zoom’s security and privacy issues, only some of which the company has addressed thus far. In order to capitalize on Zoom’s troubles, Skype has rolled out Skype Meet Now calls that don’t require a sign-up or installation.

Here’s how it works. Meet Now allows you to host conference calls by generating a free unique link with one click. You then share that link with participants to enjoy unlimited meetings via Skype. According to Microsoft, which owns Skype, your meeting link does not expire and can be used at any time.

Skype says that you’ll be able to leverage its features during your video conferences. This includes the ability to record your call and save it for later. The company stores your recording for 30 days. You can also blur your background before entering the call, which is helpful for those of us are don’t have the neatest home office or who have pets or children jumping in and out of the frame.

With Skype Meet Now, you can also share your screen at any time, which makes it easier to collaborate with colleagues and share presentations with a group.

Meet Now works on any device with the Skype app installed, and you don’t even need a Skype account to join these calls. You can also use the Skype web client for making calls.

Read More

GameStop offers Nintendo Switch Lite starter bundle with Animal Crossing, $20 eShop gift card

GameStop offers Nintendo Switch Lite starter bundle with Animal Crossing, $20 eShop gift card


Vox Media has affiliate partnerships. These do not influence editorial content, though Vox Media may earn commissions for products purchased via affiliate links. For more information, see our ethics policy.

Nintendo Switch consoles have been hard to find lately — retailers have been sold out for months — but the handheld-only Switch Lite is in stock most places. GameStop, however, is offering a new Nintendo Switch Lite starter bundle. In addition to a $10 discount on the console, GameStop is throwing in a $20 Nintendo eShop gift card and a copy of the Switch game of the moment, Animal Crossing: New Horizons, as well as an all-important screen protector. (Protect your screens, people!)

Xbox One users can get six months of the company’s joint online and game subscription service, Xbox Game Pass Ultimate, for the price of three months with an offer from Amazon. The retailer is throwing in an extra three months when you purchase a three month subscription card for the standard $45.

Finally, Amazon and Target are both still running their buy-two-get-one free sales on video games and board games. Bestselling titles like Doom Eternal, Catan, and the Dungeons & Dragons Starter Set are included in the offer.

Consoles and TVs

Video games

Accessories

Movies

Read More