Functions provide a means of composing interactions into parameterized goals or, in other words, a way to programmatically break off a flow into re-usable code.
In a single snippet, here’s what the structure of defining a function looks like:
function_name <|> args... <|
function_body |
It starts with the function’s name separated from its arguments by a <|> operator which is then followed by a <| operator and the function body before being closed by a vertical bar | at the end.
The name of the function is the symbol to which the function’s defintion is being ASSIGNed to. To invoke the function later on in LSD SQL, treat the function’s name as though it were a keyword.
foo <|> args... <| body...|
FROM url
|> foo arg_1 arg_2
|> ...
The arguments of the function allow you to re-use parts of your code without unnecessarily repeating lines over and over. Separate the names of arguments by spaces between the <|> and <| operators then you can refer to the placeholders in the function body so that, as the function gets called with arguments provided, the values are filled in when evaluating.
foo <|> arg_a arg_b <|
FROM arg_a
|> CLICK ON arg_b |
foo "https://lsd.so" a
In this example, the value arg_a in the line containing the FROM expression would be replaced value the value “https://lsd.so” as it’s the first argument provided to the foo call at the bottom of the LSD SQL above and a would fill in for arg_b in the CLICK line.
The body of the function is the repeatable procedure that is invoked when the function gets called. All assignments are inherited from the LSD SQL that led to the function being called similar to how function decorators work in other languages.
Arguments can be either variables or values that would be valid as variables. Since functions expect arguments to be defined and called with arguments being space separated, we recommend using named variables when working with functions.
static_value <| a[href="/docs"] |
click_followed_by_another_click <|> starting_url follow_up <|
FROM starting_url
|> CLICK ON static_value
|> CLICK ON follow_up
|> SELECT title |
click_followed_by_another_click "https://lsd.so" a[href="/docs/database"]
In this example, even though the assignment for static_value is happening in the top-level program itself and not inside the click_followed_by_another_click function, it’s still inherited when called at the bottom of the LSD SQL above.
To invoke a function later in LSD SQL, treat the function’s name as though it were a keyword at the start of a line followed by any arguments provided.
foo <|> arg <|
CLICK arg
|> SELECT title |
FROM some_url
|> foo div#selector
In this example, the name foo is being treated as though it were a keyword after the |> operator at the bottom of the LSD SQL above.
Inspired by the example in our ZIP docs, let’s write an LSD SQL trip that remixes together the questions from Ask HN with the scores of posts on the front page of HN.
Taking advantage of how Hacker News structures their views with the same elements and styles, we can modify the functions from the ZIP example to take in a URL and return the corresponding fields from that page.
hn <| https://news.ycombinator.com |
ask_hn <| https://news.ycombinator.com/ask |
subtitle_container <| span.subline |
author <| a.hnuser |
score <| span.score |
title_container <| span.titleline |
post <| a |
post_link <| a@href |
get_post_conversations <|> hn_url <|
FROM hn_url
|> GROUP BY subtitle_container
|> SELECT author, score |
get_post_meta <|> hn_url <|
FROM hn_url
|> GROUP BY title_container
|> SELECT post, post_link |
get_ask_hn_posts <|> <|
get_post_conversations hn |
get_hn_post_meta <|> <|
get_post_meta ask_hn |
ZIP get_ask_hn_posts get_hn_post_meta