Re: behavior of CASE with strings

Damien Mattei <[email protected]>
Newsgroups gmane.lisp.scheme.bigloo,gmane.lisp.scheme.kawa
Message-ID <CADEOaddqzUjnxOMzcU1=n=yRZTgyr85CDZ7Kw6q=WCjNM+Q85A@mail.gmail.com>
Hi,

i could used string->symbol instead of stings with the normal CASE but
i finally wrote a macro for CASE with strings,
it was harder than expected , i learned macro at university with the
define-macro style ,i was familiar with this style, now define-syntax is
used, here is my macro:

(define-syntax case-string

  (syntax-rules ( => )


    ;; (define dog "dog")
    ;; (case-string dog (("dog") "animal")   (else => "mineral or
vegetable"))
    ((case-string var
          lst
          (else => res-else  ...))

     (if (member var (car (quote lst)))
       (cadr (quote lst))
       (begin
         res-else
         ...)))

    ;; (define cat "cat")
    ;; (case-string cat (("dog") "animal") (("cat") "my daughter say cats
are not animals!")  (else => "mineral or vegetable"))
    ((case-string var
              lst
              lst2
              ...
              (else => res-else ...))

     (if (member var (car (quote lst)))
     (cadr (quote lst))
     (case-string var
              lst2
              ...
              (else => res-else ...))))



    ;;(case-string dog  (else => "silly case"))
    ((case-string var
          (else => res-else ...))

     (begin
       res-else
       ...))))

i'm not sure if this macro is r5rs compliant but i have test it working.

Regards,

 Damien

On Tue, Jan 17, 2017 at 8:27 PM, Bent Phillipsen <[email protected]>
wrote:

> Hi Damien,
>
> This question has already been answered. Should it be of interest, I would
> like to add the following:
>
> R5RS specifies that the case expression tests equivalence with eqv?
> (p.10), but also that equivalence test of strings with eqv? is
> 'unspecified' (p.18). This has the consequence that stings cannot be used
> as key and clause in case expressions in a well defined way (or at least
> portable way). You can however easily define a macro that *also* can use
> strings. You can write your own; but simply taking the case macro defined
> in R5RS (p.43) ensures that all corner cases are handled correctly. You
> then just need to replace 'memv' with 'member' (this has the effect of
> testing equivalence with equal? instead of eqv?). You probably want to
> change the name of the macro also, for instance to case-member, to avoid
> shadowing the original case expression. You will get something like the
> following, which should work and which I think is portable. (There is of
> cause a (mostly insignificant) performance penalty in testing with equal?
> instead of eqv?):
>
> --------------------------------------
>
> (module test-case-member
>         (main start))
>
> (define-syntax case-member
>         (syntax-rules (else)
>                 ((case-member (key ...)
>                         clauses ...)
>                  (let ((atom-key (key ...)))
>                         (case-member atom-key clauses ...)))
>                 ((case-member key
>                         (else result1 result2 ...))
>                  (begin result1 result2 ...))
>                 ((case-member key
>                         ((atoms ...) result1 result2 ...))
>                  (if (member key '(atoms ...))
>                         (begin result1 result2 ...)))
>                 ((case-member key
>                         ((atoms ...) result1 result2 ...) clause clauses
> ...)
>                  (if (member key '(atoms ...))
>                         (begin result1 result2 ...)
>                         (case-member key clause clauses ...)))))
>
> (define (start argv)
>
>         (define x (string-append "b" "a" "r"))
>         (define y "animal")
>         (define z 'composit)
>
>         (print "next line should be '" y "':")
>         (print (case-member (string-append "do" "g") (("cat" "dog"
> "mouse") y) (else "mineral or vegetable")))
>
>         (print (string-append "next line should be '" x "':"))
>         (case-member x
>                 (("foo")  (print 'foo))
>                 (("bar")  (print 'bar))
>                 (else "it was not foo or bar"))
>
>         (print (string-append "next line should be '" (symbol->string z)
> "':"))
>         (print (case-member (* 2 3) ((2 3 5 7) 'prime)
>                                     ((1 4 6 8 9) z))))
>
> ---------------------------------
>
> Best regards
>
> Bent
>
>
> 2017-01-16 14:32 GMT+01:00 <[email protected]>:
>
>> Hi Damien,
>>
>> Bigloo complies with the R5RS specification (see section 4.2) that says:
>>
>> -----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
>> -----|-----|-----
>> case <key> <clause1> <clause2> ...,     library syntax
>> Syntax: <Key> may be any expression. Each <clause> should have the form
>>
>> ((<datum1> ...,) <expression1> <expression2> ...,),
>>
>> where each <datum> is an external representation of some object. All the
>> <datum>s must be distinct. The last <clause> may be an ``else clause,''
>> which has the form
>>
>> (else <expression1> <expression2> ...,).
>>
>> Semantics: A case expression is evaluated as follows. <Key> is evaluated
>> and its result is compared against each <datum>. If the result of
>> evaluating <key> is equivalent (in the sense of eqv?; see section
>> Equivalence predicates) to a <datum>, then the expressions in the
>> corresponding <clause> are evaluated from left to right and the result(s)
>> of the last expression in the <clause> is(are) returned as the result(s) of
>> the case expression. If the result of evaluating <key> is different from
>> every <datum>, then if there is an else clause its expressions are
>> evaluated and the result(s) of the last is(are) the result(s) of the case
>> expression; otherwise the result of the case expression is unspecified.
>>
>> (case (* 2 3)
>>   ((2 3 5 7) 'prime)
>>   ((1 4 6 8 9) 'composite))            =>  composite
>> (case (car '(c d))
>>   ((a) 'a)
>>   ((b) 'b))                            =>  unspecified
>> (case (car '(c d))
>>   ((a e i o u) 'vowel)
>>   ((w y) 'semivowel)
>>   (else 'consonant))                   =>  consonant
>> -----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
>> -----|-----|-----
>>
>> You can observe that with:
>>
>> (pp (expand '(case x (("foo") 1) (("bar" ) 2))))
>> =>
>> (let ((case-value x))
>>   (if (eqv? case-value '"foo")
>>     1
>>     (if (eqv? case-value '"bar") 2 #unspecified)))
>>
>> Cheers,
>>
>> --
>> Manuel
>>
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.