hello,
i needed a single symbol to define a new syntax but almost all those that can be directly typed on an US keyboard are already used.
i wanted to use the underscore _ as a keyword (i think of / but my syntax can use numeric computation so no / is already used, i think of : but it is already used SRFI eager comprehension.
so i think now to use _ (underscore):
type or > _
_: wildcard not allowed as an expression in: _paste code here
it seems to be used in special case in scheme (Guile too...)
and i want to use it in this special syntax as a keyword:
> {T <+ (vector 1 2 3 5 6 7)}
'#(1 2 3 5 6 7)
> {T2 <+ T[2 _ 5]}
_: wildcard not allowed as an expression in: _
so i decided to do that, a bit ugly it is, i overwrite _ :
(define _ '())
(define slice _)
and now it works:
Welcome to DrRacket, version 8.6 [cs].
Language: reader "../Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/SRFI/SRFI-105-toplevel.rkt", with debugging; memory limit: 14000 MB.
> {T <+ (vector 1 2 3 5 6 7)}
'#(1 2 3 5 6 7)
> {T2 <+ T[2 _ 5]}
'#(3 5 6)
and we can still use _ as defined in Scheme language:
> (define xs (build-list 5 (λ _ (random))))
> xs
'(0.26274433048693946 0.6228901421560789 0.3809531045235335 0.4011282367712523 0.5968311471261267)
>
the macro definition of bracket-apply from SRFI 151 that i develop is this portion ,used in this example for RHS (right expression):
(define-syntax $bracket-apply$
(syntax-rules ()
;; 1 argument in []
;; T[index]
((_ container index)
..............................code cut ........................................
;; 3 arguments in []
;; T[i1 / i2] , T[i1 i2 i3] , T[/ / s]
((_ container index1-or-keyword index2-or-keyword index3-or-keyword-or-step)
($>
;; this portion evaluate the macro's arguments
;; to avoid compute it twice or many
{container-eval <+ container}
{index1-or-keyword-eval <+ index1-or-keyword}
{index2-or-keyword-eval <+ index2-or-keyword}
{index3-or-keyword-or-step-eval <+ index3-or-keyword-or-step}
;; {#(1 2 3 4 5 6 7)[2 / 5]}
;; '#(3 4 5)
(cond ((vector? container-eval) ;; 3 dimension vector T[i1 i2 i3]? or T[i1 / i3] or T[/ / step] or T[/ i2 /] or T[i1 / /]
;; {#(1 2 3 4 5 6 7 8)[/ / 3]}
;; '#(1 4 7)
;; {#(1 2 3 4 5 6 7 8)[/ / -2]}
;; '#(8 6 4 2)
(cond ((and (equal? slice index1-or-keyword-eval) ;; T[/ / step]
(equal? slice index2-or-keyword-eval))
(when (= 0 index3-or-keyword-or-step-eval)
(error "$bracket-apply$ : slice step cannot be zero"))
(let* ((size-input (vector-length container-eval))
(size (quotient size-input (abs index3-or-keyword-or-step-eval)))
(result '())
(i 0))
(when (not (= (modulo size-input index3-or-keyword-or-step-eval) 0))
(set! size (+ 1 size)))
(set! result (make-vector size))
(if (< index3-or-keyword-or-step-eval 0) ;; with negative index we start at end of vector (like in Python)
(for ((define k (- size-input 1)) (>= k 0) (set! k (+ k index3-or-keyword-or-step-eval)))
(vector-set! result
i
(vector-ref container-eval k))
(set! i (+ 1 i)))
(for ((define k 0) (< k size-input) (set! k (+ k index3-or-keyword-or-step-eval)))
(vector-set! result
i
(vector-ref container-eval k))
(set! i (+ 1 i))))
result))
((equal? slice index2-or-keyword-eval) ;; T[i1 / i3]
(when (< index1-or-keyword-eval 0) ;; negative index
(set! index1-or-keyword-eval (+ (vector-length container-eval) index1-or-keyword-eval)))
(when (< index3-or-keyword-or-step-eval 0) ;; negative index
(set! index3-or-keyword-or-step-eval (+ (vector-length container-eval) index3-or-keyword-or-step-eval)))
(vector-copy container-eval index1-or-keyword-eval index3-or-keyword-or-step-eval))
((equal? slice index2-or-keyword-eval) ;; T[i1 / /]
(when (< index1-or-keyword-eval 0) ;; negative index
(set! index1-or-keyword-eval (+ (vector-length container-eval) index1-or-keyword-eval)))
(vector-copy container-eval index1-or-keyword-eval))
.................. code cut ...................................;;
note: i no more use / that still is in comments, i use now _
in the LHS (left hand side) for assignation, example:
;; T[i1 / i2 / step]
> {s <+ (string-append "abcdefgh")}
"abcdefgh"
> {s[2 _ 7 _ 2] <- "0000"}
> s
"ab0d0f0h"
> (display s)
ab0d0f0h
the code use match pattern which require evaluated expressions, not symbols, here is a piece of the relevant code:
.................... header cut ........................;
;; scheme@(guile-user)> {T[3] <- T[2]}
;; $bracket-apply$
;; <- : vector or array set!
;; $4 = 4
;; scheme@(guile-user)> {T[3]}
;; $bracket-apply$
;; $5 = 4
;; scheme@(guile-user)> '{x <- y <- 7}
;; $1 = (<- x y 7)
;; $bracket-apply$ is from SRFI 105 bracket-apply is an argument of the macro
(define-syntax <-
(syntax-rules ()
((_ (bracket-apply container index) expr)
............................code cut .......................;
;; this portion of Scheme+ is written in... Scheme+ !!!
;; 5 arguments in []
;; ex: T[i1 / i2 / step] , T[i1 i2 i3 i4 i5]
;; {s[2 / 7 / 2] <- "000000000000"[3 / 7 / 1]}
((_ (bracket-apply container index1 index2-or-keyword index3 index4-or-keyword index5-or-step) expr)
($>
(unless (equal? (quote $bracket-apply$) (quote bracket-apply))
(error "Bad <- form: the LHS of expression must be an identifier or of the form ($bracket-apply$ array index1-or-keyword-or-step ...) , first argument "
(quote bracket-apply)
" is not $bracket-apply$."))
;; this portion evaluate the macro's arguments
;; to avoid compute it twice or many
{container-eval <+ container}
{index1-eval-pos <+ index1-eval <+ index1}
{index2-or-keyword-eval-pos <+ index2-or-keyword-eval <+ index2-or-keyword}
{index3-eval-pos <+ index3-eval <+ index3}
{index4-or-keyword-eval-pos <+ index4-or-keyword-eval <+ index4-or-keyword}
{index5-or-step-eval-pos <+ index5-or-step-eval <+ index5-or-step}
{expr-eval <+ expr}
(declare container-length container-copy!)
(if (vector? container)
($
{container-length <- vector-length}
{container-copy! <- vector-copy!})
($ ;; a string
{container-length <- string-length}
{container-copy! <- string-copy!}))
;; transform the negative indexes in positive ones when not slices
(when {(not (equal? index1-eval-pos slice)) and {index1-eval-pos < 0}}
{index1-eval-pos <- (container-length container-eval) + index1-eval-pos})
(when {(not (equal? index2-or-keyword-eval-pos slice)) and {index2-or-keyword-eval-pos < 0}}
{index2-or-keyword-eval-pos <- (container-length container-eval) + index2-or-keyword-eval-pos})
(when {(not (equal? index3-eval-pos slice)) and {index3-eval-pos < 0}}
{index3-eval-pos <- (container-length container-eval) + index3-eval-pos})
(when {(not (equal? index4-or-keyword-eval-pos slice)) and {index4-or-keyword-eval-pos < 0}}
{index4-or-keyword-eval-pos <- (container-length container-eval) + index4-or-keyword-eval-pos})
(when {(not (equal? index5-or-step-eval-pos slice)) and {index5-or-step-eval-pos < 0}}
{index5-or-step-eval-pos <- (container-length container-eval) + index5-or-step-eval-pos})
(match (list index1-eval-pos index2-or-keyword-eval-pos index3-eval-pos index4-or-keyword-eval-pos index5-or-step-eval-pos)
;; T[i1 / i2 / step]
;; {s <+ (string-append "abcdefgh")}
;; "abcdefgh"
;; > {s[2 / 7 / 2] <- "0000"}
;; > s
;; "ab0d0f0h"
((list i1 (== slice) i2 (== slice) step-not-used)
{step <+ index5-or-step-eval}
(copy-stepped-slice container-eval expr-eval i1 i2 step))
;; T[i1 i2 i3 i4 i5]
((list i1 i2 i3 i4 i5)
;; normal case
(if (vector? container-eval)
(function-array-n-dim-set! container-eval expr-eval (reverse (list i1 i2 i3 i4 i5))) ;;(array-n-dim-set! array expr-eval i1 i2)
(array-set! container-eval index1-eval index2-or-keyword-eval index3-eval index4-or-keyword-eval index5-or-step-eval expr-eval)))
) ;; match
) ;; $>
) ;; ((_ (bracket-apply container ...
.................................. code cut ...............................................
(define (copy-stepped-slice container-eval expr-eval i1 i2 step)
(when {step = 0}
(error "assignment : slice step cannot be zero"))
{i <+ 0}
(if {step < 0} ;; with negative index we start at end of vector (like in Python)
(for ({k <+ i2} {k >= i1} {k <- k + step})
{container-eval[k] <- expr-eval[i]}
{i <- i + 1})
(for ({k <+ i1} {k < i2} {k <- k + step})
{container-eval[k] <- expr-eval[i]}
{i <- i + 1})))
i'm asking if it could not break something in other scheme code to redefine _ ?
for now it seems no , i can use it in the macros,even in macros given in the above code that use _ as pattern and _ as a keyword inspired from : from Python.
Anyway i want a single character keyword like _ or : , : is used in Python ,example T[1:3]
but if someone have another idea?
regards,
Damien