Match if two values in an unorded list are the same
Asked Answered
B

2

6

I have a Racket list with some values (list 'foo 'bar 2 #t 42 9 2 'some). In reality these values follow some more specific pattern but for the question this is irrelevant. I want to test test if there are two identical values in the list, in this case the number 2, and get the element and the other elements. This is my attempt:

#lang racket

(match (list 'foo 'bar 2 #t 42 9 2 'some)
  [(list-no-order a a rest ...)
     "Do some stuff"]
  [_ "Do some other stuff"])

The pattern is (list-no-order a a rest ...). But the interpretation of the program fails with:

a11: unbound identifier;
 also, no #%top syntax transformer is bound in: a11

To me it looks an error when transforming the macro. If one changes list-no-order to list the pattern works but of course only if the elements are at the beginning of the list.

Is my pattern wrong, if so how to correct it or is the intended pattern not possible and what is the best way to work around it?

Bering answered 7/4, 2016 at 20:35 Comment(6)
Here's a result after macro expansion of (match (list 2 2 #t) [(list-no-order asd asd dsa) "Do some stuff"]): pastebin.com/K3PG44kY. We can see that there's an unbound id asd8. Perhaps the macro is buggy?Purapurblind
How certain are you that this is a bug? Should I report it to the Racket developers?Bering
Reported at Github.Bering
Thank you for submitting this as a bug report. :)Kcal
After filing the bug report I found out that the bug was already reported in 2009 and resubmitted by others. For the bug reports a person called samth is responsible with 266 open bugs assigned. There is no movement at all for these reports and I doubt that this will change in the next years. Of course I could try to fix it myself since it is open-source but I would need to learn complex Racket syntax transformations first. Quite disappointing. :-(Bering
*by othersBering
S
1

For now, the best work-around is to use a #:when condition:

#lang racket

(match (list 'foo 'bar 2 #t 42 9 2 'some)
  [(list-no-order a b rest ...)
   #:when (equal? a b)
   "Do some stuff"]
  [_ "Do some other stuff"])
Schooling answered 17/8, 2018 at 21:3 Comment(0)
A
0

I wonder why you are trying to pattern match something. Its not clear to me via your question and code. I would approach your problem via pure list processing (at least as far as I understand)

(filter
    (lambda (x)
        ;;filter for the first element of the prev created tuple and 
        ;;check if its larger than 1
        (> (first x) 1))
    (map
        (lambda (x)
            ;;tuple of the length of the prevously created group and the group itself
            (cons (length x) x))
        (group-by
            ;;just the element it seld
            (lambda (x)
                x)
            (list 'foo 'bar 2 #t 42 9 2 'some))))
Assagai answered 14/2, 2017 at 10:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.