chansey97
2020-7-3 08:17:42

It’s great! Thanks @notjack


soegaard2
2020-7-3 08:43:24

Good to know,


chansey97
2020-7-3 08:47:30

Why no flip function in the Racket base library? see https://docs.racket-lang.org/reference/procedures.html I don’t find flip function. (flip means flipping two arguments of functions when evaluating)


soegaard2
2020-7-3 08:50:16

It’s rarely needed. In the past I have seen xcons defined as (define (xcons d a) (cons a d)).


notjack
2020-7-3 08:50:59

most of the time when I would have used a flip function, what I really wanted was for the function I’m flipping to have a better order to its arguments in the first place


notjack
2020-7-3 08:51:53

(looking at you, cons)


chansey97
2020-7-3 08:56:57

I don’t think it is rarely need. For example, I am writing a threading functions like this

(define (compose-flip g f) (compose f g)) (define (~>> arg list-of-funcs) ((foldr compose-flip identity list-of-funcs) arg)) ;; Then I can call this: (~>> 0 (list add1 add2 product3 product4)) Note that the function compose-flip is defined by myself.

It would be nice, if base library can provide flip directly.


soegaard2
2020-7-3 08:58:16

If you are programming in the point free style, I see, that you will need it.


chansey97
2020-7-3 09:00:51

@soegaard2 Racket is a multi-paradigm language:wink:


chansey97
2020-7-3 09:23:36

I have another question: The following two examples, which one is better?

1st: (define (~>>-foldl arg list-of-funcs) ((foldl compose identity list-of-funcs) arg)) (~>>-foldl 0 (list add1 add2 product3 product4)) 2nd: (define (compose-flip g f) (compose f g)) (define (~>>-foldr arg list-of-funcs) ((foldr compose-flip identity list-of-funcs) arg)) (~>>-foldr 0 (list add1 add2 product3 product4)) Note that: 1st using foldl and do not need flip 2nd using foldr but need a custom flip

I prefers the 2nd one, because when executing it seem no need to extend the stack. But is there any way to profile this kind of thing in Racket? (to confirm this idea)

For example, To compare factorial and factorial-iter, we can using (trace factorial) (define (factorial n) (if (= n 1) 1 (* n (factorial (- n 1))))) (trace factorial) (factorial 6) output is >(factorial 6) > (factorial 5) > >(factorial 4) > > (factorial 3) > > >(factorial 2) > > > (factorial 1) < < < 1 < < <2 < < 6 < <24 < 120 <720 720 (define (factorial n) (fact-iter 1 1 n)) (define (fact-iter product counter max-count) (if (> counter max-count) product (fact-iter (* counter product) (+ counter 1) max-count))) (trace fact-iter) (fact-iter 1 1 6) >(fact-iter 1 1 6) >(fact-iter 1 2 6) >(fact-iter 2 3 6) >(fact-iter 6 4 6) >(fact-iter 24 5 6) >(fact-iter 120 6 6) >(fact-iter 720 7 6) <720 720 Is this trace (or something like that) can be used to profile ~>> which I defined above? Thanks.



chansey97
2020-7-3 13:17:27

@franci.dainese Thanks, will try it.


badkins
2020-7-3 14:17:07

Interesting perspective. The let variants have always behaved exactly as I expected. Occasionally, define has not behaved as I expected. There was one particularly frustrating example that I can’t recall at the moment, and I remember thinking I should probably make a note of it, but then I realized there was no point since the let family did exactly what I wanted.


maueroats
2020-7-3 18:54:01

If the list of functions is known ahead of time, you can use the <https://docs.racket-lang.org/threading/index.html#%28part..How___works%29|Threading Macros package. > (Maybe already familiar, but I love it.)


chansey97
2020-7-3 19:22:39

@maueroats Yes. threading-macro is great. This function I defined just a toy function. Actually, I think should reverse list when need flip in folding.


chansey97
2020-7-3 19:41:46

Can I define a internal define in a test-suite?

I’m writing a parsing-library, the following is my code structure: #lang racket (provide (all-defined-out)) ;; main code ... ;; test code (module+ main (require rackunit rackunit/text-ui) (define parsing-tests (test-suite "Tests for basic parsing" (define (try-three) (define (g x y z) (list x z)) (g (try-item) (try-item) (try-item))) (check-equal? (parse try-three (string-&gt;list "abcdef")) '(#t (#\a #\c) (#\d #\e #\f))) (check-equal? (parse try-three (string-&gt;list "ab")) '(#f ())) )) (run-tests parsing-tests) ) But compiled error: > define: not allowed in an expression context This because test-suite is a expression, define can not be allowed in an expression. So I have to lift (define (try-three) ... to the top of module main.

But as you see, the try-three is just a util function for tests of “basic parsing”, I want to define it in the testsute. Could someone give me a suggestion? Very thanks.


chansey97
2020-7-3 19:44:59

Or what’s the convention of writing this kind of Racket’s tests?


badkins
2020-7-3 19:45:26

I’ve yet to use test-suite so having nested defines of functions hasn’t been an issue.


badkins
2020-7-3 19:47:29

Here’s an example: (module+ test (require rackunit) (exec-db-test (λ (conn) (define (foo n) (+ n 7)) (check-equal? (foo 3) 10) )) (check-equal? (format-full-name (build-sample-contact 3)) "Fred G. Flintstone") ) Ignore exec-db-test as that’s a custom function of mine.


