Tuesday, 15 July 2014

design patterns - How to not fall into R's 'lazy evaluation trap' -


"R is not near, not value. This promise is not evaluated when it is first evaluated, Is passed. ", See G. See also reference of Headley's book by Greyhandende.

In simple examples like

  & gt; Have fun & lt; - lapply (1:10, function (i) function () print (i)) & gt; Have fun [[1]] () [1] 10 & gt; Have fun [[2]] () [1] 10  

It is possible to keep such unsatisfactory behavior in mind.

However, I often fall in this trap during the daily development. I follow a rather functional programming style, which means that I often have Function A function B, where B. is on the basis of some parameters with whom A was called. Dependence is not as easy as it is in the above example, because calculations are complex and there are many criteria.

Due to this problem it is difficult to debug problems, because all calculations run smoothly - except that the result is false, only a clear validation of results shows the problem.

What comes at the top, even though I've seen such a problem, I'm never sure which variable I need force and which I do not I do

How can I make sure not to fall into this trap? Is there a programming pattern that stops it or at least ensures that I have a problem? P> You are creating functions with false parameters, which is not necessarily the best practice in your example, the contained parameter i will be another way of working again:

  Library (functional) MyPrints & lt; - Function (x) Print (x) Enjoy & lt; - lapply (1:10, function (i) curry micrint, i) fun [[1]] () # [1] 1 fun [[2]] () # [1] 2  

Here, we clearly specify the parameter curry to note the function that we could cream directly the print but for example not here Were.

Creates a new version of the Curry function with pre-defined criteria. This parameter clarifies the specification and avoids the potential issues that are going on in you because curry evaluates the forces (which is not a version but it will not help here).

Another option is to capture the entire environment of the original work, copy it, and assign it to the parent of your new function:

  funs2 & lt; - lapply (1:10, function (i) (funny .lt; - function () print (i) environment (fun). & Lt; - list2env (as.list (environment ()) # Force parent env copy fun .res}) funs2 [[1]] () # [1] 1 fun 2 [[2]] () # [1] 2  

But I do not recommend it because you Maybe a copy of the whole bunch will not be needed, the variables may not be worse, it becomes much more complicated if you have nested the layers of tasks that make up the works. The only advantage is that you can continue your underlying parameter specification, but again, it seems like bad practice to me.


No comments:

Post a Comment