Skip to content

(:ref)

Signature:

clojure
(:ref [value])
(:ref [value])

Where value is a non-operator selector.

Dereferencing variable declarations

Variable declarations are dereferenced when the initializer (i.e. the right-hand side) is selected by the operand to (:ref), or when it is itself a reference to the value previously selected.

Querying for (:ref (num 1)) selects 1, a, b and c:

javascript
var a = 1; // selected
var b = a; // ref
var c = b; // ref of ref
var a = 1; // selected
var b = a; // ref
var c = b; // ref of ref

Dereferencing Array literals

Array literals are dereferenced when they contain an element that is selected by the operand to (:ref), or one that is itself a reference to the value previously selected.

Querying for (:ref (num 7)) selects x, y[0] and z[1]:

javascript
var x = 7 // selected
var y = [x] // ref
var z = [33, y[0]] // ref of ref
var x = 7 // selected
var y = [x] // ref
var z = [33, y[0]] // ref of ref

Dereferencing Array patterns

Array patterns that appear in variable declarations or in function parameters are dereferenced similarly to Array literals, i.e. when they contain an element that is selected by the operand to (:ref) or one that is itself a reference to the value previously selected.

Querying for (:ref (num 5)) selects 5, counts[0], userCount and users in the scope of displayCounts:

javascript
const counts = [5]
const [userCount] = counts
const displayCounts = ([users]) => {}
const counts = [5]
const [userCount] = counts
const displayCounts = ([users]) => {}

The referent may reside at any depth or index within the expression:

javascript
var [[[,,,,a]]] = [[[1,2,3,4,5]]]
var [[[,,,,a]]] = [[[1,2,3,4,5]]]

Dereferencing Object literals

Object literals are dereferenced when they contain a property whose value is selected by the operand to (:ref) or is itself a reference to the value previously selected.

Querying for (:ref (num 5)) selects 5, userCount, x.userCount and users:

javascript
var userCount = 5
var x = { userCount }
var { userCount: users } = x
var userCount = 5
var x = { userCount }
var { userCount: users } = x

The referent may reside at any depth within the expression:

javascript
var { a: { b: { c } } } = { a: { b: { c: 5 } } }
var { a: { b: { c } } } = { a: { b: { c: 5 } } }

Dereferencing Object patterns

Object patterns that appear in variable declarations or in function parameters are dereferenced similarly to Object literals, i.e. when one of their properties contains a value that is selected by the operand to (:ref) or is itself a reference to the value previously selected.

Querying for (:ref (num 5)) selects 5, counts.users, userCount and params.count in the scope of logCounts:

javascript
const counts = { users: 5 }
const { users: userCount } = counts
const logCounts = (params) => {}

logCounts({ count: 5 })
const counts = { users: 5 }
const { users: userCount } = counts
const logCounts = (params) => {}

logCounts({ count: 5 })

Dereferencing assignment patterns

Identifiers that appear in an assignment pattern are selected when the right-hand side is itself the value selected by the operand to (:ref) or a reference to it.

Querying for (:ref (num 3)) selects a in all statements:

javascript
var [a=3] = [1]
var {a=3} = {a:1}
function x(a = 3) {}
var [a=3] = [1]
var {a=3} = {a:1}
function x(a = 3) {}

Dereferencing function parameters

Function parameters are dereferenced when they are called by an expression whose arguments are selected by the operand to (:ref) or are themselves references to the value previously selected.

Querying for (:ref (num 1)) selects 1 and a in the scope of logNumbers:

javascript
function logNumbers(a, b, c) {
  console.log(a, b, c)
}

logNumbers(1, 2, 3)
function logNumbers(a, b, c) {
  console.log(a, b, c)
}

logNumbers(1, 2, 3)

Dereferencing function calls

Calls to functions are dereferenced when the function body is available and contains a return statement whose value is selected by the operand to (:ref) or is itself a reference to the value previously selected.

Querying for (:ref (of Promise)) selects new Promise() and x in the scope of usePromise:

javascript
function makePromise() {
  return new Promise()
}

function usePromise(x) {
  x.then()
}

usePromise(makePromise())
function makePromise() {
  return new Promise()
}

function usePromise(x) {
  x.then()
}

usePromise(makePromise())

Querying for (:ref (of Promise)) again selects new Promise(), x in the scope of identity and y:

javascript
const identity = (x) => x
const y = identity(new Promise())
const identity = (x) => x
const y = identity(new Promise())

Querying for (:ref (of Promise)) once more selects only new Promise() because we don't know what identity returns:

javascript
import { identity } from 'util'
const y = identity(new Promise())
import { identity } from 'util'
const y = identity(new Promise())

Dereferencing member expressions

Member expressions are dereferenced when they point to the referent or a reference to it.

Querying for (:ref (num 5)) selects 5, a.b and x:

javascript
var a = { b: 5 }
var x = a.b;
var a = { b: 5 }
var x = a.b;

Copyright © 2022-present Semantic Works, Inc.