[Rd] Contract Syntactic Sugar

Brian Lee Yung Rowe rowe at muxspace.com
Tue Feb 5 02:17:10 CET 2013


Ivo,

If you don't like the multipart function syntax you can write a single definition. Personally I prefer this as it isolates data management logic and control flow from model/application logic. There are duck typing operators that you can use in the guard similar to the syntax you wrote. You can also create your own types and use that in a type constraint. However the type constraint syntax must be a distinct statement although you could embed it all within a guard. Here are three different approaches using lambda.r. 

NaturalNumber(x) %when% {
  all(is.positive(x))
} %as% { x }

# Using an explicit type constraint with a custom type
exponentiate(x, exponent) %::% data.frame : NaturalNumber : integer 
exponentiate(x, exponent) %when% {
  x %hasa% base
} %as% { x$base ^ exponent }

 -- or --

# Embedding everything in a guard
exponentiate(x, exponent) %when% {
  x %hasa% base
  x %isa% NaturalNumber
} %as% { x$base ^ exponent }

 -- or --

# Eschewing a custom type for explicit statements
exponentiate(x, exponent) %when% {
  x %hasa% base
  all(is.positive(x$base))
} %as% { x$base ^ exponent 

Warm Regards,
Brian

•••••
Brian Lee Yung Rowe
917 496 4583


On Feb 4, 2013, at 6:23 PM, ivo welch <ivo.welch at gmail.com> wrote:

> hi brian---interesting and very impressive.  is it possible to move
> everything into one definition and/or to chain multiple conditions?
> 
> exponentiate(x, exponent) %::% data.frame : c(numeric,allpositive) :
> integer  %as% {
>  x %has% base  ## my invention, since this is not checked, and R is
> not strict enough
>  x$base %::% allpositive
>  x$base ^ exponent
> }
> 
> multiple creations as in your doc examples on the same function are a
> recipe for errors for me.  it's also why I am not too fond of
> TypeInfo.  chaining conditions in my c() is not important, as long as
> I can define my own types (which can check multiple aspects at the
> same time).  suggestion: in your doc example, can you define a
> different type than an integer?  it's a little confusing.  how about
> defining a strictly positive integer?
> 
> regards,
> 
> /iaw
> ----
> Ivo Welch (ivo.welch at gmail.com)
> http://www.ivo-welch.info/
> J. Fred Weston Professor of Finance
> Anderson School at UCLA, C519
> Director, UCLA Anderson Fink Center for Finance and Investments
> Free Finance Textbook, http://book.ivo-welch.info/
> Editor, Critical Finance Review, http://www.critical-finance-review.org/
> 
> 
> 
> On Mon, Feb 4, 2013 at 2:10 PM, Brian Lee Yung Rowe <rowe at muxspace.com> wrote:
>> Ivo,
>> 
>> You might be interested in my lambda.r package which provides syntax (using the %::% operator) for type constraints. Given a function with n arguments, the type constraint requires n + 1 types, as the last type listed is the return type. Lambda.r also provides syntax for specifying any arbitrary condition on the input arguments via the %when% operator. For your example below you could do the following:
>> 
>> exponentiate(x, exponent) %::% data.frame : numeric : numeric
>> exponentiate(x, exponent) %when% {
>>  is.positive(x)
>> } %as% {
>>  x$base ^ exponent
>> }
>> 
>> You can see more examples in the package (available on CRAN) or in the source (https://github.com/muxspace/lambda.r).
>> 
>> HTH,
>> Brian
>> 
>> 
>> On Feb 4, 2013, at 4:53 PM, ivo welch <ivo.welch at anderson.ucla.edu> wrote:
>> 
>>> ## the following is a dream: add some sugar syntax to allow for
>>> contracts with teeth (in and out checking)
>>> 
>>>> is.positive <- function(x) (all(x>0))
>>> 
>>>> exponentiate <- function( x ::is.data.frame , exponent ::is.numeric is.positive)  :: is.vector is.numeric  {
>>>   x$base :: is.positive        ## error also if base does not exist
>>> in x; may need some special IQ
>>>   x$base^exponent
>>> }
>>> 
>>> should be self-explanatory.  anything that has '::' means "run what is
>>> before through all the functions after and barf if it is not true".
>>> any other operator rather than :: or other syntax would be as
>>> good---this is just illustratory.  in the end, this code should be
>>> viewed by R as the same as
>>> 
>>>> exponentiate <- function( x, exponent ) {
>>>   stopifnot( is.data.frame(x) )
>>>   stopifnot( is.numeric(exponent) )
>>>   stopifnot( is.positive(exponent) )
>>>   stopifnot( exists("base", "x") )
>>>   stopifnot( is.positive( x$base ) )
>>>   return.value <- x$base^exponent
>>>   stopifnot( is.vector(return.value) )
>>>   stopifnot( is.numeric(return.value) )
>>>   return.value
>>> }
>>> 
>>> is this a feasible summer project for a student with a prospect of
>>> inclusion of the completed code in the R core language itself if I pay
>>> for the development time?  {or does better syntax already exist and I
>>> am just ignorant (which I often am)?}
>>> 
>>> regards,
>>> 
>>> /iaw
>>> ----
>>> Ivo Welch (ivo.welch at gmail.com)
>>> 
>>> ______________________________________________
>>> R-devel at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>> 



More information about the R-devel mailing list