sorawee
2021-7-21 07:00:35

yeah


xlambein
2021-7-21 07:01:10

Yep I see :thinking_face: I tend to feel like imperativity isn’t too bad, as long as it’s controlled and encapsulated within functional interfaces. I like Rust a lot for that reason.


xlambein
2021-7-21 07:02:05

Also I find some stuff easier to express imperatively, but that’s probably because it’s all I’ve done for my first ten years of programming? :sweat_smile:


sschwarzer
2021-7-21 07:02:40

Yes, functional APIs is usually the style I (try to) use. :slightly_smiling_face:


sschwarzer
2021-7-21 07:03:46

> Also I find some stuff easier to express imperatively, but that’s probably because it’s all I’ve done for my first ten years of programming?

Yes, that’s most likely the reason. :wink: It also took me a while to get used to FP style.


xlambein
2021-7-21 07:05:46

Yeah that seems to be the usual experience :D


sschwarzer
2021-7-21 07:06:17

Regarding the typical recursive factorial example, I went from “Who would actually do this?” to “Ok, you could do that.” to “Why not?” :smile:


xlambein
2021-7-21 07:07:25

Yeah I remember learning the basics of functional programming at university, like, five years ago, and thinking it was bonkers and uselessly complicated :sweat_smile:


sschwarzer
2021-7-21 07:07:49

But yes, I’m also much more fluent in imperative programming, but I enjoy the “flow” of FP. And of s-expressions.


xlambein
2021-7-21 07:10:01

I really didn’t think I’d ever enjoy writing with sexps. When I started learning Racket, I thought I’d just have to live with it. But then surprisingly quickly I came to understand and like it


notjack
2021-7-21 07:10:59

I think if we add this to the standard library, it should have an #:ordered? keyword argument that defaults to true that indicates whether the cartesian product should be iterated in the standard order


sschwarzer
2021-7-21 07:13:34

I didn’t know there was a “standard” order, but rather a “typical” order.

#:ordered? would be somewhat confusing because the second version orders the yielded items, too, just in a different order.


sschwarzer
2021-7-21 07:14:46

In the context of iterating over multi-dimensional arrays, I saw the term “faster changing index” (or similar), but I guess we should try to find better terminology. :slightly_smiling_face:


sschwarzer
2021-7-21 07:17:23

FWIW, a few days ago I came across a Python program where I specifically needed the order from @sorawee’s second implementation. But I found you can convert from cartesian-product by reversing the input sequences and the yielded/returned items.


sschwarzer
2021-7-21 07:19:00

But of course the reversing, which I did with (map reverse cartesian-product-result) in my Racket experiments, rebuilds the whole outer list, which costs time and memory.


notjack
2021-7-21 07:27:13

I would guess that most people would assume the order of a cartesian product is the same order that the equivalent nested for loops would iterate in


sschwarzer
2021-7-21 07:28:11

@notjack Yes, most likely. If we have a “default order”, it should be this one from cartesian-product.


notjack
2021-7-21 07:28:16

but that’s an inefficient order to iterate in if the input sequences are very large (or infinite)


notjack
2021-7-21 07:28:38

for instance, I think (in-cartesian-product (in-naturals) (in-naturals)) is a totally reasonable use case


sschwarzer
2021-7-21 07:29:31

If this is nested, it would stick to 0 for one index though?


sorawee
2021-7-21 07:30:16

If you want something like (in-cartesian-product (in-naturals) (in-naturals)) to work, I suggest the bijective enumeration


notjack
2021-7-21 07:30:23

yes, which would be bad - I can’t imagine a user who’s providing infinite sequences as input would not want to also specify that they don’t care what order the products are iterated in


notjack
2021-7-21 07:31:26

I think ordered by default and bijective if the client specifies unordered would be reasonable


notjack
2021-7-21 07:32:52

I’m biased though - I recently hit this same issue while designing the transposing transducer in rebellion, and I went with that approach: https://docs.racket-lang.org/rebellion/Transducers.html#%28def._%28%28lib._rebellion%2Fstreaming%2Ftransducer..rkt%29._transposing%29%29


sorawee
2021-7-21 07:36:08

