ryanc
2021-7-20 07:22:16

The round-trip property already fails to hold, because there are multiple kinds of hashes, and they are not equal. (equal? (string->jsexpr (jsexpr->string (hash 'a 1))) (hash 'a 1)) Allowing strings would make the equal? situation worse, though, and it would introduce new kinds of questionable/bad jsexprs, like (hash "a" 1 'a 2) and (hasheq "a" 1 (string #\a) 2).


chansey97
2021-7-20 09:03:19

Is there any Z3 bindings for Racket? I found some packages on the Internet, but I don’t know which one should I use.



chansey97
2021-7-20 09:40:28

Thanks @spdegabrielle. But can rosette/solver/smt/z3 be used as a general z3 API interface (e.g. z3py)? Or it is just be used for rosette by itself? For example, (List Int) in Z3 is a solvable type, but not in rosette. (solvable? list?) ; => #f, I even don't know how to define a recur solvable type in rosette. BTW, the docs doesn’t tell me how to use rosette/solver/smt/z3 as a SMT solver directly.


Add some background information:

I am comparing traditional Logic Programming (e.g minikanren/Prolog) vs Satisfiability Modulo Theories (e.g. z3). Although using different theoretical frameworks, they are very similar (Consider CLP(X) vs DPLL(T)).

For one direction, we seemly can use an SMT solver as minikan’s backend for constraint logic programing. In fact, someone has already done this work, see https://github.com/namin/clpsmt-miniKanren

For another direction, I think an excellent SMT solver can do constraint logical programming efficiently (to some extent). But there are very few materials about this on the internet. So I have to tried it by myself.

My first attempt is executing a program backwards. For example, implements minikanren’s appendo relation in z3. In fact, I have succeeded in smt2 language. The problem is that smt2 cannot get all the satisfying models automatically. We must use some API binding. This is why I want a z3 API binding in Racket.

PS. I have tried z3py, but failed. The z3py’s docs is very brief and difficult to read, especially about “how to define a recursive function”. Frankly, I posted a https://stackoverflow.com/questions/68450731/converting-appendo-relation-from-smt2-to-python\|question in StackOverflow, but no one has answered so far.

Notice that smt2 is a s-expr language. So I think its API binding should be compatible well with Racket. Or more easily, we can construct smt2 commands in Racket and send them to z3 process. But I hope some framework code (or lib) can do this out of box.


xlambein
2021-7-20 12:28:06

Does anyone know of other languages that use Racket’s separate phases of execution model?



soegaard2
2021-7-20 12:31:32

Maybe Sweet.js? I not 100% sure though - maybe they only have phase 0 and 1.


soegaard2
2021-7-20 12:35:27

According to this blog post, there are infinite many phases. https://medium.com/@disnet/sweetening-syntactic-abstractions-e615ab87f2dd


soegaard2
2021-7-20 12:35:52

And Tim Disney writes they are using the Racket approach.


xlambein
2021-7-20 12:39:45

Looks interesting, thanks!


samth
2021-7-20 13:09:03

I think rust’s approach effectively implements phases too


xlambein
2021-7-20 13:12:23

That’s interesting, I’d never thought of it that way, but yeah I guess it does?


xlambein
2021-7-20 13:14:06

A Rust procedural macro is compiled into a library, which is then used by the compiler to expend code that uses that macro :thinking_face:


spdegabrielle
2021-7-20 13:17:40

Maybe you could look at how rosette does it and create your own standalone z3 library for racket?


laurent.orseau
2021-7-20 13:18:54

{scribble again, sorry} The online docs still give red-underlined tags despite having for-labelled the relevant libraries (as can be seen https://github.com/Metaxal/text-block/blob/main/scribblings/combiners.scrbl#L3\|here), and raco setup --check-pkg-deps reporting no issue. Strangely, the issue doesn’t appear when generating the docs on my laptop.


soegaard2
2021-7-20 13:21:15

I think, you need to add racket/base too.


laurent.orseau
2021-7-20 13:23:01

That would be strange, since these symbols are exported by the libs listed above


laurent.orseau
2021-7-20 13:23:04

I’ll try though


samth
2021-7-20 13:25:50

exact-nonnegative-integer? is in racket/base


laurent.orseau
2021-7-20 13:27:59

Huh, right indeed…


chansey97
2021-7-20 13:29:34

@spdegabrielle Yes, that is what I originally wanted to do, but rosette’s source code is a bit hard to read (lacking z3 wrapper’s unit test). I just found clpsmt-miniKanren has z3-driver.rkt and z3-tests.rkt, which seems what I want. I’m reading her code :wink:.


laurent.orseau
2021-7-20 13:31:07

When I scribble-run the page alone on my laptop, these tags are always in red though, even with for-label racket/base . And if I raco setup then raco docs all links are good. That makes it a little complicated to debug. Is there a simple way to do it to see how it would render on http://docs.racket-lang.org\|docs.racket-lang.org?


soegaard2
2021-7-20 13:32:07

I use this to invoke scribble. raco scribble +m --htmls --dest htmls --redirect-main <http://docs.racket-lang.org> manual-sketching.scrbl &amp;&amp; open htmls/manual-sketching/index.html


soegaard2
2021-7-20 13:33:52

I think, that handles the red tags at least. I did see a difference between raco setup and raco scribble when racket/gui was instantiated (but that seems to be a "don’t do that-situation).


laurent.orseau
2021-7-20 13:38:15

Thanks a bunch @soegaard2


laurent.orseau
2021-7-20 13:38:48

I still had to run raco setup to remove the red links though


shu--hung
2021-7-20 13:39:04

I usually just start the z3 process and send s-expressions


shu--hung
2021-7-20 13:42:11

soegaard2
2021-7-20 13:46:25

I think, I picked it up here on Slack.


chansey97
2021-7-20 13:46:52

Thanks. @shu—hung Can it run in windows? It tells me ; error writing to stream port Sorry I am not familiar with system programming in Racket.


shu--hung
2021-7-20 13:47:49

Yes it can. You need to provide the full, absolute path to z3.exe in https://gist.github.com/shhyou/ce02ba69a2ecc7f89a7f704eb8e1f8b2#file-solver-rkt-L9


shu--hung
2021-7-20 13:48:50

SMTLIB is an S-expression language so I do think directly launching the process and interact with it is the most straightforward way


shu--hung
2021-7-20 13:49:07

using the API binding, however, is going through FFI and C etc


chansey97
2021-7-20 13:53:00

@shu—hung I run the module test, it gives a error: > solve: cannot parse model ((define-fun x () Int 10)) > input: ((declare-const x Int) (assert (= (* x 2) (+ x 10))))


soegaard2
2021-7-20 13:57:26

What is the convention with respect to syntax-track-origin? (when should it be used)


shu--hung
2021-7-20 13:57:41

Hmm, I’m using Z3 4.8.7. What version of z3 are you using?


chansey97
2021-7-20 13:57:56

z3–4.8.12


shu--hung
2021-7-20 13:59:50

Do you know if Z3’s syntax changed since then? Looks like the code is expecting the output (model (define-fun x () Int 1) ) from the solver but there’s no model around the output.


chansey97
2021-7-20 14:00:36

@shu—hung I switched to z3-4.4.1 , it works. Thanks!


shu--hung
2021-7-20 14:03:18

Okay. Basically, this is what solve is doing: 1. send the given S-expressions to Z3 2. send (check-sat) (L45) 3. get an S-expression from the solver. if the output is sat, (L47-L50) 4. send (get-model) to the solver (L51) 5. get an S-expression from the solver. expect the output to have the form `(model (define-fun ,vars () ,typs ,vals) ...)


chansey97
2021-7-20 14:03:21

@shu—hung Yes. The syntax has changed. In z3–4.4.1, there is a model at the top of the s-exp. In z3–4.8.12, no model at the top.


shu--hung
2021-7-20 14:03:33

Okay! So that’s the problem


shu--hung
2021-7-20 14:04:39

Moreover, the code isn’t doing much in parsing the output from the solver. For example, it does not handle ite, functions (and hence no arrays), etc


shu--hung
2021-7-20 14:05:18

One most visible part is probably the missing handling for let


chansey97
2021-7-20 14:06:30

@shu—hung What do you mean by “missing handling for let”? Sorry I am new to z3.


shu--hung
2021-7-20 14:13:51

The output of Z3 can contain let expressions. I forgot the concrete syntax in SMTLIB2, but it’s documented in the SMTLIB2 language


shu--hung
2021-7-20 14:14:13

So you might want to handle it


chansey97
2021-7-20 14:16:45

> Moreover, the code isn’t doing much in parsing the output from the solver. For example, it does not handle ite, functions (and hence no arrays), etc > One most visible part is probably the missing handling for let That’s not a big problem:grinning:. I can fine-tune the code by myself or comparing with z3-driver.rkt in clpsmt-miniKanren (which use a similar approach). Thanks.


shu--hung
2021-7-20 14:18:38

I found the relevant decoding code in Rosette EDIT: https://github.com/emina/rosette/blob/master/rosette/solver/smt/dec.rkt#L135


capfredf
2021-7-20 14:20:48

Out of curiosity. Is there a way to force DrRacket to do a GC? I currently have a DrRacket instance running for a while. I closed all the tabs at the some point, but DrRacket is using 1.6G


chansey97
2021-7-20 14:22:04

Thanks.


samth
2021-7-20 14:22:19

You can call (collect-garbage) or click the recycle icon


chansey97
2021-7-20 14:23:42

BTW, the FFI approach is very difficult to use (e.g. z3py’s docs is too brief:thinking_face:).


chansey97
2021-7-20 15:24:35

Thanks @camoy. I will try it.


massung
2021-7-20 15:25:06

Is it possible to monkey patch a struct (e.g. add a gen:stream or gen:custom-write to it post-hoc)?


chansey97
2021-7-20 15:29:44

But since it does not support parameterized sort, it may not be able to implement List Int type (see background information in the thread below).


samth
2021-7-20 15:34:16

no, that’s not possible


samth
2021-7-20 15:34:39

I would probably create a wrapper struct with the property


ben.knoble
2021-7-20 15:39:30

I remember reading something about being able to forward parts of the struct, but I could be making that up? i.e., the wrapper should be able to automatically create wrapper field-accessors &c.?


ben.knoble
2021-7-20 15:40:11

Maybe that was some kind of struct inheritance/extension I saw, idk anymore


massung
2021-7-20 15:40:37

yeah, that sounds familiar. a wrapper is fine, just wondered if there was a method of doing it


samth
2021-7-20 15:40:45

you could use struct inheritance as well, the substruct could implement the properties


bsaiki
2021-7-20 15:51:08

I’m using racket/engine , and I’m having issues with the main thread being blocked after exiting on a timeout. I know there are issues with mutable hash tables using equal? and eq? comparisons. Are there any other data structures with this issue? For instance, the main thread will be blocked if I try to print the value of a box used in the engine, but that seems wrong. Additionally, if I create another thread (not in engine) that simply prints the stack trace of the main thread every so often, the main thread will start executing again. Unfortunately, I have no small example for this, so I’m describing this issue in broad strokes. Any help is appreciated.


bsaiki
2021-7-20 15:51:22

To recreate this issue: Checkout: https://github.com/bksaiki/herbie/tree/thread-safe Run: make install (requires cargo) racket src/herbie.rkt report --threads 1 --timeout 5 bench/hamming graphs


massung
2021-7-20 15:57:19

Is there a nice, built-in (list? stream?) -&gt; (stream? list?) function?


soegaard2
2021-7-20 15:58:16

Doing what?


massung
2021-7-20 15:58:37

I have a list of streams and want to convert it into a single stream that returns a list of values each iteration


massung
2021-7-20 15:59:21

I can write something, but if a function already existed (that I’m not seeing), I’d rather use that :wink:


soegaard2
2021-7-20 15:59:51

Not sure, haven’t used streams in a while.


samth
2021-7-20 16:00:42

sadly stream-map doesn’t take multiple streams


sorawee
2021-7-20 16:36:09

I don’t think there’s a built-in function, but we can write one: https://stackoverflow.com/questions/59232050/varadic-zip-in-racket/59232230#59232230


badkins
2021-7-20 16:37:25

Is it possible that the error message for a contract violation does not correctly describe the actual contract? I received the following error: licensing-search: contract violation expected: string? given: #f in: an element of the 6th argument of (-&gt;* (connection? string? Date? (listof hash?) (listof string?) string?) (#:case-key-set set-mutable? #:fuzzy-address-search? boolean? #:limit exact-positive-integer?) any) contract from: (function licensing-search) blaming: /home/deploy/crcracket/ncaoc/acis/licensing-search.rkt (assuming the contract is correct) but the code is: (define/contract (licensing-search conn api-username reference dob names driver-licenses last4ssn #:limit [ limit 100 ] #:fuzzy-address-search? [ fuzzy-address-search? #f ] #:case-key-set [ case-key-set (mutable-set) ]) (-&gt;* (connection? string? string? date? (listof hash?) (listof string?) string?) (#:limit exact-positive-integer? #:fuzzy-address-search? boolean? #:case-key-set set-mutable?) any) The error message is missing the 3rd argument i.e. the second string?, so this makes me wonder if the “6th argument” part of the error is accurate.


badkins
2021-7-20 16:40:30

The fact that it says “in an element of” seems to imply a list, so it does seem to be the actual 6th argument vs. the 6th argument in the error message.


massung
2021-7-20 16:44:48

Ah, this is nicer than what I cobbled together. Thanks!


samth
2021-7-20 16:45:25

That seems like it would be a bug, but I just tried to replicate it with this code and I got “7th”: #lang racket (require racket/date) (define (connection? x) #t) (define/contract (licensing-search conn api-username reference dob names driver-licenses last4ssn #:limit [ limit 100 ] #:fuzzy-address-search? [ fuzzy-address-search? #f ] #:case-key-set [ case-key-set (mutable-set) ]) (-&gt;* (connection? string? string? date? (listof hash?) (listof string?) string?) (#:limit exact-positive-integer? #:fuzzy-address-search? boolean? #:case-key-set set-mutable?) any) (void)) (licensing-search #f "x" "x" (current-date) null null 'x)


badkins
2021-7-20 16:46:12

Strange. The code hasn’t changed since Oct 2020, so it’s unlikely to be an out of date compilation.


sorawee
2021-7-20 16:47:12

I saw it’s used when you want to forge a new identifier based on an existing identifier.

In fancy-app, it turns (+ _ 1 _ 2) to (lambda (x1 x2) (+ x1 1 x2 2)).

In the above example, you want to create two new identifiers “x1” and “x2", but you also want x1 to inherit whatever the first _ has, and x2 to inherit whatever the second _ has.

https://github.com/samth/fancy-app/blob/master/main.rkt#L18


badkins
2021-7-20 16:50:39

I took your example, slightly modified, and I got the correct error message: licensing-search: contract violation expected: string? given: #f in: an element of the 6th argument of (-&gt;* (connection? string? string? date? (listof hash?) (listof string?) string?) (#:case-key-set set-mutable? #:fuzzy-address-search? boolean? #:limit exact-positive-integer?) any) I’ve viewing the error via journalctl on Ubuntu Linux, so I’m wondering if the line containing the 3rd argument just didn’t get logged properly? Regardless, I think I can count on it being the 6th arg which is all I need. Thanks @samth


badkins
2021-7-20 16:51:23

I used: #lang racket (require racket/date) (define (connection? x) #t) (define/contract (licensing-search conn api-username reference dob names driver-licenses last4ssn #:limit [ limit 100 ] #:fuzzy-address-search? [ fuzzy-address-search? #f ] #:case-key-set [ case-key-set (mutable-set) ]) (-&gt;* (connection? string? string? date? (listof hash?) (listof string?) string?) (#:limit exact-positive-integer? #:fuzzy-address-search? boolean? #:case-key-set set-mutable?) any) (void)) (licensing-search #f "x" "x" (current-date) '() '(#f) "1234")


badkins
2021-7-20 16:52:53

This is on Racket v7.3 for what it’s worth.


samth
2021-7-20 16:54:00

I get the same (correct) error message for both 7.3 and HEAD



badkins
2021-7-20 16:59:06

Maybe not - I ran the full journalctl output and I don’t see any suppressed messages for today even though there are some suppressed messages last month.


soegaard2
2021-7-20 17:26:07

Thanks for the example!


greg
2021-7-20 17:56:32

@badkins I notice it’s Date? in your first error message but date? in the define/contract. I don’t know the significance but wonder if that discrepancy might be a clue? Maybe the error message comes from another contract for another function, somehow??


greg
2021-7-20 17:58:24

One wild guess: That package added an optional argument, and your server is running an older version than the newer one you and Sam are looking at locally??


greg
2021-7-20 17:59:36

(By “that package” I guess I mean /home/deploy/crcracket/ncaoc/acis/licensing-search.rkt; I don’t know if it’s a package.)


sschwarzer
2021-7-20 18:39:14

Nim ( https://nim-lang.org ) has at least macros at compile time in addition to runtime execution. You can execute most of the code at compile time you could execute at runtime.


badkins
2021-7-20 20:29:06

Thanks Greg. I just had another error, and the contract error has the same issue of the missing string?. That would be far too coincidental to be a logging issue with a missing log line. I’ve grep’d the code for licensing-search, and I only see one definition in my entire source tree, and that definition hasn’t changed since Oct 2020. But your catch of Date? vs. date? is an interesting one!! I’ll have to keep digging…


badkins
2021-7-20 20:49:48

@samth crazy question, but I’ve grep’d my codebase and found zero occurrences of Date? - can you think of a possible explanation for the contract error to capitalize date? to Date? - I know it’s nuts, but I had to ask :)


samth
2021-7-20 20:50:16

That’s very weird


badkins
2021-7-20 20:50:19

It’s blaming the right function at the right line of the right file, so this is so odd.


badkins
2021-7-20 21:03:47

I’m able to reproduce the issue with 'Date? by (require gregor) , instead of (require racket/date) - but I expect that’s a red herring.


badkins
2021-7-20 21:04:23

Although I’m mildly curious why that happens :)


badkins
2021-7-20 21:35:06

@jaz do you happen to know why a Racket contract error would capitalize a gregor date? to ’Date? ? I doubt it’s related to my current problem, but any additional understanding of what’s going on with the contract system could be useful.


shu--hung
2021-7-20 22:15:03

Does removing the compiled/ directories and performing full-system recompilation (raco setup ) help? do you have the old code before Oct 2020?


bsaiki
2021-7-20 22:50:27

Currently being handled… All good


jaz
2021-7-21 00:31:37

jaz
2021-7-21 00:32:10

And, in fact, I did find a way around this in datetime.


alexharsanyi
2021-7-21 01:20:31

Is it possible to update the sqlite DLLs shipped with Racket? The version that ships wit Racket is 3.22.0, which is 3 years old. In particular this version contains a bug where a COMMIT might report success even though it failed (this bug was introduced in 3.17.0 and fixed in 3.32.2).

This is the bug that was fixed: https://www.sqlite.org/src/info/810dc8038872e212 And this is the release log for SQLite: https://sqlite.org/changes.html


samth
2021-7-21 01:31:11

I think someone had a package that packaged updated SQLite binaries, but I forget who it was


alexharsanyi
2021-7-21 01:41:26

I think it is @popa.bogdanp: https://github.com/Bogdanp/racket-libsqlite3, however, is there a reason why this needs to be a separate package while Racked ships with a very old version?


samth
2021-7-21 01:42:45

I agree that this should be fixed; just mentioning an alternative solution at the moment


alexharsanyi
2021-7-21 01:52:23

If I understand the process correctly, it would be just a matter of taking the prebuilt binaries from that package and adding them to https://github.com/racket/libs

If this is all that it is involved, and @popa.bogdanp is OK with using the binaries he built, I would be happy to do this and submit a pull request for this.


samth
2021-7-21 01:55:00

I think there’s code somewhere for the build process but I can’t find it now, so a PR seems fine


notjack
2021-7-21 03:34:03

the (hash "a" 1 'a 2) case is particularly bad


notjack
2021-7-21 03:34:23

since at least with the other kinds of round-tripping, it’s fairly easy to guess what the result will be


notjack
2021-7-21 03:35:45

round-tripping (hash "a" 1 'a 2) could validly produce any of the following four results: • (hash "a" 1)(hash 'a 2)(hash "a" 2)(hash 'a 1) …and I don’t really see any “logical” best choice


notjack
2021-7-21 03:36:31

in the case of key collisions, throwing an exception would be the best choice IMO


sorawee
2021-7-21 03:38:20

One possibility is to define jsexpr? as:

jsexpr? = ... \| (hash/c symbol? jsexpr?) \| (hash/c string? jsexpr?)


sorawee
2021-7-21 03:38:55

Then you can’t mix symbol? and string? within one hash, but can mix them across hashes


sorawee
2021-7-21 03:39:38

It still won’t fix the equal? issue, but at least the (hash "a" 1 'a 2) problem won’t occur


notjack
2021-7-21 03:40:36

You can use transposing in Rebellion to do that


sorawee
2021-7-21 03:40:47

Rhombus should “fix” this issue though


notjack
2021-7-21 03:41:32

(in-transduced streams (transposing #:into into-list)) will give you a lazy (sequence/c list?)


notjack
2021-7-21 03:41:45

It’s not quite a (stream/c list?) though


notjack
2021-7-21 03:43:34

Oh wait, transposing requires that all of the sequences have the same length. Does that matter for your case?


notjack
2021-7-21 03:45:39

if we’re talking about how to deal with this problem in Rhombus, I’m half-tempted to suggest just getting rid of symbols and mutable strings


popa.bogdanp
2021-7-21 04:05:49

> If this is all that it is involved, and @popa.bogdanp is OK with using the binaries he built, I would be happy to do this and submit a pull request for this. Feel free! @alexharsanyi


popa.bogdanp
2021-7-21 04:31:12

Heads-up, though, that my version of the Windows libs are built on Windows Server 2016 so it’s possible (likely?) that they won’t work on Windows versions older than Windows 10 so that might be a problem with just copying them into racket-libs. I don’t know what the minimum supported Windows version is, but I assume it’s older than Windows 10.


alexharsanyi
2021-7-21 06:08:24

I checked both the x86 and x64 sqlite DLLs for windows and they only link against kernel32.dll, so I think they would work fine on older windows versions, except perhaps Windows XP. However, I have no way of testing this…


xlambein
2021-7-21 06:34:24

Looks interesting too, thanks a lot!


sschwarzer
2021-7-21 06:39:41

Is there something in the standard library or a third-party package which is like https://docs.racket-lang.org/reference/pairs.html?q=cartesian#%28def._%28%28lib._racket%2Flist..rkt%29._cartesian-product%29%29\|cartesian-product , but yields the inner lists (or maybe vectors for faster random access) lazily? Outside the standard library, I found https://docs.racket-lang.org/for-helpers/index.html?q=in-nested#%28form._%28%28lib._for-helpers%2Fextra..rkt%29._in-nested%29%29\|in-nested , but from the syntax it seems to assume that the number of sequences is known at compile time.


sschwarzer
2021-7-21 06:42:03

I like the language a lot, but all in all I seem to have even more fun with Racket. :smile:


xlambein
2021-7-21 06:44:22

Fair enough :D seems to be a lot of people’s experience, that they always go back to their Lisp of choice. I’m still a newbie in this space, but maybe that’ll be me in the future haha


notjack
2021-7-21 06:47:44

good question, an in-cartesian-product function would be a good thing to add to racket/sequence


sschwarzer
2021-7-21 06:49:32

I learned and used Nim before Racket, but after getting used a bit to the latter I’m now enjoying it more than Nim. But I still like programming in Nim when Racket isn’t a good fit.

Note that Nim is an imperative language. There are some FP-like features (say, higher-order functions and anonymous functions), but the data structures usually used, say, in the standard library, are all mutable.


sorawee
2021-7-21 06:51:46

Here’s one possible implementation

(require racket/generator) (define (product . xss) (in-generator (let loop ([xss xss] [acc '()]) (cond [(null? xss) (yield (reverse acc))] [else (for ([x (in-list (first xss))]) (loop (rest xss) (cons x acc)))]))))


sschwarzer
2021-7-21 06:51:58

I saw there’s https://docs.racket-lang.org/reference/sequences.html?q=in-parallel#%28def._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._in-parallel%29%29\|in-parallel which would suggest in-nested for the new function, although it would conflict with the for-helpers package. :wink:


sorawee
2021-7-21 06:57:09

This version is a bit more efficient, but the ordering is not consistent with cartesian-product. It still enumerates correctly though, just with different ordering


sorawee
2021-7-21 06:57:12

(define (product . xss) (in-generator (let loop ([xss (reverse xss)] [acc '()]) (cond [(null? xss) (yield acc)] [else (for ([x (in-list (first xss))]) (loop (rest xss) (cons x acc)))]))))


sschwarzer
2021-7-21 06:59:21

That was quick! :slightly_smiling_face: I want this in the standard library, both. :smile:


sschwarzer
2021-7-21 06:59:52

For the first version I checked that you can use it with sequences in general if you remove the in-list call.