Functions
Functions have two types of parameters:
- Positional parameters, which require an argument.
- Named parameters, which optionally take an argument, otherwise using their default value.
So this function is named fahrenheit_to_celsius
and has one parameter temp
:
PRQL
let fahrenheit_to_celsius = temp -> (temp - 32) / 1.8
from cities
derive temp_c = (fahrenheit_to_celsius temp_f)
SQL
SELECT
*,
((temp_f - 32) / 1.8) AS temp_c
FROM
cities
This function is named interp
, and has two positional parameters named high
and x
, and one named parameter named low
which takes a default argument of 0
. It calculates the proportion of the distance that x
is between low
and high
.
PRQL
let interp = low:0 high x -> (x - low) / (high - low)
from students
derive {
sat_proportion_1 = (interp 1600 sat_score),
sat_proportion_2 = (interp low:0 1600 sat_score),
}
SQL
SELECT
*,
((sat_score - 0) / (1600 - 0)) AS sat_proportion_1,
((sat_score - 0) / (1600 - 0)) AS sat_proportion_2
FROM
students
Piping values into functions
Consistent with the principles of PRQL, it’s possible to pipe values into functions, which makes composing many functions more readable. When piping a value into a function, the value is passed as an argument to the final positional parameter of the function. Here’s the same result as the examples above with an alternative construction:
PRQL
let interp = low:0 high x -> (x - low) / (high - low)
from students
derive {
sat_proportion_1 = (sat_score | interp 1600),
sat_proportion_2 = (sat_score | interp low:0 1600),
}
SQL
SELECT
*,
((sat_score - 0) / (1600 - 0)) AS sat_proportion_1,
((sat_score - 0) / (1600 - 0)) AS sat_proportion_2
FROM
students
and
PRQL
let fahrenheit_to_celsius = temp -> (temp - 32) / 1.8
from cities
derive temp_c = (temp_f | fahrenheit_to_celsius)
SQL
SELECT
*,
((temp_f - 32) / 1.8) AS temp_c
FROM
cities
We can combine a chain of functions, which makes logic more readable:
PRQL
let fahrenheit_to_celsius = temp -> (temp - 32) / 1.8
let interp = low:0 high x -> (x - low) / (high - low)
from kettles
derive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)
SQL
SELECT
*,
((((temp_c - 32) / 1.8) - 0) / (100 - 0)) AS boiling_proportion
FROM
kettles
Late binding
Functions can bind to any variable that is in scope when the function is executed. For example, here cost_total
refers to the column that’s introduced in the from
.
PRQL
let cost_share = cost -> cost / cost_total
from costs
select {materials, labor, overhead, cost_total}
derive {
materials_share = (cost_share materials),
labor_share = (cost_share labor),
overhead_share = (cost_share overhead),
}
SQL
SELECT
materials,
labor,
overhead,
cost_total,
(materials / cost_total) AS materials_share,
(labor / cost_total) AS labor_share,
(overhead / cost_total) AS overhead_share
FROM
costs