#lang racket
 
#| In the docs about procedure curry I read:
 
" A function call (curry proc v ...) is equivalent to ((curry proc) v ...).
In other words, curry itself is curried. "
 
This means: |#
 
((curry list)) ; -> #<procedure:curried>
 
#| where I would prefer:
 
((curry list)) ; -> ()
 
To me the following seems inconsistent : |#
 
(for/list ((n (in-range 0 3)))
 ((apply curry list (build-list n identity)) 'rest))
 
#|Gives:
 
(#<procedure:curried>
 (0 rest)
 (0 1 rest))
 
where I would prefer:
 
((rest)
 (0 rest)
 (0 1 rest))
 
QUESTION: What is the deeper thought underlying the self currying of
procedure curry?
Do you have examples where the self currying of procedure curry makes sense?
 
Procedure curry does not produce a procedure if the maximum number of
arguments is already present.
To me it seems more logical curry always returning a procedure. For example:
|#
 
(curry cons 1 2) ; -> (1 . 2), where I would prefer #<procedure:curried>.
 
#| Ignoring keyword arguments
and simplifying by omitting additional checks on arities,
I would define procedure kurry as follows: |#
 
(define (kurry proc . args) ; -> procedure? (yes, always a procedure)
 ; proc : procedure?
 ; args : list-of any/c
 (define (rename proc) (procedure-rename proc 'curried))
 ; When kurry is called it returns a curried procedure,
 ; even when we already have enough arguments.
 ; It must not yet call procedure proc.
 ; When the kurried procedure is called and has enough arguments,
 ; it must call the proc. Otherwise it must kurry again.
 ; Therefore we need a helper.
 (define (help . args)
  (if (procedure-arity-includes? proc (length args))
      (apply proc args)
      (rename (λ more-args (apply help (append args more-args))))))
 ; Now return the curried proc:
 (rename (λ more-args (apply help (append args more-args)))))
 
((kurry list)) ; -> ()
 
(for/list ((n (in-range 0 3)))
 ((apply kurry list (build-list n identity)) 'rest))
; -> ((rest) (0 rest) (0 1 rest))
 
(kurry cons 1 2 3) ; -> #<procedure:curried>
((kurry cons 1 2)) ; -> (1 . 2)
((kurry cons 1) 2) ; -> (1 . 2)
((kurry cons) 1 2) ; -> (1 . 2)
(((kurry cons) 1) 2) ; -> (1 . 2)
 
#| For procedures with an arity-at-least in their arity,
it may be useful to specify a depth of currying: |#
 
(define (kurryn n proc . args)
 (if (zero? n) (apply proc args)
  (procedure-rename
   (λ more-args (apply kurryn (sub1 n) proc (append args more-args)))
   'curried)))
 
(kurryn 0 list 1) ; -> (1)
(kurryn 1 list 1) ; -> #<procedure:curried>
((kurryn 1 list 1) 2) ; -> (1 2)
((kurryn 2 list 1) 2) ; -> #<procedure:curried>
(((kurryn 2 list 1) 2) 3) ; -> (1 2 3)
; whereas, of course:
(((curry list 1) 2) 3)
; and
(((kurry list 1) 2) 3)
#| ->
application: not a procedure;
 expected a procedure that can be applied to arguments
  given: (1 2)
  arguments...:
 
Is is obvious that applying the idea of currying to
procedures of arity 0 or procedures with an arity-at-least
requires some choices.
In lambda calculus we don't have this problem.
 
Thanks, Jos |#

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to