Matlab-style multiple assignment in R

[This article was first published on Struggling Through Problems » R, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

R again!

You know how in Matlab you can do?

S, I = sort(M)

I like that.

R generic functions makes this possible. First, let’s genericize assignment. I feel like regular “=” and “<-” oughta stay nongeneric, so let’s make a new one.

'%=%' = function(l, r, ...) UseMethod('%=%')

Now the next step is a bit tricky. We need to group several variables on the left of %=%

... a, b, ... %=% foo()

The trick is they have to stay unevaluated. Luckily R uses (what IIRC is called) “pass by name”, so we can do this. Let’s start with a function to take a, b, …

l = function(...) {

}

The hard part is grabbing the ‘…’ without evaluating it.

> substitute(...)
...

won’t work, nor will alist(…). I have NO IDEA why, but the following expression (stolen from data.frame()) works:

as.list(substitute(list(...)))[-1L]

So now we have our function

l = function(...) {
	List = as.list(substitute(list(...)))[-1L]
	class(List) = 'lbunch'

	List
}

And we can add a specific implementation for our generic %=%:

'%=%.lbunch' = function(l, r, ...) {
	Names = lapply(l, as.character)
	Envir = as.environment(-1)

	for (II in 1:length(Names)) {
		Name = Names[[II]]
		assign(Name, r[[II]], pos=Envir)
	}
}

Which just treats the objects “a”, “b” … as strings, and assigns into the caller’s environment.

That’s what I had first, but it can be made better. With the above implementation:

> l(a[1], b) %=% list(3, 4)
Warning message:
In assign(Name, r[[II]], pos = Envir) :
  only the first element is used as variable name

It doesn’t play nice with assignment functions.

It can be modified to call ‘<-’ directly:

'%=%.lbunch' = function(l, r, ...) {
	Envir = as.environment(-1)

	for (II in 1:length(l)) {
		do.call('<-', list(l[[II]], r[[II]]), envir=Envir)
	}
}

And now all is good.

> l(attr(a, 'foo'), b) %=% list(3, 4)
> a
[1] 3
attr(,"foo")
[1] 3

To leave a comment for the author, please follow the link and comment on their blog: Struggling Through Problems » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)