-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathpal_roxygen.Rd
161 lines (133 loc) · 4.88 KB
/
pal_roxygen.Rd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/doc-pal-roxygen.R
\name{pal_roxygen}
\alias{pal_roxygen}
\title{The roxygen pal}
\description{
The roxygen pal prefixes the selected function with a minimal roxygen2
documentation template. The pal is instructed to only generate a subset
of a complete documentation entry, to be then completed by a developer:
\itemize{
\item Stub \verb{@param} descriptions based on defaults and inferred types
\item Stub \verb{@returns} entry that describes the return value as well as important
errors and warnings users might encounter.
}
}
\section{Cost}{
The system prompt from a roxygen pal includes something like 1,000 tokens.
Add in 200 tokens for the code that's actually highlighted
and also sent off to the model and you're looking at 1,200 input tokens.
The model returns maybe 10 to 15 lines of relatively barebones royxgen
documentation, so we'll call that 200 output tokens per refactor.
As of the time of writing (October 2024), the default pal model Claude
Sonnet 3.5 costs $3 per million input tokens and $15 per million output
tokens. So, using the default model,
\strong{roxygen pals cost around $4 for every 1,000 generated roxygen documentation
entries}. GPT-4o Mini, by contrast, doesn't tend to infer argument types
correctly as often and
often fails to line-break properly, but \emph{does} usually return syntactically
valid documentation entries, and it would cost around
20 cents per 1,000 generated roxygen documentation entries.
}
\section{Gallery}{
This section includes a handful of examples
"\href{https://github.com/hadley/elmer/tree/e497d627e7be01206df6f1420ca36235141dc22a/R}{from the wild}"
and are generated with the default model, Claude Sonnet 3.5.
Documenting a function factory:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{deferred_method_transform <- function(lambda_expr, transformer, eval_env) \{
transformer <- enexpr(transformer)
force(eval_env)
unique_id <- new_id()
env_bind_lazy(
generators,
!!unique_id := inject((!!transformer)(!!lambda_expr)),
eval.env = eval_env
)
inject(
function(...) \{
(!!generators)[[!!unique_id]](self, private, ...)
\}
)
\}
}\if{html}{\out{</div>}}
Returns:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{#' #' Transform a deferred method
#'
#' @description
#' A short description...
#'
#' @param lambda_expr A lambda expression to transform.
#' @param transformer A transformer function or expression.
#' @param eval_env The environment in which to evaluate the transformer.
#'
#' @returns
#' A function that, when called, will evaluate the transformed lambda expression.
#' The returned function accepts `...` arguments which are passed to the generated function.
#'
#' @export
}\if{html}{\out{</div>}}
A function that may raise a condition:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{set_default <- function(value, default, arg = caller_arg(value)) \{
if (is.null(value)) \{
if (!is_testing() || is_snapshot()) \{
cli::cli_inform("Using \{.field \{arg\}\} = \{.val \{default\}\}.")
\}
default
\} else \{
value
\}
\}
}\if{html}{\out{</div>}}
Returns:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{#' Set default value
#'
#' @description
#' A short description...
#'
#' @param value A value to check.
#' @param default The default value to use if `value` is NULL.
#' @param arg Optional. The name of the argument being set.
#'
#' @returns
#' Returns `value` if it's not NULL, otherwise returns `default`.
#' Informs the user when using the default value.
#'
#' @export
}\if{html}{\out{</div>}}
A function with some tricky indexing:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{find_index <- function(left, e_right) \{
if (!is.list(e_right) || !has_name(e_right, "index") || !is.numeric(e_right$index)) \{
return(NA)
\}
matches_idx <- map_lgl(left, function(e_left) e_left$index == e_right$index)
if (sum(matches_idx) != 1) \{
return(NA)
\}
which(matches_idx)[[1]]
\}
}\if{html}{\out{</div>}}
Returns:
\if{html}{\out{<div class="sourceCode">}}\preformatted{#' Find matching index
#'
#' @description
#' A short description...
#'
#' @param left A list of elements, each expected to have an 'index' field.
#' @param e_right A list with an 'index' field to search for in `left`.
#'
#' @returns
#' The numeric index in `left` where `e_right$index` matches, or NA if not found
#' or if inputs are invalid. Returns NA if multiple matches are found.
#'
#' @export
}\if{html}{\out{</div>}}
}
\section{Interfacing manually with the roxygen pal}{
Pals are typically interfaced with via the pal addin. To call the roxygen
pal directly, use:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{pal_roxygen <- .init_pal("roxygen")
}\if{html}{\out{</div>}}
Then, to submit a query, run:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{pal_roxygen$chat(\{x\})
}\if{html}{\out{</div>}}
}