(require data/enumerate/lib) (define my-enum/e (cons/e natural/e natural/e)) (for/list ([x (in-enum my-enum/e)] [i 100]) x)


notjack
2021-7-21 07:36:25

nice :p


notjack
2021-7-21 07:36:42

at least we have somewhere to copy the algorithm from


sschwarzer
2021-7-21 07:37:03

Nice. Very nice. :slightly_smiling_face:



sorawee
2021-7-21 07:37:43

There are two possible ordering for cons/e


notjack
2021-7-21 07:37:46

oh wow it even does the ordering thing


sorawee
2021-7-21 07:38:18

Yeah, otherwise it wouldn’t be bijective :slightly_smiling_face:


notjack
2021-7-21 07:38:30

I mean the keyword argument to control ordering part :p


sorawee
2021-7-21 07:38:35

Ah, right


notjack
2021-7-21 07:40:09

> (enum->list (cons/e natural/e natural/e #:ordering 'square) 10) '((0 . 0) (0 . 1) (1 . 0) (1 . 1) (0 . 2) (1 . 2) (2 . 0) (2 . 1) (2 . 2) (0 . 3))


sorawee
2021-7-21 07:40:31

> If ordering is ’square, it uses a generalized form of Szudzik’s “elegant” ordering and if ordering is ’diagonal, it uses a generalized form of Cantor’s mapping from pairs of naturals to naturals.



notjack
2021-7-21 07:40:40

hmm


notjack
2021-7-21 07:40:49

which of those is…. good?


notjack
2021-7-21 07:41:25

what on earth is “Szudzik’s elegant ordering”


sorawee
2021-7-21 07:41:30

notjack
2021-7-21 07:43:01

huh


notjack
2021-7-21 07:45:03

neat, and I think that should actually be the only option for unordered in-cartesian-product because it won’t look at the n+1th element of any input sequence before exhausting all possible combinations that can be constructed by looking up to the nth element of every input sequence


notjack
2021-7-21 07:46:00

so it maximizes laziness


sorawee
2021-7-21 07:46:51

I don’t know how to use the bijective enumeration with sequences though


sorawee
2021-7-21 07:47:10

Like, we can convert a bijective enumeration to a sequence


sorawee
2021-7-21 07:47:17

But I don’t think the opposite can be done?


sorawee
2021-7-21 07:47:35

There’re special cases like natural/e, but not any sequence in general


notjack
2021-7-21 07:47:35

yeah I think you’d have to rip out the algorithm and reimplement it in terms of plain sequences that are iteratively evaluated



alexharsanyi
2021-7-21 08:46:00

soegaard2
2021-7-21 13:23:33

@samdphillips Hi. Following your lead, the sketching now builds and deploys its docs directly. The trickiest part (after seeing how you used James Ives github-deploy-action) was to get the path right. It helped, when I inserted an ls -r * to see what was going on…


badkins
2021-7-21 16:57:49

Just to tie up this loose end. While I’m still not sure why the contract error message is missing one of the arguments on my production system running Racket 7.3 BC, I was able to recreate the scenario on my dev machine running Racket v8.1.0.6 [cs], and the contract error message is correct. It appears to be a bug in 7.3 exhibited by my particular scenario, but since it seems fixed (if it was a bug) in my current version of Racket, I’m not going to dig any further.


djholtby
2021-7-21 17:59:10

So I’m trying to narrow down unexpected behaviour with dynamic-rerequire (it won’t reload a file if the source file itself hasn’t changed, but a dependency has)

I’ve fixed this when loading from source (by having it reload if the timestamp is newer, OR if a dependency was reloaded), but the fix doesn’t work if they’re being loaded from .zo files (built using raco make --disable-constant)

What I’ve discovered is that if you have a directory called “private” that contains “a.rkt” and “b.rkt”, and a requires b then module-compiled-imports gives a list that contains #<module-path-index:"b.rkt" + a[4893]> So far so good. But when check-latest is descending through the dependencies, this module-path-index doesn’t seem to behave correctly.

If I use module-path-index-resolve on that module-path-index? then the behaviour depends on how those files were loaded. If they were loaded from source, then I get a path to the “b.rkt” file I expect, "./private/b.rkt", and if this file gets reloaded then with my patch, “a.rkt” also gets reloaded.

If they were loaded from a .zo file, then instead I get an path that tries to point to “b.rkt” in the current directory e.g. "./b.rkt" (which isn’t where it is located). Since that file isn’t in the cache, the loop does not descend into that dependency (meaning b.rkt will not be reloaded).


mflatt
2021-7-21 18:28:54

I’m not sure what’s happening, but when a “.zo” file is loaded, the resolved module path and/or current load-relative directory should be set to the “.rkt” file name, as opposed to the “.zo” name, while loading the code. But assuming that you haven’t changed the way rerequire-load/use-compiled uses get-module-code, that should be done right already.


mflatt
2021-7-21 18:30:21

.. or maybe it isn’t done right already, and that’s where the problem is


djholtby
2021-7-21 18:34:10

I didn’t touch rerequire-load/use-compiled only the loop inside check-latest


mflatt
2021-7-21 18:34:22

On reflection, I guess get-module-code doesn’t tie the loaded code to the file that it was loaded from. So, probably those module path indices from module-compiled-imports need to be rebuilt on a module path index in place of the “self” one that has the “.rkt” file’s path.


mflatt
2021-7-21 18:34:42

Otherwise, module-path-index-resolve will use the current [load-relative] directory.


mflatt
2021-7-21 18:37:01

Another approach to repairing the current code may be to use resolve-module-path-index function, which lets you provide the “self” path as the second argument.


djholtby
2021-7-21 18:40:38

Alright, I think I had something working along those lines but wasn’t sure if this was due to something deeper that should be fixed


gknauth
2021-7-21 19:40:01

For lists there is map and for-each. For vectors there is vector-map (and vector-map!). Is there a reason there is no for-each equivalent for vectors? I’m operating on a list which has tens of thousands (or more) items, and I take slices of them, so I turned the list into a vector.


soegaard2
2021-7-21 19:42:09

I think the reason is that vector-for-each wasn’t in R5RS - and nobody thought of adding it to Racket. It’s in srfi/43 though.


gknauth
2021-7-21 19:44:24

thx


massung
2021-7-21 20:05:51

obviously there’s also just for :wink:


spdegabrielle
2021-7-21 20:17:11

notjack
2021-7-21 20:18:17

@gknauth there’s sequence-for-each


sschwarzer
2021-7-21 21:23:52

Is there a way (in _un_typed Racket) to check if two values have the same type? Hypothetical example: (define my-list '(1 2 3)) (define my-vector #(1 2 3)) (same-type? my-list my-vector) ; #f (define my-list2 '(1 2 3 4)) (same-type? my-list my-list2) ; #t


soegaard2
2021-7-21 21:25:24

No. But I think, you could get close with (equal? (description value1) (description value2)).


sorawee
2021-7-21 21:25:40

It depends on what you mean by type…

For example, do a list of integers and a list of booleans have the same type? In one sense, yes, they are both lists. In another sense, no.


sschwarzer
2021-7-21 21:26:33

Good point. For the application I have in mind it would be better if the predicate only checked the “outer” type.


massung
2021-7-21 21:28:18

Just to add to the above… what about int vs. float and fixnum vs. bignum?


massung
2021-7-21 21:28:39

are ratio and float the same?



soegaard2
2021-7-21 21:34:26

yes


sschwarzer
2021-7-21 21:34:38

@massung They would be different types for me. But now after thinking a bit more about it, I might get by without the type equality check after all. :smile:


shu--hung
2021-7-21 21:35:06

and also in this case should '(5) and (cons #f #f) be the same? they are both cons cells


soegaard2
2021-7-21 21:35:59

But as the others point out - you may need to roll your own, if your interpretation of “type” is different.


sschwarzer
2021-7-21 21:48:57

That’s interesting. In one sense they’re the same type (cons cells), but in another sense different types (not both are lists). But that’s actually similar to @massung’s point in that, for example, all four types are numbers.

So yes, I’ll make do without the “type equality” check. :slightly_smiling_face:


massung
2021-7-21 21:51:12

As a poor-man’s check, you could probably do something like (untested): (define type-predicates '(number? null? boolean? cons? hash?)) (define (type=? x y) (findf (lambda (pred) (and (pred x) (pred y))) type-predicates))