强制包的功能使用用户提供的功能 [英] Forcing a package's function to use user-provided function

查看:113
本文介绍了强制包的功能使用用户提供的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个问题,我已经追踪到 deparse MNP >(其最大宽度限制为500个字符)。



背景(如果您无聊,则轻松跳过)



因为 mnp 使用一些有点特殊的语法来允许不同的选择集(你包括 cbind(choiceA,choiceB,...)公式定义),我的公式调用的左边是1700个字符,当 model.matrix.default 调用 deparse 上由于 deparse 支持500个字符的最大值 width.cutoff ,所以 sapply(attr(t ,变量),deparse,width.cutoff = 500)[ - 1L] line in model.matrix.default 具有第一个元素:

  [1]cbind(plan1,plan2,plan3,plan4,plan5,plan6,plan7,plan8,plan9,plan10 ,计划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 ,plan61,plan62,plan63,
[2]plan64,plan65,plan66,plan67,plan68,plan69,plan70,plan71,plan72,plan73,plan74,plan75,plan76,plan77,plan78,plan79,plan80,计划81,计划82,计划83,计划84,计划85,计划86,计划87,计划88,计划8 9,plan90,plan91,plan92,plan93,plan94,plan95,plan96,plan97,plan98,plan99,plan100,plan101,plan102,plan103,plan104,plan105,plan106,plan107,plan108,plan109,plan110,plan111,plan1212,plan113,计划114,计划115,计划116,计划117,计划118,计划119,计划120,计划121,计划122,计划123,
[3]计划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计划,plan160,plan161,plan162,plan163,plan164,plan165,plan166,plan167,plan168,plan169,plan170,plan171,plan172,plan173,plan174,plan175,plan176,plan177,plan178,plan179,
[4] plan180,plan181,plan182,plan183,plan184,plan185,plan186,plan187,plan188,plan189,plan190,plan191,plan192,plan193,plan194,plan195,plan196,plan197,pla n198,plan199,plan200,plan201,plan202,plan203,plan204,plan205,plan206,plan207,plan208,plan209,plan210,plan211,plan212,plan213,plan214,plan215,plan216,plan217,plan218,plan219,plan220,plan221,plan222,计划223,plan224,plan225,plan226,plan227,plan228,plan229,plan230,plan231,plan232,plan233,plan234,plan235,
[5]plan236,plan237,plan238,plan239,plan240,plan241,plan224,plan243 ,plan244,plan245,plan246,plan247,plan248,plan249,plan250,plan251,plan252,plan253,plan254,plan255,plan256,plan257,plan258,plan259,plan260,plan261,plan262,plan263,plan264,plan265,plan266,plan267,plan268 ,计划269,计划270,计划271,计划272,计划273,计划274,计划275,计划276,计划277,计划278,计划27,计划280,计划281,计划282,计划28,计划284,计划285,计划286,计划287,计划288,计划288,计划290,计划291 $ b [6]plan292,plan293,plan294,plan295,plan296,plan297,plan298,plan299,plan300,plan301,plan302,plan303,plan304,plan305,计划306,plan307,plan308,plan309,plan310,plan311,plan312,plan313)

model.matrix.default 根据data.frame中的变量进行测试,它返回错误。



问题



为了解决这个问题,我写了一个新的 deparse function:

  deparse<  -  function(expr,width.cutoff = 60L,backtick = mode(expr)%in%
c调用,expression,(,function),control = c(keepInteger,
showAttributes,keepNA),nlines = -1L){
ret< - .Internal(deparse,expr,width.cutoff,backtick,.deparseOpts(control),nlines))
paste0(ret,collapse =)
}