badkins
2020-7-3 19:48:04

Using module+ test ... is convenient, then tests are automatically run with raco test file.rkt


badkins
2020-7-3 19:49:01

Having said that, when testing, I often lift utility functions when I wouldn’t do the same in regular code.


chansey97
2020-7-3 19:50:58

@badkins Thanks, but I don’t understand your code. What’s the exec-db-test?


badkins
2020-7-3 19:51:29

As I mentioned above, that’s a custom function of mine that takes care of preparing a database connection so the test can make use of it.


badkins
2020-7-3 19:51:49

You could just as easily use (let... or something else for a scope.


chansey97
2020-7-3 19:53:54

@badkins You add all tests in the module test and did not use test-suiteto group tests.


badkins
2020-7-3 19:54:44

Correct, that was my point, test-suite was not playing nice with define for you, so I don’t think you need test-suite


chansey97
2020-7-3 19:56:22

But what I want is to split different test concepts by test-suite (or something like that), not mix all tests in a module. What’s the convention of this sort of thing in Racket? By using submodules?


badkins
2020-7-3 19:56:30

Racket provides a ton of ways to organize your code.


badkins
2020-7-3 19:57:25

So you want to be able to run only a subset of your tests? I’m curious about what you’re trying to accomplish with test-suite


badkins
2020-7-3 19:58:37

My colleagues often joke with me about the fact that I often answer the question “How do I …” with the answer of “with a function” :slightly_smiling_face:


chansey97
2020-7-3 19:58:53

> So you want to be able to run only a subset of your tests? I’m curious about what you’re trying to accomplish with test-suite @badkins, yes. but… of course this is just to make the code look clean (because this is just a toy project). What I really want to know is the convention of Racket.


badkins
2020-7-3 20:00:41

“clean” is in the eye of the beholder, but I personally have slightly different standards for normal code and test code. Having said that, organizing tests to reside w/in functions, or let scopes, or other scopes is clean to me. Your mileage may vary.


chansey97
2020-7-3 20:07:03

I found a solution: Using a let inside test-suite, it works, although it make code drifted rightward a little bit… (module+ test (require rackunit rackunit/text-ui) (define parsing-tests (test-suite "Tests for parsing" (let () (define (try-three) (define (g x y z) (list x z)) (g (try-item) (try-item) (try-item))) (check-equal? (parse try-three (string-&gt;list "abcdef")) '(#t (#\a #\c) (#\d #\e #\f))) (check-equal? (parse try-three (string-&gt;list "ab")) '(#f ())) ) )) (run-tests parsing-tests) ) Thanks:smile:


notjack
2020-7-3 20:10:42

I think the let variants should be avoided not because they behave unexpectedly, but because the behaviors they introduce are not worth keeping track of.


notjack
2020-7-3 20:12:09

Actually I’d call this a bug. The test-suite form should allow internal definitions.


badkins
2020-7-3 20:13:22

I often need to initialize some variables in my let blocks, so I don’t need to create an empty one just for organization. For example: (module+ test (require rackunit rackunit/text-ui) ;; Tests for parsing (let ([ s1 "abcdef" ] [ s2 "ab" ]) (define (try-three) (define (g x y z) (list x z)) (g (try-item) (try-item) (try-item))) (check-equal? (parse try-three (string-&gt;list s1)) '(#t (#\a #\c) (#\d #\e #\f))) (check-equal? (parse try-three (string-&gt;list s2)) '(#f ())) ) ) It doesn’t really make sense here for s1 and s2, but I just did that as an example. I’m still not convinced of the value of test-suite in this case.


notjack
2020-7-3 20:14:58

You could reverse the list of functions instead of reversing the composition function’s argument order


notjack
2020-7-3 20:15:42

Also you may be interested in the threading package.


badkins
2020-7-3 20:16:35

I had the opposite experience with define - wasn’t worth thinking about how they behaved differently than expected i.e. no benefit to me. They’re also more verbose which I find more ugly than a slight indentation drift. I think what we have here is a different set of aesthetics which is to be expected :slightly_smiling_face:


notjack
2020-7-3 20:19:08

how would you feel about var x = expr syntax? as a wild hypothetical


badkins
2020-7-3 20:19:09

If you had said, “I prefer define because …” I doubt I would even have commented, but to say, “Please use define … ” as a prescription doesn’t seem appropriate to me given it’s a preference.


badkins
2020-7-3 20:20:08

regarding var x = expr, in what context/language ? I mean, I prefer (let ([ x expr ]) ... over var


badkins
2020-7-3 20:21:14

I know there is work going on (at least I think it’s still happening) for Rhombus, but I just love Scheme, and one of the things I like about Scheme is let - I find many aspects of it simply beautiful :slightly_smiling_face:


notjack
2020-7-3 20:22:05

I think define is a better default for the majority of racket users, and I find code with lots of nested let forms very frustrating to read. But you’re right, it’s pretty subjective.


badkins
2020-7-3 20:23:25

It is subjective, and I certainly have code where I use define similar to what you’re advocating - sometimes it does seem appropriate to me. One of the frustrating things about Ruby was some idiosyncrasies regarding lexical scope, and I think Scheme nailed it.


badkins
2020-7-3 20:24:24

And I’m aware of the recommendations in the style guide, so I would abide by them when adding/editing core Racket code, vs. my own libraries, as a team player :slightly_smiling_face:


badkins
2020-7-3 20:24:38

Consistency has its own beauty.