badkins
2020-12-29 13:35:45

I don’t think this is true. Maybe let or letrec ?


kellysmith12.21
2020-12-29 13:42:21

I was basing what I said on how define gets expanded in an internal definitions context. It appears to expand to nested lets, though it also expands to letrec if the defines bind functions that refer to one another.


badkins
2020-12-29 18:22:13

Another example of define surprising me. The following does not work: (define (foo bar) (define bar (string-upcase bar)) bar) but this does work: (define (foo bar) (let ([bar (string-upcase bar)]) bar)) This is not contrived. I have a very complicated function, that I’m not quite ready to refactor. I need to upcase an argument, so I thought I could save some trouble by simply using (define foo (string-upcase foo)) at the top of the function, but it failed.


badkins
2020-12-29 18:24:58

Again, the let family have simply always worked as I expected, so I’m fine with a bit of rightward drift.


sorawee
2020-12-29 18:25:51

Wouldn’t it be nice if there’s no rightward drift, and the code works…


soegaard2
2020-12-29 18:26:48

In (define x e) the scope of x includes e. This is handy for defining recursive functions. It’s not so handy, when you have a let* type of scenario. You sort of need an define*.



badkins
2020-12-29 18:29:47

Yes, but aesthetically, I think I still prefer: (let ([abc "def"] [def 7.8] [ghi 31416] [jkl mno]) (use-these-variables ...)) more than: (define abc "def") (define def 7.8) (define ghi 31416) (define jkl mno) (use-these-variables ...)


sorawee
2020-12-29 18:31:33

Interesting. What are your reasons?


badkins
2020-12-29 18:32:19

The former is prettier.


badkins
2020-12-29 18:32:58

Notice the boiler plate of having the same word “define” specified over and over again. It’s the antithesis of Scheme for me.


badkins
2020-12-29 18:33:27

I like internal define for defining functions, but not variables.


sorawee
2020-12-29 18:33:44

I’m not gonna argue with that then :slightly_smiling_face:

But in Rhombus, it probably could look like:

let abc := "def" let def := 7.8 ... or even:

abc := "def" def := 7.8 ...


sorawee
2020-12-29 18:33:52

would that help?


sorawee
2020-12-29 18:34:42

If I were to design one on S-exp now, I would make it look like:

{let abc := "def"} ...


badkins
2020-12-29 18:34:44

I will continue to use #lang racket if/when Rhombus is completed. I chose Racket, in part, due to the Scheme syntax.


ben.knoble
2020-12-29 18:41:50

let is closer to ML for me, so I prefer it for that reason alone :slightly_smiling_face:


ben.knoble
2020-12-29 18:43:22

Is this not working b/c the define is like let rec in ML? i.e., you can create self-referential definitions, instead of using the old value?


ben.knoble
2020-12-29 18:43:55

plragde
2020-12-29 22:38:09

Hi, Hazel, sorry I didn’t check this Slack yesterday. Glad to hear that you are working through LACI and enjoying it. I’m happy to take questions here or directly by email. Since you figured out the universe hierarchy, you probably also figured out that in the two-sort system, you have to make sure that for the Arrow case, the recursive synths have to produce a sort. But that’s about it.


ben.knoble
2020-12-29 22:42:06

Working through <git://github.com/zyrolasting/racket-koans.git>, having trouble with a contract exercise: ;; Read this carefully: Write a procedure `my-join` that joins at least ;; one integer together into a single string with an optional delimiter ;; character that defaults to a single blank space as the first argument. ;; Have a contract enforce these precise restrictions. Hint: You will ;; need 'case-&gt;' (define/contract my-join (case-&gt; (-&gt; char? integer? #:rest (listof integer?) string?) (-&gt; integer? #:rest (listof integer?) string?)) (let ([join (λ (c i is) (string-join (map number-&gt;string (cons i is)) (string c)))]) (case-lambda [(c i . is) (join c i is)] [(i . is) (join #\space i is)]))) (let ([arity (procedure-arity my-join)]) (if (and (arity-at-least? arity) (eqv? (arity-at-least-value arity) 1)) (begin (check-equal? (my-join #\- 1 2 3) "1-2-3") (check-equal? (my-join #\space 1 2 3) "1 2 3") (check-equal? (my-join 1 2 3) "1 2 3") (check-equal? (my-join #\space 1) "1") (check-equal? (my-join 1) "1") (check-exn (λ () (my-join #\?))) (check-exn (λ () (my-join ","))) (check-exn (λ () (my-join #\space "a" "b"))) (check-exn (λ () (my-join "," 0.1 9)))) (fail "Double check your signature of my-join"))) I get this error it seems because I cannot distinguish the case char int int* from int int* with just case-&gt;/case-lambda? my-join: contract violation expected: char? given: 1 in: the domain of the 1st case of (case-&gt; (-&gt; char? integer? #:rest (listof integer?) string?) (-&gt; integer? #:rest (listof integer?) string?)) contract from: (definition my-join)


plragde
2020-12-29 22:42:34

I will be doing some small rewrites to LACI in the next few weeks based on what I learned from my course offering this fall, and then I will add a new chapter on how to add holes to the predicate version of Proust (I’ve gotten as far as using unification to refine holes, the equivalent of the “apply” tactic in Coq or C-c C-r in Agda), with more discussion of things like implicits, placeholders, pattern matching, and user-defined datatypes.


anything
2020-12-30 00:51:30

How do you check whether you have a boolean true?


anything
2020-12-30 00:51:45

I guess anything is true except #f.


anything
2020-12-30 00:53:09

That’s what racket/bool seems to tell me: https://docs.racket-lang.org/reference/booleans.html


plragde
2020-12-30 01:00:06

Only #t is a Boolean true. But everything else except #f is “truthy”. Opinions are divided on this.


notjack
2020-12-30 02:46:14

@badkins I hit this kind of thing often too. The three idioms I see for this are: - using let - using different names, like bar and bar* - using set!


badkins
2020-12-30 03:11:04

let solved the problem perfectly. Upon further analysis, it wasn’t that big of a deal. The function was inexcusably long, but most of it was internally defined helper functions, so the actual amount of code that needed to be w/in the let wasn’t that much. I thought some of the helpers may have closed over the argument, but none of them did.


cdep.illabout_slack
2020-12-30 04:42:59

One could argue that this is sort of a problem with shadowing variables, as opposed to define vs. let.


cdep.illabout_slack
2020-12-30 04:44:12

Other languages will provide warnings when you’ve shadowed a variable, because it can be confusing to read code where the same identifier is used for different variables.


rokitna
2020-12-30 06:38:05

That’s an odd exercise. Looks to me like you have to decompose the argument list in an unusual way. The way I’m thinking about it, one of the cases would use (or/c char? integer?).