3

I'd like to know what this code means in Scheme:

(define ((K x) y) x)

(define (((S x) y) z)
  ((x z) (y z)))

The whole file is here.

Is this legal Scheme? Is (K x) a parametrized function, something like generic functions in Java? I looked up the MIT Scheme reference, there seems to be nothing mentioned for definition of this kind.

Will Ness
  • 62,652
  • 8
  • 86
  • 167
Jiaji
  • 165
  • 9

2 Answers2

2

Trying it in MIT Scheme works

(define ((K x) y) x)
;Value: k

((k 3) 4)
;Value: 3

Apparently, these are the definitions for K and S combinators from a combinatorial logic SKI calculus.

We can define the same function explicitly,

(define k (lambda (x) (lambda (y) x)))
;Value: k

((k 3) 4)
;Value: 3

Apparently, MIT-Scheme does that for us, just as in case of regular definitions like (define (fun foo) bar) being translated to (define fun (lambda (foo) bar)).

The S combinator would be defined explicitly as

(define S (lambda (x) (lambda (y) (lambda (z) 
  ((x z) (y z))))))

(define ((add a) b) (+ a b))
;Value: add

(define (add1 a) (+ a 1))
;Value: add1

(((s add) add1) 3)
;Value: 7

This is how currying languages (like e.g. Haskell) work, where every function is a function of one argument. Haskell is very close to the combinatorial logic in that respect, there's no parentheses used at all, and we can write the same definitions simply as

_K x y = x
_S x y z = x z (y z)

So that _S (+) (1+) 3 produces 7.

Will Ness
  • 62,652
  • 8
  • 86
  • 167
  • Thanks. Now I see raison d'etre of the function definition syntax of Scheme, so it can be extracted recursively. – Jiaji Oct 25 '13 at 09:12
  • @Jiaji you might not want to depend on this kind of behavior though. I've never seen it before. It might not be standard (but maybe it is). It works in Dr.Racket's r5rs, as well. The R5RS standard, in section [5.2 Definitions](http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-8.html#%_sec_5.2) only gives `(define ...)` and `(define (variable ...) ...)`, so I'm not sure that this is actually legal, in general. However, I can see where a compiler that transforms `(define ( . args) body)` into `(define (lambda args body))` and keeps applying the – Joshua Taylor Oct 25 '13 at 15:13
  • @Jiaji transformation recursively would end up with the appropriate definitions. Maybe later versions of Scheme _do_ define it as a syntax transformation, but I think it's not technically legal in R5RS, since the specification only allows the forms with a variable: `(define ...)` and `(define ( ...) ...)`. – Joshua Taylor Oct 25 '13 at 15:19
  • @WillNess Re: "Apparently, MIT-Scheme does that for us, just as in case of regular definitions like (define (fun foo) bar) being translated to (define fun (lambda (foo) bar))." Do other versions of Scheme (i.e., not R5RS, which is _my_ go-to Scheme) actually define it as a translation, as opposed to R5RS's enumerating different legal `define` forms? – Joshua Taylor Oct 25 '13 at 15:21
  • @JoshuaTaylor I don't know. This was a surprise to me too. I think your guess is right about a compiler continuing to apply the transformation. Is Dr.Racket's r5rs what you use most? – Will Ness Oct 25 '13 at 15:32
  • @WillNess I don't do all that much Scheming, but Dr. Racket is usually what I use. As you said though, MIT-Scheme does it too. Implementing it as a translation doesn't surprise me, since it's a pretty obvious case of syntactic sugar; it just seems like since it's not _specified_ as a translation, code that depends on it being a translation isn't portable. – Joshua Taylor Oct 25 '13 at 15:40
  • @JoshuaTaylor yes, a bit suspicious to rely on. – Will Ness Oct 25 '13 at 15:41
  • @JoshuaTaylor [turns out](http://stackoverflow.com/a/19595805/849891) it's [documented](http://docs.racket-lang.org/guide/define.html#%28part._.Curried_.Function_.Shorthand%29) in Racket. – Will Ness Oct 25 '13 at 22:23
  • @JoshuaTaylor I've always been curious why Scheme uses a function definition syntax that is structurally different from older Lisps, now I understand this kind of transformation must have been in mind when the language was created, not just an implementation specific feature. – Jiaji Oct 26 '13 at 06:43
1

It's called Curried Function Shorthand and described here.

uselpa
  • 18,168
  • 2
  • 30
  • 47