chris613
2019-10-1 09:00:49

thanks @spdegabrielle


stefan.kruger
2019-10-1 13:33:41

I wanted to find the first element in a list which has no duplicates. I came up with: (define xs '(1 1 1 1 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 3)) (for/first ([x (in-list xs)] #:when (= 1 (count (curry = x) xs))) x)


stefan.kruger
2019-10-1 13:34:23

Which works — and looks cute :slightly_smiling_face: — but is probably horrendously inefficient. How can I make it better?


stefan.kruger
2019-10-1 13:36:21

I guess doing this should be better? (for/first ([x (in-list (remove-duplicates xs))] #:when (= 1 (count (curry = x) xs))) x)


stefan.kruger
2019-10-1 13:39:29

Feels like this could be done better using sets maybe.


soegaard2
2019-10-1 13:48:43
(define (first-unique xs)
  (define ht (make-hash))
  (define (add! x) (hash-update! ht x add1 0))
  (for-each add! xs)
  (for/or ([x xs]) (and (= 1 (hash-ref ht x)) x)))

stefan.kruger
2019-10-1 13:52:35

Nice (and fast).


soegaard2
2019-10-1 13:53:32

My first idea was to use a multi set (bag), but I couldn’t find one.


mark.warren
2019-10-1 13:55:58

Could use a hash map but that sounds inefficient.


soegaard2
2019-10-1 13:58:14
(require rebellion/collection/multiset)

(define (first-unique xs)
  (define m (list->multiset xs))
  (for/or ([x xs])
    (and (= 1 (multiset-frequency m x)) x)))

soegaard2
2019-10-1 13:59:34
(require rebellion/collection/multiset)

(define (first-unique xs)
  (define m (list->multiset xs))
  (for/first ([x xs] #:when (= (multiset-frequency m x) 1))
    x))

stefan.kruger
2019-10-1 14:09:13

rebellion?


stefan.kruger
2019-10-1 14:09:28

googles


samdphillips
2019-10-1 14:39:10

Yes Rebellion’s multiset is the same as a bag.


samdphillips
2019-10-1 14:40:56

(sorry catching up)


samdphillips
2019-10-1 14:55:43

This one works in one pass. It depends on the input being sorted though (per the example) (define (first-unique vs) (define (step prev vs) (match vs [(list) #f] [(list (== prev) vs ...) (step prev vs)] [(list x y vs ...) (cond [(equal? x y) (step y vs)] [else x])])) (match vs [(list) #f] [(cons v vs) (step v vs)]))


rokitna
2019-10-1 15:28:40

eyeballing it, that looks like it would return 2 for (list 1 2 3)and raise a “no matching clause found” error for (list 1 2)


aymano.osman
2019-10-1 15:40:10

... matches 0 or more,


aymano.osman
2019-10-1 15:40:45

so the two essential cases are covered, empty list and list of at least one element.


aymano.osman
2019-10-1 15:41:44

I didn’t know about the match expander ==! Glad I know now.


stefan.kruger
2019-10-1 15:47:12

Right. Don’t understand how that works :slightly_smiling_face:


stefan.kruger
2019-10-1 15:50:29

What does (list (== prev) vs ...) mean?



stefan.kruger
2019-10-1 15:57:20

I realize I’m a long way from any sort of mastery of this :confused:


rokitna
2019-10-1 16:55:32

That branch matches lists of 0 elements, list of 1 or more elements where the first is equal to prev, and other lists of 2 or more elements, but it doesn’t have a clause for lists of 1 or more elements where the first isn’t prev


rokitna
2019-10-1 16:56:05

er, lists of exactly one element which isn’t prev


notjack
2019-10-1 17:10:19

beware that multisets are unordered! so you won’t necessarily get the first element with only one occurrence, you’ll just get an element


samdphillips
2019-10-1 17:12:59

Good catch. An additional clause [(list x) x] solves that.


badkins
2019-10-1 17:27:34

Is the list sorted?


badkins
2019-10-1 18:05:12

Nice procrastination exercise for me :slightly_smiling_face: Assumes a sorted list where #f is not a valid element.


notjack
2019-10-1 18:09:54

@badkins If you’d like to get it to work with lists containing #f, Rebellion also provides an option type which is either a (present v) value or the absent constant.


badkins
2019-10-1 18:11:01

Thanks @notjack - this was just a “what’s the first one-pass solution that pops out of my head” sort of thing :slightly_smiling_face:


notjack
2019-10-1 18:13:43

It’s a great solution :simple_smile:


badkins
2019-10-1 18:15:33

I don’t like seeing multiple (loop (cdr lst) though


notjack
2019-10-1 18:16:08

Tangent: there’s also “reducers” in Rebellion which are basically “one-pass operations on sequences”. Your approach would make for a good reducer, which would make it work on arbitrary sequences.


badkins
2019-10-1 18:16:27

I’ll definitely have to check out Rebellion.



badkins
2019-10-1 19:01:03

Hmm… I thought I’d try and create a macro next that I could use as (next #f element) instead of (loop (cdr lst) #f element) - it’s not as trivial as I’d hoped. What is the general mechanism for referring to an existing binding such as loop and lst ?


badkins
2019-10-1 19:17:00

To clarify, I’d like to the macro to refer to a binding that doesn’t exist at macro definition time, but does exist at macro invocation time.


notjack
2019-10-1 19:19:28

Could you make a helper function that calls loop?


badkins
2019-10-1 19:22:43

@notjack I’m not positive, but I don’t think so. I’m not exactly sure how “named let” is implemented, but I just tried a simple helper unsuccessfully


badkins
2019-10-1 19:23:48

And even if it’s possible, I’d really like to know how to refer to bindings in a “simple substitution” manner.


badkins
2019-10-1 19:24:53

oops - hold on!


badkins
2019-10-1 19:25:48

<sigh> I had a stupid error that probably affected all of my macro attempts also :disappointed: Yes, the helper works fine.


yfangzhe
2019-10-1 19:27:22

How to input characters like “ℕ” in DrRacket with keybind, like “\alpha” and then “C-“?


notjack
2019-10-1 19:27:41

On the bright side, now you’ve got it working :grin:


badkins
2019-10-1 19:30:28
(define-simple-macro (next a b)
  #:with loop (datum-&gt;syntax #'a 'loop)
  #:with lst  (datum-&gt;syntax #'a 'lst)
  (loop (cdr lst) a b))

notjack
2019-10-1 19:41:06

@badkins if you define the macro locally, inside the scope where you want to use it, it should work without the #:with clauses


badkins
2019-10-1 19:42:42

Confirmed


aymano.osman
2019-10-1 23:51:55

I have a pict question. I have a png image which I would like to draw on top of. I want to draw a green tick or a red cross on the png. How do I do that?


aymano.osman
2019-10-1 23:52:05

Or maybe I need another library?


shu--hung
2019-10-2 00:04:30

shu--hung
2019-10-2 00:04:44

and bitmap creates a pict? from an image file. I dont’ know if there’s a better approach though.


aymano.osman
2019-10-2 00:05:09

I found read-bitmap from racket/draw too. I’ll try them all out thanks.


shu--hung
2019-10-2 00:05:27

read-bitmap is for creating bitmap% objects afaik


aymano.osman
2019-10-2 00:06:01

you are correct


aymano.osman
2019-10-2 00:06:36

I’m not sure what the relationship between the two libraries is or where is best to start.


shu--hung
2019-10-2 00:08:02

IIUC, bitmap% from racket/draw is a lower-level primitive that let you draw almost everything, working at the pixel level


notjack
2019-10-2 00:08:06

@aymano.osman You can turn the png into a pict, then make a separate pict with your green tick / red cross, then combine them with cc-superimpose which will put one pict directly on top of the center of another


shu--hung
2019-10-2 00:08:10

and pict is an abstraction for pictures


notjack
2019-10-2 00:09:29

And the bitmap function will, given a path to a png file, read that file and give you back a pict


notjack
2019-10-2 00:11:31

So if you have /path/to/base-image.png and /path/to/green-tick.png, you can combine them with this: (define base-image (bitmap "/path/to/base-image.png")) (define green-tick (bitmap "/path/to/green-tick.png")) (cc-superimpose base-image green-tick)


aymano.osman
2019-10-2 00:14:19

perfect :slightly_smiling_face: thanks


notjack
2019-10-2 00:16:34

@aymano.osman You’re welcome :simple_smile: also, here’s some real-world example code where I loaded a png file into a pict: https://github.com/jackfirth/chess/blob/346d0506d367890ee67f67f2f2495dda01e1ca4e/pict.rkt#L34-L82


aymano.osman
2019-10-2 00:18:28

Nice. That looks like it will be very helpful.