Re: [R] [EXTERNAL] Re: function doesn't exists but still runs..... (akshay kulkarni)
Dear Jorgen, thanks a lot Thanking you, Yours sincerely Akshay M Kulkarni From: Jorgen Harmse Sent: Monday, January 23, 2023 9:31 PM To: r-help@r-project.org ; akshay kulkarni Subject: Re: [R] [EXTERNAL] Re: function doesn't exists but still runs..... (akshay kulkarni) Hi Akshay, I usually use debug (a function provided by R). When you are stepping through a function your environment is the one in which function code is being executed, so you can easily see everything that is visible to the function. If you single step into a function that the first function calls then you also see everything that is available to that function. Moreover, you don't see anything that is not visible to the function you are debugging, so you can really determine what any piece of code would do if called inside the function. Note 1: Code in R is always executed in an environment. I show in the example below that in the empty environment (the ultimate ancestor of all other environments) R can't even add. Usually the current environment (e.g. .GlobalEnv at the command line or a fresh environment created by a function call) has the right contents and the right parent to do what you expect, but in some special cases you need to understand how environments work. Even evalq & with are functions (unavailable for example in the empty environment), and the environment argument has to be evaluated in the current environment before the main expression can be evaluated in the environment that you want. > E[1] [[1]] > evalq(2+2, E[[1L]]) Error in 2 + 2 : could not find function "+" > evalq(2L+2L, E[[1L]]) Error in 2L + 2L : could not find function "+" Note 2: Besides automatically showing what a function sees, using debug (instead of hand-executing lines of code from the function) gives you the correct call stack. Suppose that you run some code at the debug command line to make a sub-sub-…-function do what you want, and you create in that environment what you hope is the correct return value. You can then use parent.frame() to put that value into the environment of the caller and run the caller's remaining code in the correct environment to see what happens. If there are no other problems then you can work your way up to top level and confirm that your patch has the right effect before you even modify the actual code of the offending function. (Saving all environments in .GlobalEnv forces R to keep them even if you quit the debugger. Combining eval & parse is sometimes more convenient than using evalq.) Regards, Jorgen. -- Message: 2 Date: Sun, 22 Jan 2023 14:25:59 + From: akshay kulkarni To: Jorgen Harmse , "r-help@r-project.org" , "williamwdun...@gmail.com" Subject: Re: [R] [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Message-ID: Content-Type: text/plain; charset="utf-8" Dear Jorgen, regrets to reply this late I got into this issue because it threw an error, and it took more than 4 days to fix this. I learnt a lot, and one things I learnt is to debug the function, even when that is a public package functioninstead of googling the error message...Any ideas on how to do this more efficiently? THanking you, Yours sincerely, AKSHAY M KULKARNI From: Jorgen Harmse Sent: Friday, January 20, 2023 11:35 PM To: akshay kulkarni ; r-help@r-project.org ; williamwdun...@gmail.com Subject: Re: [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Hi Akshay, Lexical scoping and environments are closely tied. (I think Bill even cited the documentation.) I guess it's arcane in the sense that scoping usually does what you expect, but the way that works is related to what we discussed. What led you to discover the issue? Were you debugging the public package function because it didn't do what you expected, or were you just curious how it worked? Regards, Jorgen. From: akshay kulkarni Date: Friday, January 20, 2023 at 11:19 To: Jorgen Harmse , r-help@r-project.org , williamwdun...@gmail.com Subject: [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Dear Jorgen, thanks for the reply.so according to you one can pegion hole the problem as concerning R's lexical scoping rules,am I right? Or some arcane concept regarding environments? THanking you, Yours sincerely, AKSHAY M KULKARNI From: Jorgen Harmse Sent: Friday, January 20, 2023 9:34 PM To: r-help@r-project.org ; akshay...@hotmail.com ; williamwdun...@gmail.com Subject: Re: function doesn't exists but still runs. (akshay kulkarni) It may hel
Re: [R] [EXTERNAL] Re: function doesn't exists but still runs..... (akshay kulkarni)
Hi Akshay, I usually use debug (a function provided by R). When you are stepping through a function your environment is the one in which function code is being executed, so you can easily see everything that is visible to the function. If you single step into a function that the first function calls then you also see everything that is available to that function. Moreover, you don't see anything that is not visible to the function you are debugging, so you can really determine what any piece of code would do if called inside the function. Note 1: Code in R is always executed in an environment. I show in the example below that in the empty environment (the ultimate ancestor of all other environments) R can't even add. Usually the current environment (e.g. .GlobalEnv at the command line or a fresh environment created by a function call) has the right contents and the right parent to do what you expect, but in some special cases you need to understand how environments work. Even evalq & with are functions (unavailable for example in the empty environment), and the environment argument has to be evaluated in the current environment before the main expression can be evaluated in the environment that you want. > E[1] [[1]] > evalq(2+2, E[[1L]]) Error in 2 + 2 : could not find function "+" > evalq(2L+2L, E[[1L]]) Error in 2L + 2L : could not find function "+" Note 2: Besides automatically showing what a function sees, using debug (instead of hand-executing lines of code from the function) gives you the correct call stack. Suppose that you run some code at the debug command line to make a sub-sub-…-function do what you want, and you create in that environment what you hope is the correct return value. You can then use parent.frame() to put that value into the environment of the caller and run the caller's remaining code in the correct environment to see what happens. If there are no other problems then you can work your way up to top level and confirm that your patch has the right effect before you even modify the actual code of the offending function. (Saving all environments in .GlobalEnv forces R to keep them even if you quit the debugger. Combining eval & parse is sometimes more convenient than using evalq.) Regards, Jorgen. -- Message: 2 Date: Sun, 22 Jan 2023 14:25:59 + From: akshay kulkarni To: Jorgen Harmse , "r-help@r-project.org" , "williamwdun...@gmail.com" Subject: Re: [R] [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Message-ID: Content-Type: text/plain; charset="utf-8" Dear Jorgen, regrets to reply this late I got into this issue because it threw an error, and it took more than 4 days to fix this. I learnt a lot, and one things I learnt is to debug the function, even when that is a public package functioninstead of googling the error message...Any ideas on how to do this more efficiently? THanking you, Yours sincerely, AKSHAY M KULKARNI From: Jorgen Harmse Sent: Friday, January 20, 2023 11:35 PM To: akshay kulkarni ; r-help@r-project.org ; williamwdun...@gmail.com Subject: Re: [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Hi Akshay, Lexical scoping and environments are closely tied. (I think Bill even cited the documentation.) I guess it's arcane in the sense that scoping usually does what you expect, but the way that works is related to what we discussed. What led you to discover the issue? Were you debugging the public package function because it didn't do what you expected, or were you just curious how it worked? Regards, Jorgen. From: akshay kulkarni Date: Friday, January 20, 2023 at 11:19 To: Jorgen Harmse , r-help@r-project.org , williamwdun...@gmail.com Subject: [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Dear Jorgen, thanks for the reply.so according to you one can pegion hole the problem as concerning R's lexical scoping rules,am I right? Or some arcane concept regarding environments? THanking you, Yours sincerely, AKSHAY M KULKARNI From: Jorgen Harmse Sent: Friday, January 20, 2023 9:34 PM To: r-help@r-project.org ; akshay...@hotmail.com ; williamwdun...@gmail.com Subject: Re: function doesn't exists but still runs. (akshay kulkarni) It may help to expand a bit on Bill Dunlap's answer. I think that library does something like this: Create a new environment for all the package objects. This environment will not be directly visible from .GlobalEnv, and ancestor environments may not be directly visible either. It may contain functions & other objects that are not exported, and
Re: [R] [EXTERNAL] Re: function doesn't exists but still runs..... (akshay kulkarni)
Dear Jorgen, regrets to reply this late I got into this issue because it threw an error, and it took more than 4 days to fix this. I learnt a lot, and one things I learnt is to debug the function, even when that is a public package functioninstead of googling the error message...Any ideas on how to do this more efficiently? THanking you, Yours sincerely, AKSHAY M KULKARNI From: Jorgen Harmse Sent: Friday, January 20, 2023 11:35 PM To: akshay kulkarni ; r-help@r-project.org ; williamwdun...@gmail.com Subject: Re: [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Hi Akshay, Lexical scoping and environments are closely tied. (I think Bill even cited the documentation.) I guess it's arcane in the sense that scoping usually does what you expect, but the way that works is related to what we discussed. What led you to discover the issue? Were you debugging the public package function because it didn't do what you expected, or were you just curious how it worked? Regards, Jorgen. From: akshay kulkarni Date: Friday, January 20, 2023 at 11:19 To: Jorgen Harmse , r-help@r-project.org , williamwdun...@gmail.com Subject: [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Dear Jorgen, thanks for the reply.so according to you one can pegion hole the problem as concerning R's lexical scoping rules,am I right? Or some arcane concept regarding environments? THanking you, Yours sincerely, AKSHAY M KULKARNI From: Jorgen Harmse Sent: Friday, January 20, 2023 9:34 PM To: r-help@r-project.org ; akshay...@hotmail.com ; williamwdun...@gmail.com Subject: Re: function doesn't exists but still runs. (akshay kulkarni) It may help to expand a bit on Bill Dunlap's answer. I think that library does something like this: Create a new environment for all the package objects. This environment will not be directly visible from .GlobalEnv, and ancestor environments may not be directly visible either. It may contain functions & other objects that are not exported, and it may use objects in ancestor environments that .GlobalEnv doesn't see directly. On the other hand, functions in the package will still see external functions in the way the package author intended instead of seeing functions with the same name that are visible to .GlobalEnv. Run the source code in the private environment (using source(local=private environment, )?). Most package source code just defines functions, but the source code could build other objects that the package needs for some reason, or it could use delayedAssign to build the objects lazily. By default, the environment of any function defined by the source code is the private environment, so the function has access to private objects and to anything in ancestor environments. Create a second new environment whose parent is parent.env(.GlobalEnv). For every export, assign the corresponding object from the private environment into the corresponding name in the public environment. Note that the environment of any function is still the private environment in which it was created. (I think that a function is mostly determined by its environment, its formals, and its body. A function call creates a new environment whose parent is the environment of the function. Thus whoever wrote the function can control the search for anything that isn�t passed in or created by the function itself.) Reset parent.env(.GlobalEnv) to be the public environment. This makes all the exported objects (usually functions) available at the command line and allows the user to see everything that was available before (usually by name only, but by scope-resolved name if necessary). As noted by Bill Dunlap and in more detail above, package functions can use functions & other objects that are not directly visible to the user. As he also showed, you can (usually) pierce the privacy as long at least one function is exported. environment(package_function) is the private environment, so you can use it to see all the private objects and everything in the ancestor environments. You can repeat the trick to see private environments of packages you didn't directly pull in. I think you can even unlock bindings and do ghastly things to the package's private environment. Regards, Jorgen Harmse. -- Message: 17 Date: Thu, 19 Jan 2023 16:02:31 -0800 From: Bill Dunlap To: akshay kulkarni Cc: R help Mailing list Subject: Re: [R] function doesn't exists but still runs. Message-ID: Content-Type: text/plain; charset="utf-8" Look into R's scoping rules. E.g., https://bookdown.org/rdpeng/rprogdatascience/scoping-rules-of-r.html. * When a function looks up a name, it looks it up in the environment in which the function was defined. * Functions
Re: [R] [EXTERNAL] Re: function doesn't exists but still runs..... (akshay kulkarni)
Hi Akshay, Lexical scoping and environments are closely tied. (I think Bill even cited the documentation.) I guess it's arcane in the sense that scoping usually does what you expect, but the way that works is related to what we discussed. What led you to discover the issue? Were you debugging the public package function because it didn't do what you expected, or were you just curious how it worked? Regards, Jorgen. From: akshay kulkarni Date: Friday, January 20, 2023 at 11:19 To: Jorgen Harmse , r-help@r-project.org , williamwdun...@gmail.com Subject: [EXTERNAL] Re: function doesn't exists but still runs. (akshay kulkarni) Dear Jorgen, thanks for the reply.so according to you one can pegion hole the problem as concerning R's lexical scoping rules,am I right? Or some arcane concept regarding environments? THanking you, Yours sincerely, AKSHAY M KULKARNI From: Jorgen Harmse Sent: Friday, January 20, 2023 9:34 PM To: r-help@r-project.org ; akshay...@hotmail.com ; williamwdun...@gmail.com Subject: Re: function doesn't exists but still runs. (akshay kulkarni) It may help to expand a bit on Bill Dunlap's answer. I think that library does something like this: Create a new environment for all the package objects. This environment will not be directly visible from .GlobalEnv, and ancestor environments may not be directly visible either. It may contain functions & other objects that are not exported, and it may use objects in ancestor environments that .GlobalEnv doesn't see directly. On the other hand, functions in the package will still see external functions in the way the package author intended instead of seeing functions with the same name that are visible to .GlobalEnv. Run the source code in the private environment (using source(local=private environment, )?). Most package source code just defines functions, but the source code could build other objects that the package needs for some reason, or it could use delayedAssign to build the objects lazily. By default, the environment of any function defined by the source code is the private environment, so the function has access to private objects and to anything in ancestor environments. Create a second new environment whose parent is parent.env(.GlobalEnv). For every export, assign the corresponding object from the private environment into the corresponding name in the public environment. Note that the environment of any function is still the private environment in which it was created. (I think that a function is mostly determined by its environment, its formals, and its body. A function call creates a new environment whose parent is the environment of the function. Thus whoever wrote the function can control the search for anything that isn�t passed in or created by the function itself.) Reset parent.env(.GlobalEnv) to be the public environment. This makes all the exported objects (usually functions) available at the command line and allows the user to see everything that was available before (usually by name only, but by scope-resolved name if necessary). As noted by Bill Dunlap and in more detail above, package functions can use functions & other objects that are not directly visible to the user. As he also showed, you can (usually) pierce the privacy as long at least one function is exported. environment(package_function) is the private environment, so you can use it to see all the private objects and everything in the ancestor environments. You can repeat the trick to see private environments of packages you didn't directly pull in. I think you can even unlock bindings and do ghastly things to the package's private environment. Regards, Jorgen Harmse. -- Message: 17 Date: Thu, 19 Jan 2023 16:02:31 -0800 From: Bill Dunlap To: akshay kulkarni Cc: R help Mailing list Subject: Re: [R] function doesn't exists but still runs. Message-ID: Content-Type: text/plain; charset="utf-8" Look into R's scoping rules. E.g., https://bookdown.org/rdpeng/rprogdatascience/scoping-rules-of-r.html. * When a function looks up a name, it looks it up in the environment in which the function was defined. * Functions in a package are generally defined in the package's environment (although sometimes they are in a descendent of the parent's environment). * When one searches an environment for a name, if it is not found in the environment the search continues in the parent environment of that environment, recursively until the parent environment is the empty environment. > with(environment(wdman::selenium), java_check) function () { javapath <- Sys.which("java") if (identical(unname(javapath), "")) { stop("PATH to JAVA not found. Please check JAVA is installed.") } javapath } -Bill On Thu, Jan 19, 2023 at 2:28 PM akshay kulkarni wrote: > dear members, >