但是,当我再次运行 mnp 时,会返回相同的错误同样的原因( base :: deparse 正在运行,而不是我的 deparse



这对我来说有些令人惊讶,正如我所期望的更为典型的是这个例子,用户定义的函数临时覆盖基本函数: p>

 > print<  -  function(){
+ cat(user-defined print ran\\\

+}
> print()
用户定义的打印运行

我意识到正确的方法来解决这个问题是要重写 model.matrix.default ,但作为调试工具我很好奇如何强制它使用我的 deparse 为什么预期(由我)行为不在这里发生。

解决方案

函数提供fixInNamespace assignInNamespace 以允许编辑现有功能。你可以尝试...但我会,因为使用 deparse 看起来太危险了:



$
函数(deparse,
函数(expr,width.cutoff = 60L,backtick = mode(expr)%)%
c(call expression,(,function),control = c(keepInteger,
showAttributes,keepNA),nlines = -1L){
ret < (deparse,expr,width.cutoff,backtick,.deparseOpts(control),nlines))
paste0(ret,collapse =)
},base)

帮助页面上有一个指示,使用这些功能有限制,我不会惊讶,这样的核心功能可能额外的保护层,由于它通过副作用,您不需要分配结果。


I'm running into a problem with the MNP package which I've traced to an unfortunate call to deparse (whose maximum width is limited to 500 characters).

Background (easily skippable if you're bored)

Because mnp uses a somewhat idiosyncratic syntax to allow for varying choice sets (you include cbind(choiceA,choiceB,...) in the formula definition), the left hand side of my formula call is 1700 characters or so when model.matrix.default calls deparse on it. Since deparse supports a maximum width.cutoff of 500 characters, the sapply(attr(t, "variables"), deparse, width.cutoff = 500)[-1L] line in model.matrix.default has as its first element:

[1] "cbind(plan1, plan2, plan3, plan4, plan5, plan6, plan7, plan8, plan9, plan10, plan11, plan12, plan13, plan14, plan15, plan16, plan17, plan18, plan19, plan20, plan21, plan22, plan23, plan24, plan25, plan26, plan27, plan28, plan29, plan30, plan31, plan32, plan33, plan34, plan35, plan36, plan37, plan38, plan39, plan40, plan41, plan42, plan43, plan44, plan45, plan46, plan47, plan48, plan49, plan50, plan51, plan52, plan53, plan54, plan55, plan56, plan57, plan58, plan59, plan60, plan61, plan62, plan63, "       
[2] "    plan64, plan65, plan66, plan67, plan68, plan69, plan70, plan71, plan72, plan73, plan74, plan75, plan76, plan77, plan78, plan79, plan80, plan81, plan82, plan83, plan84, plan85, plan86, plan87, plan88, plan89, plan90, plan91, plan92, plan93, plan94, plan95, plan96, plan97, plan98, plan99, plan100, plan101, plan102, plan103, plan104, plan105, plan106, plan107, plan108, plan109, plan110, plan111, plan112, plan113, plan114, plan115, plan116, plan117, plan118, plan119, plan120, plan121, plan122, plan123, "
[3] "    plan124, plan125, plan126, plan127, plan128, plan129, plan130, plan131, plan132, plan133, plan134, plan135, plan136, plan137, plan138, plan139, plan140, plan141, plan142, plan143, plan144, plan145, plan146, plan147, plan148, plan149, plan150, plan151, plan152, plan153, plan154, plan155, plan156, plan157, plan158, plan159, plan160, plan161, plan162, plan163, plan164, plan165, plan166, plan167, plan168, plan169, plan170, plan171, plan172, plan173, plan174, plan175, plan176, plan177, plan178, plan179, "
[4] "    plan180, plan181, plan182, plan183, plan184, plan185, plan186, plan187, plan188, plan189, plan190, plan191, plan192, plan193, plan194, plan195, plan196, plan197, plan198, plan199, plan200, plan201, plan202, plan203, plan204, plan205, plan206, plan207, plan208, plan209, plan210, plan211, plan212, plan213, plan214, plan215, plan216, plan217, plan218, plan219, plan220, plan221, plan222, plan223, plan224, plan225, plan226, plan227, plan228, plan229, plan230, plan231, plan232, plan233, plan234, plan235, "
[5] "    plan236, plan237, plan238, plan239, plan240, plan241, plan242, plan243, plan244, plan245, plan246, plan247, plan248, plan249, plan250, plan251, plan252, plan253, plan254, plan255, plan256, plan257, plan258, plan259, plan260, plan261, plan262, plan263, plan264, plan265, plan266, plan267, plan268, plan269, plan270, plan271, plan272, plan273, plan274, plan275, plan276, plan277, plan278, plan279, plan280, plan281, plan282, plan283, plan284, plan285, plan286, plan287, plan288, plan289, plan290, plan291, "
[6] "    plan292, plan293, plan294, plan295, plan296, plan297, plan298, plan299, plan300, plan301, plan302, plan303, plan304, plan305, plan306, plan307, plan308, plan309, plan310, plan311, plan312, plan313)"  

When model.matrix.default tests this against the variables in the data.frame, it returns an error.

The problem

To get around this, I've written a new deparse function:

deparse <- function (expr, width.cutoff = 60L, backtick = mode(expr) %in% 
  c("call", "expression", "(", "function"), control = c("keepInteger", 
                                                        "showAttributes", "keepNA"), nlines = -1L)  {
    ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines))
    paste0(ret,collapse="")
  }

However, when I run mnp again and step through, it returns the same error for the same reason (base::deparse is being run, not my deparse).

This is somewhat surprising to me, as what I expect is more typified by this example, where the user-defined function temporarily over-writes the base function:

> print <- function() {
+   cat("user-defined print ran\n")
+ }
> print()
user-defined print ran

I realize the right way to solve this problem is to rewrite model.matrix.default, but as a tool for debugging I'm curious how to force it to use my deparse and why the anticipated (by me) behavior is not happening here.

解决方案

The functions fixInNamespace and assignInNamespace are provided to allow editing of existing functions. You could try ... but I will not since mucking with deparse looks too dangerous:

 assignInNamespace("deparse", 
                  function (expr, width.cutoff = 60L, backtick = mode(expr) %in% 
               c("call", "expression", "(", "function"), control = c("keepInteger", 
               "showAttributes", "keepNA"), nlines = -1L)  {
    ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines))
    paste0(ret,collapse="")
                         }   , "base")

There is an indication on the help page that the use of such functions has restrictions and I would not be surprised that such core function might have additional layers of protection. Since it works via side-effect, you should not need to assign the result.

这篇关于强制包的功能使用用户提供的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