[racket] racket newbie question on quoting and the built in procedure-arity function
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)>]
>>