Skip to content

tinyplot.R cosmetic refactor#464

Merged
vincentarelbundock merged 4 commits intograntmcdermott:mainfrom
vincentarelbundock:tinyplot_refactor_v1
Sep 9, 2025
Merged

tinyplot.R cosmetic refactor#464
vincentarelbundock merged 4 commits intograntmcdermott:mainfrom
vincentarelbundock:tinyplot_refactor_v1

Conversation

@vincentarelbundock
Copy link
Copy Markdown
Collaborator

This PR does four things:

  1. Consolidate: related code was spread all over the function. This PR consolidates related calls in coherent/related chunks.
  2. Comment: add block comments to clearly highlight groups of related calls
  3. Modularize: spin off title drawing into draw_title() helper function.
  4. Explicit: make some of the list2env() calls more explicit. They are convenient and I was the one who introduced them, but I now feel that they are quite a bad idea, because they obscure which variables are being passed to (and potentially) overwritten by a function. This is a first step toward a future refactor to make internal argument passing easier and more robust.

I consider this a self-contained contribution ready for review.

@vincentarelbundock
Copy link
Copy Markdown
Collaborator Author

FYI, I changed very little code in this PR, but I moved many lines around, which makes review difficult.

Sorry!

Here's the link to the whole file: https://github.com/grantmcdermott/tinyplot/blob/ef588b88eb3daebe730a284fa5e402437d8a3ffa/R/tinyplot.R

Copy link
Copy Markdown
Owner

@grantmcdermott grantmcdermott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a quick review during my lunch break.

One nit(ish) meta comment that I didn't make: I'm not the biggest fan of block headings b/c they are slight pain to write and also don't index well in my IDE/dev environment for quick navigation between sections. Could we maybe use something that is more "breadcrumb" friendly like:

#
## some section -----
#

?

Comment thread R/tinyplot.R Outdated

###########################
# save parameters and calls
###########################
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and several other places: Can you please make sure there is a 1-line gap between the section header and the subsequent code.

Comment thread R/tinyplot.R
if (is.null(bg) && !is.null(fill)) bg = fill

# will be overwritten by some type_data() functions and ignored by others
# ribbon.alpha is overwritten by some type_data() functions
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe prefix comment with # note: ...

Comment thread R/tinyplot.R
if (!null_by && is.character(by)) by = factor(by)
x_by = identical(x, by) # "boxplot", "spineplot" and "ridge"

# flag if x==by (currently only used for "boxplot", "spineplot" and "ridges" types)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep this old description? I know the code isn't difficult to read, but I feel explicit comments are better.

Comment thread R/tinyplot.R
Comment on lines +759 to +770
tmp = sanitize_axes(axes, xaxt, yaxt, frame.plot)
list2env(tmp[c("axes", "xaxt", "yaxt", "frame.plot")], environment())
rm("tmp")

# xlab & ylab
tmp = sanitize_xylab(
x = x, xlab = xlab, x_dep = x_dep, xmin_dep = xmin_dep, xmax_dep = xmax_dep,
y = y, ylab = ylab, y_dep = y_dep, ymin_dep = ymin_dep, ymax_dep = ymax_dep,
type = type)
xlab = tmp$xlab
ylab = tmp$ylab
rm("tmp")
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I have an aversion to tmp variables (even if cleaned up directly). Could we not just assign/subset directly, e.g.:

list2env(sanitize_axes(...)[<args_you_want_to_keep>])

?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second comment on these sections, should we briefly say what each of these sanitize_* functions are meant to do? In the spirit of more explicit commenting, I think it would be helpful to state here what we expect them to return, so that we don't have to look up the the internal cross-ref. (I don't recall offhand whether they are internally documented...)

Comment thread R/tinyplot.R Outdated
rm("tmp")

# facet
facet_by = FALSE
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to x_by, maybe a more explicit comment?

Comment thread R/tinyplot.R
bubble_alpha = if (!is.null(alpha)) alpha else 1
bubble_bg_alpha = if (!is.null(bg) && length(bg)==1 && is.numeric(bg) && bg > 0 && bg <=1) bg else 1
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove extra line

Comment thread R/tinyplot.R Outdated
}

# plot limits
# after yaxb
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New comment isn't clear to me. Are we saying we only want to calculate limits after x/yaxb have been calculated?

Comment thread R/tinyplot.R Outdated
xlim_user = xlim_user, ylim_user = ylim_user,
type = type
)
fargs = fargs[c("xlim", "ylim")]
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we subset directly in the line above?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, maybe we just assign/subset directly in the list2env call like I proposed above. fargs is a bad name for the temp variable anyway... i'm not sure why we (I?) called it that in the first place.

Comment thread R/tinyplot.R
Comment on lines -964 to -967
# Determine the number and arrangement of facets.
# Note: We're do this up front, so we can make some adjustments to legend cex
# next (if there are facets). But the actual drawing of the facets will only
# come later.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm. I prefer this old, more explicit comment. Maybe we can add some more detail to the new terse on below (l. 992).

Comment thread R/tinyplot.R
Comment on lines -1187 to -1189
#
## Exterior plot elements (plot and facet windows, axes, etc.)
#
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we re-use some version of this comment that makes the logic explicit? The point I was trying to convey, which was tricky to figure out originally, is that you first need to determine and draw all of the exterior elements (facets, axes, etc.) in your plot window, before you circle back to each facet and and draw the interior elements (grouped points, lines, etc.).

@grantmcdermott
Copy link
Copy Markdown
Owner

4. Explicit: make some of the list2env() calls more explicit. They are convenient and I was the one who introduced them, but I now feel that they are quite a bad idea, because they obscure which variables are being passed to (and potentially) overwritten by a function. This is a first step toward a future refactor to make internal argument passing easier and more robust.

P.S. Agree that this is a good idea. One simple solution would be to roll our own variant that provides the option (or requires?) the explicit return list.

@vincentarelbundock
Copy link
Copy Markdown
Collaborator Author

Thanks for the review @grantmcdermott

I agree with all your comments and have implemented all of them except for 1: avoid temporary objects and stricter list2env.

The reason is that this PR is just the last cosmetic step toward implementing my Master Plan (tm). I'll open a new WIP / spec PR soon with a concrete proposal, and if you like that idea, it'll make all these messy calls and temp variables obsolete.

If it doesn't work out, I can circle back to this and cleanup the residual tmp objects.

So I'd just like to merge the cosmetics for now, and move on the actual substantive proposal.

@grantmcdermott
Copy link
Copy Markdown
Owner

Sgtm. I'm excited to see the master plan!

Feel free to merge if you're happy.

@vincentarelbundock vincentarelbundock merged commit cba25cb into grantmcdermott:main Sep 9, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants