• [pre-SRFI] Predicate Single Dispatch

    From Amirouche Boubekki@21:1/5 to All on Fri Oct 25 03:36:01 2019
    Hello all!


    While working on SRFI-167, SRFI-168 and RDBMS [0] it became clear to me that scheme requires something like single dispatch to ease the implementation of swap-able backend.

    [0] https://srfi-email.schemers.org/schemepersist/msg/12473867/

    It can also help during (unit) tests to implement mocks.

    I know that I don't know. In particular, I forgo to include subsumption, because I don't know where / when it is useful.

    What do you think?

    I started a pre-SRFI at:

    https://github.com/amirouche/single-dispatch#predicate-single-dispatch

    Here is the current full document:

    # Predicate Single Dispatch

    ## Status

    Early Draft

    ## Abstract

    *Two or three sentences about what library this SRFI describes.*

    ## Rationale

    *Explain why it is useful and how it can be put to good use.*

    In many situations, the need arise to have several implementations of
    a procedure that depends on the type of the first argument.

    This specification describes an approach to solve that problem. It is compatible with R7RS-small records objects and more generally with any
    objects that have disjoints predicates.

    ## Specification

    ### `(make-single-dispatch) → procedure`

    Return a single-dispatch procedure. A single-dispatch procedure has
    the same type as any other procedure.

    ### `(single-dispatch-register single-dispatch predicate? proc) → unspecified`

    Register `PROC` to be called when `SINGLE-DISPATCH` is passed as first
    argument an object for which `PREDICATE?` returns `#t`.

    ### Calling a single-dispatch procedure

    A single-dispatch procedure when called with a first argument for
    which there is one and only one predicate registered with `single-dispatch-register` returns `#t` will pass all the arguments to
    the procedure that was associated with it.

    When called with zero arguments the implementation must error. That
    is, it can only be called with one or more arguments.

    The implementation must error if the first argument can be associated
    with more than one predicate registered with
    `single-dispatch-register`.

    If no registered predicate return `#t`, the implementation must error.

    ## Implementation

    ```scheme
    (library (single-dispatch)

    (export make-single-dispatch
    single-dispatch-register)

    (import (chezscheme))

    (define %register (list '%register))

    (define (make-single-dispatch)
    (let ((%dispatcher '()))
    (lambda (obj . rest)
    (let loop ((dispatcher %dispatcher))
    (if (null? dispatcher)
    (cond
    ((eq? obj %register)
    (set! %dispatcher (cons (cons (car rest) (cadr rest)) %dispatcher)))
    ((null? %dispatcher)
    (error 'single-dispatch "there is no procedure registred"))
    (else (error 'single-dispatch "unknown object")))
    (if ((caar dispatcher) obj)
    (apply (cdar dispatcher) obj rest)
    (loop (cdr dispatcher))))))))

    (define (single-dispatch-register single-dispatch predicate? proc)
    (assert (procedure? predicate?))
    (assert (procedure? proc))
    (single-dispatch %register predicate? proc)))
    ```

    ## Acknowledgements

    Give credits where credits is due.

    ## Copyright

    Copyright (C) Amirouche Boubekki (2019).

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Takashi Kato@21:1/5 to All on Sat Oct 26 13:26:04 2019
    What do you think?
    It looks like a method of CLOS. You may also want to check R7RS portable CLOS implementation: https://github.com/ktakashi/r7rs-clos
    For R6RS you may want to check this: https://akkuscm.org/packages/r6rs-clos/

    NOTE: for R7RS, it's based on tiny CLOS implementation.

    Cheers,
    Takashi

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Amirouche Boubekki@21:1/5 to Takashi Kato on Wed Oct 30 10:03:00 2019
    On Saturday, October 26, 2019 at 10:26:06 PM UTC+2, Takashi Kato wrote:
    What do you think?
    It looks like a method of CLOS. You may also want to check R7RS portable CLOS implementation: https://github.com/ktakashi/r7rs-clos
    For R6RS you may want to check this: https://akkuscm.org/packages/r6rs-clos/

    NOTE: for R7RS, it's based on tiny CLOS implementation.

    Thanks.

    Eventually, I did not need single dispatch, I use the following procedure:

    (define (make-invoker accessor)
    (lambda (engine . args)
    (apply (accessor engine) args)))


    (define engine-open (make-invoker %engine-open))

    ref: https://github.com/scheme-requests-for-implementation/srfi-167/blob/master/srfi/engine.sld

    By the SRFI-167 and SRFI-168 entered the last step of the SRFI process.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)