[racket] racket newbie question on quoting and the built in procedure-arity function

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Mon Jan 6 09:33:28 EST 2014

Rian, you want a syntactic abstraction that hides this mechanism: 



#lang racket

(module library racket
  (provide 
   ;; syntax 
   ;; (define/safe (f x ...) e ...) 
   ;; introduces a safe function that is ... and prints its name as just 'f'
   define/safe)
  
  (define-syntax-rule 
    (define/safe (f x ...) e ...)
    (define f (safe-function (lambda (x ...) e ...) 'f)))
  
  
  (struct safe-function (f name)
    #:property prop:procedure 0 ; first field is the function
    #:methods gen:custom-write
    [(define (write-proc safe-function port mode)
       (display (safe-function-name safe-function) port))]))

(module sample-tester racket 
  (require (submod ".." library))
  (module+ test
    (require rackunit))

  (define/safe ($+ x ...) (+ x ...))
  
  (module+ test
    (check-equal? ($+ 3 4) 7)
    (check-equal? (with-output-to-string (write $+)) "$+")))

(require 'sample-tester)



On Jan 6, 2014, at 9:26 AM, Vincent St-Amour <stamourv at ccs.neu.edu> wrote:

> As far as I know, no.
> 
> Vincent
> 
> 
> At Sun, 5 Jan 2014 19:51:10 -0500,
> Rian Shams wrote:
>> 
>> Perfect, I didn't know structs could be used like that.
>> Thank you!
>> 
>> As a follow-up question, can you directly create functions with a custom
>> printing method, without having to go through structs?
>> 
>> 
>> On Sat, Jan 4, 2014 at 8:13 PM, Vincent St-Amour <stamourv at ccs.neu.edu>wrote:
>> 
>>> Similarly, you can represent safe functions as applicable structures (so
>>> they can behave like functions) with a custom printing method.
>>> 
>>>    #lang racket
>>> 
>>>    (struct safe-function (f name)
>>>            #:property prop:procedure 0 ; first field is the function
>>>            #:methods gen:custom-write
>>>            [(define (write-proc safe-function port mode)
>>>               (display (safe-function-name safe-function) port))])
>>> 
>>>    (define $+ (safe-function + '$+))
>>> 
>>>    ($+ 1 2) ; => 3
>>>    $+ ; prints "$+"
>>> 
>>> 
>>> Vincent
>>> 
>>> 
>>> 
>>> At Sat, 4 Jan 2014 18:52:55 -0500,
>>> Matthias Felleisen wrote:
>>>> 
>>>> [1  <multipart/alternative (7bit)>]
>>>> [1.1  <text/plain; iso-8859-1 (quoted-printable)>]
>>>> 
>>>> Perhaps you want something like this:
>>>> 
>>>> Welcome to Racket v6.0.0.1.
>>>>> (current-print (lambda (x) (if (procedure? x) (printf "~a"
>>> (object-name x)) (print x)) (newline)))
>>>> #<void>
>>>>> +
>>>> +
>>>>> 10
>>>> 10
>>>> 
>>>> 
>>>> 
>>>> 
>>>> On Jan 4, 2014, at 6:40 PM, Rian Shams wrote:
>>>> 
>>>>> Sorry for my lack of clarity.
>>>>> 
>>>>> My question is about the output that is displayed from calling the
>>> function. For example, evaluating just
>>>>> 
>>>>>> $+
>>>>> #<procedure:$+>
>>>>> 
>>>>> The result I am looking for is
>>>>> 
>>>>>> $+
>>>>> $+
>>>>> 
>>>>> as opposed to
>>>>> #<procedure:$+>
>>>>> 
>>>>> I am not sure whether this is just a formatting or renaming problem,
>>> or if it is possible to change what the interpreter displays in Dr.Racket?
>>>>> 
>>>>> I am fairly new to Racket and programming in general and so I really
>>> appreciate your responses and patience.
>>>>> 
>>>>> 
>>>>> On Sat, Jan 4, 2014 at 5:49 PM, Matthias Felleisen <
>>> matthias at ccs.neu.edu> wrote:
>>>>> 
>>>>> Yes, you need two functions: one that gives you the name of a
>>> procedure and one that picks a procedure. I was merely hinting at how to do
>>> the former. -- Matthias
>>>>> 
>>>>> 
>>>>> 
>>>>> On Jan 4, 2014, at 4:57 PM, Rian Shams wrote:
>>>>> 
>>>>>> Thanks Matthias,
>>>>>> 
>>>>>> If I use your definition:
>>>>>> 
>>>>>> (define (select-random-safe-function)
>>>>>>  (object-name
>>>>>>   (list-ref safe-function-set (random (length safe-function-set)))))
>>>>>> 
>>>>>> then,
>>>>>> 
>>>>>>> (procedure-arity (select-random-safe-function))
>>>>>> error:procedure-arity: contract violation
>>>>>>  expected: procedure?
>>>>>>  given: '$+
>>>>>> 
>>>>>> 
>>>>>> I believe I need two things:
>>>>>> 
>>>>>> 1. (select-random-safe-function) should return an unquoted procedure,
>>> similar to
>>>>>> 
>>>>>> (define (select-random-safe-function) ;without object-name
>>>>>>   (list-ref safe-function-set (random (length safe-function-set))))
>>>>>>> (select-random-safe-function)
>>>>>> #<procedure:$+>
>>>>>> 
>>>>>> preferably without #<procedure: $+ >
>>>>>> 
>>>>>> so my problem is that I want the output to display
>>>>>> $+
>>>>>> instead of
>>>>>> #<procedure:$+>
>>>>>> 
>>>>>> 2. The reason the procedure needs to be unquoted is because
>>>>>> (procedure-arity (select-random-safe-function)) will produce an error
>>> if the function is quoted.
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> Later on I use both (procedure-arity (select-random-safe-function))
>>> and (select-random-safe-function) in a main function:
>>>>>> 
>>>>>> ;;Generate Initial Population
>>>>>> ;population size is a positive integer and the auxiliary-function,
>>> generate-chromsome generates a tree using functions from safe-function-set
>>> and terms (numbers and symbols) from a term-set
>>>>>> 
>>>>>> (define (generate-initial-population population-size)
>>>>>>  (cond [(zero? population-size) empty]
>>>>>>           [else (cons (generate-chromosome initial-chromosome-depth)
>>> ;initial-chromosome-depth is 3
>>>>>>                            (generate-initial-population (sub1
>>> population-size)))]))
>>>>>> 
>>>>>>> (generate-initial-population 1)
>>>>>> '((#<procedure:$/> (#<procedure:$-> x .234) (#<procedure:$+> .576 x)))
>>>>>> 
>>>>>> this gets me my desired result, but is hard for me to read especially
>>> as the depth and population size grows (typically I will be working with
>>> populations ranging in the hundreds or thousands and each chromosome/tree's
>>> depth could easily exceed 10) so it would be more convenient here if my
>>> solution displays
>>>>>> 
>>>>>> '(($/ ($- x .234) ($+ .576 x)))
>>>>>> 
>>>>>> instead of
>>>>>> 
>>>>>> '((#<procedure:$/> (#<procedure:$-> x .234) (#<procedure:$+> .576 x)))
>>>>>> 
>>>>>> and I am not sure how I would go about doing this?
>>>>>> 
>>>>>> On Sat, Jan 4, 2014 at 8:45 AM, Matthias Felleisen <
>>> matthias at ccs.neu.edu> wrote:
>>>>>> 
>>>>>> If you really just want the name, use object-name:
>>>>>> 
>>>>>> (define (select-random-safe-function)
>>>>>>  (object-name
>>>>>>   (list-ref safe-function-set (random (length safe-function-set)))))
>>>>>> 
>>>>>> Welcome to DrRacket, version 6.0.0.1--2013-12-29(bbb0c5f6/d) [3m].
>>>>>> Language: racket.
>>>>>>> (select-random-safe-function)
>>>>>> '$*
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> On Jan 4, 2014, at 2:48 AM, Rian Shams wrote:
>>>>>> 
>>>>>>> If I do this I get the results I need for (procedure-arity
>>> (select-random-safe-function)), but when I call
>>>>>>> (safe-function-set) or (select-random-safe-function) or any other
>>> function that returns a safe function I get for example:
>>>>>>> 
>>>>>>>> (safe-function-set)
>>>>>>> '(#<procedure:$+> #<procedure:$-> #<procedure:$*> #<procedure:$/>)
>>>>>>> 
>>>>>>>> (select-random-safe-function)
>>>>>>> #<procedure:$->
>>>>>>> 
>>>>>>> whereas when it was defined using quote as opposed to list I get:
>>>>>>> 
>>>>>>>> (safe-function-set)
>>>>>>> '($+ $- $* $/)
>>>>>>> 
>>>>>>>> (select-random-safe-function)
>>>>>>> '$-
>>>>>>> 
>>>>>>> How would I get rid of this #<procedure:$-> part for readability,
>>> keeping only the $- part which is the actual function I defined, while
>>> still keeping it a function/procedure that gives me the function arity
>>> using (procedure-arity (select-random-safe-function))?
>>>>>>> 
>>>>>>> Best,
>>>>>>> 
>>>>>>> 
>>>>>>> On Fri, Jan 3, 2014 at 5:31 PM, Sam Tobin-Hochstadt <
>>> samth at cs.indiana.edu> wrote:
>>>>>>> Try replacing `safe-function-set` with:
>>>>>>> 
>>>>>>> (define safe-function-set (list $+ $- $* $/))
>>>>>>> 
>>>>>>> Sam
>>>>>>> 
>>>>>>> On Fri, Jan 3, 2014 at 5:28 PM, Rian Shams <rian.shams at gmail.com>
>>> wrote:
>>>>>>>> Hello,
>>>>>>>> 
>>>>>>>> I am working with functions that I have defined to only take 1 or
>>> 2 operands
>>>>>>>> (called safe-functions) for the implementation of a genetic
>>> program.
>>>>>>>> 
>>>>>>>> (define ($+ augend addend) ;operation is addition
>>>>>>>>  (+ augend addend)) ; the result is the sum
>>>>>>>> (define ($- minuend subtrahend) ;operation is subtraction
>>>>>>>>  (- minuend subtrahend)) ;result is difference
>>>>>>>> (define ($* multiplicand multiplier) ;operation is multiplication
>>>>>>>>  (* multiplicand multiplier)) ;result is product
>>>>>>>> (define ($/ dividend divisor) ;operation is division
>>>>>>>>  (/ dividend divisor)) ;result is quotient
>>>>>>>> 
>>>>>>>> (define (infinity? x) (or (eq? x +Inf.0) (eq? x -Inf.0)))
>>>>>>>> (define ($sin x) (if (infinity? x) (* (sgn x) +Inf.0) (sin x)))
>>>>>>>> (define ($cos x) (if (infinity? x) (* (sgn x) +Inf.0) (cos x)))
>>>>>>>> 
>>>>>>>> (define safe-function-set
>>>>>>>>  '($+
>>>>>>>>    $-
>>>>>>>>    $*
>>>>>>>>    $/
>>>>>>>>    ;$sin
>>>>>>>>    ;$cos))
>>>>>>>> 
>>>>>>>> (define (select-random-safe-function)
>>>>>>>>  (list-ref safe-function-set (random (length safe-function-set))))
>>>>>>>> 
>>>>>>>> I would like to use procedure-arity (or a similar function) to
>>> determine the
>>>>>>>> arity of a randomly selected safe function but I get this error:
>>>>>>>> 
>>>>>>>>> (procedure-arity (select-random-safe-function))
>>>>>>>> error: procedure-arity: contract violation
>>>>>>>>  expected: procedure?
>>>>>>>>  given: '$+
>>>>>>>> 
>>>>>>>> I think the problem is that the safe-functions are passed to
>>> procedure-arity
>>>>>>>> quoted. Is there a way I can unquote the functions, or adjust
>>>>>>>> procedure-arity to make (procedure-arity
>>> (select-random-safe-function))
>>>>>>>> work?
>>>>>>>> 
>>>>>>>> Thanks,
>>>>>>>> --
>>>>>>>> Rian Shams
>>>>>>>> 
>>>>>>>> ____________________
>>>>>>>>  Racket Users list:
>>>>>>>>  http://lists.racket-lang.org/users
>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> --
>>>>>>> Rian Shams
>>>>>>> ____________________
>>>>>>> Racket Users list:
>>>>>>> http://lists.racket-lang.org/users
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> --
>>>>>> Rian Shams
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> --
>>>>> Rian Shams
>>>> 
>>>> [1.2  <text/html; iso-8859-1 (7bit)>]
>>>> 
>>>> [2  <text/plain; us-ascii (7bit)>]
>>>> ____________________
>>>>  Racket Users list:
>>>>  http://lists.racket-lang.org/users
>>> 
>> 
>> 
>> 
>> -- 
>> Rian Shams
>> [2  <text/html; ISO-8859-1 (quoted-printable)>]
>> 



Posted on the users mailing list.