Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator Overloading in Racket / Scheme

I am having some trouble here, and hopefully you guys can help.

Basically, what I am trying to do is overload the + sign in racket so that it will add two vectors instead of two numbers. Also, I want to keep the old + operator so that we can still use it. I know this is supposed to work in scheme, so I was told I needed to use module* to do it in racket. I am still not entirely sure how it all works.

Here is what I have so far:

#lang racket

(module* fun scheme/base 
  (define old+ +) 
  (define + new+)

  (define (new+ x y)
    (cond ((and (vector? x) (vector? y))
           (quatplus x y))
          (else (old+ x y))))

  (define (quatplus x y)
    (let ((z (make-vector 4)))
      (vector-set! z 0 (old+ (vector-ref x 0) (vector-ref y 0)))
      (vector-set! z 1 (old+ (vector-ref x 1) (vector-ref y 1)))
      (vector-set! z 2 (old+ (vector-ref x 2) (vector-ref y 2)))
      (vector-set! z 3 (old+ (vector-ref x 3) (vector-ref y 3)))
      z)))

But it doesn't seem to do anything at all. If anyone knows anything about this I would be very appreciative.

Thank you.

like image 679
user3308321 Avatar asked Jul 31 '26 18:07

user3308321


1 Answers

How I would do this is to use the except-in and rename-in specs for require:

#lang racket/base

(require (except-in racket + -)
         (rename-in racket [+ old+] [- old-]))

(define (+ x y)
  (cond [(and (vector? x) (vector? y))
         (quatplus x y)]
        [else (old+ x y)]))

(define (quatplus x y)
  (vector  (+ (vector-ref x 0) (vector-ref y 0))
           (+ (vector-ref x 1) (vector-ref y 1))
           (+ (vector-ref x 2) (vector-ref y 2))
           (+ (vector-ref x 3) (vector-ref y 3))))

(+ (vector 1 2 3 4) (vector 1 2 3 4))
;; => #(2 4 6 8)

You could also use prefix-in with only-in, which would be more convenient if you had many such functions to rename:

(require (except-in racket + -)
         (prefix-in old (only-in racket + -)))

A few points:

  • I had quatplus simply return a new immutable vector (instead of using make-vector and set!). It's simpler and probably faster.

  • Racket's + accepts any number of arguments. Maybe yours should?

  • As written, your new + will fail for the combination of a non-vector and a vector. You probably want to fix that:

    (+ 1 (vector 1 2 3 4))
    ; +: contract violation
    ;   expected: number?
    ;   given: '#(1 2 3 4)
    ;   argument position: 1st
    ;   other arguments...:
    ;    1
    
like image 191
Greg Hendershott Avatar answered Aug 03 '26 07:08

Greg Hendershott



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!