Skip to main content

Namespaces

On this page

Namespace (ns)#

Every Phel file needs a namespace. Names start with a letter, then letters/numbers/dashes. Parts separated by . (canonical) or \ (legacy, still parses). Last part must match filename.

(ns name imports*)

Sets the namespace and registers imports. :use for PHP classes, :require for Phel modules, :require-file for PHP files.

(ns my.custom.module
  (:require-file "vendor/autoload.php")
  (:require my.phel.module)
  (:use Some.Php.Class))

Also sets *ns* to the namespace.

PHP Coming from PHP?

Similar to PHP namespaces, with differences:

// PHP
namespace My\Custom\Module;
use Some\Php\Class;
use My\Phel\Module as Utilities;

// Phel
(ns my.custom.module
  (:use Some.Php.Class)
  (:require my.phel.module :as utilities))

Differences:

  • . separator for Phel namespaces (PHP class FQNs in :use use .)
  • :require for Phel modules, :use for PHP classes
  • Access via /, not ::
Clojure Coming from Clojure?

Like Clojure: . namespace separator. PHP class FQNs in :use use ..

  • :use is for PHP classes
  • :require works as in Clojure

Import a Phel module#

Import with :require, then access as module/name. Namespaces resolve from src/ (override with configuration).

Module util in namespace hello-world:

(ns hello-world.util)

(def my-name "Phel")

(defn greet [name]
  (print (str "Hello, " name)))

Module main imports util:

(ns hello-world.main
  (:require hello-world.util))

(util/greet util/my-name)

Use aliases to avoid collisions:

(ns hello-world.main
  (:require hello-world.util :as utilities))

On collision, use a fully-qualified name to reach the original. A locally defined get shadows phel.core/get by its short name, but the full phel.core/get still works:

(ns hello-world.http-client)

(defn get [uri]
  {:status 200 :body "Hello World" :headers {}})

(phel.core/get (get "https://example.com") :status) ; Evaluates to 200

:refer brings symbols into the current namespace:

(ns hello-world.main
  (:require hello-world.util :refer [greet]))

(greet util/my-name)

:refer and :as combine in any order.

Import a PHP class#

:use imports PHP classes:

(ns my.custom.module
  (:use Some.Php.ClassName))

Reference by name:

(ClassName.)          ; preferred shorthand
(php/new ClassName)   ; also valid

Aliases avoid collisions:

(ns my.custom.module
  (:use Some.Php.ClassName :as BetterClassName))

Importing is preferred, but optional. Use full namespace inline if needed:

(php/new Some.Php.ClassName)   ; or: (Some.Php.ClassName.)

Require PHP files#

Load external PHP files via :require-file (calls require_once). Example for Composer autoload:

(ns hello-world.main
  (:require-file "vendor/autoload.php"))

(php/require_once "vendor/autoload.php") works elsewhere, but for autoload it runs too late since Phel's core needs the autoloader. Use :require-file.

Namespaced keywords#

Plain keywords collide when sharing data. Namespaced keywords solve this.

Fully qualified: namespace, /, keyword name.

:my.namespace/foo ; absolute namespaced keyword

:: shortcut binds current namespace:

(ns bar)
::foo ; => :bar/foo

ns aliases also work:

(ns foobar
  (:require abc.xyz :as bar))

::bar/foo ; evaluates to :abc.xyz/foo