abbyrjones72
2019-2-22 08:07:56

This is a fantastic article, and it asked and answered questions I didn’t know how to ask.


jerome.martin.dev
2019-2-22 09:21:26

I’ve been asked the question “What are the practical uses for DSLs?” a lot when doing Racket presentations. Thank you so much for that, Matthew!


jerome.martin.dev
2019-2-22 09:38:34

By the way, the videos of my presentations at FOSDEM 2019 on How to make languages in Racket are available here: https://fosdem.org/2019/schedule/event/jsonwhendsl/ https://fosdem.org/2019/schedule/event/makeownlangracket/


pocmatos
2019-2-22 11:12:33

thanks @samth i will take a more in-depth look at his code then.


daniel
2019-2-22 12:12:32

Thank you, Jérôme!


pierre
2019-2-22 12:52:26

is there a way to support response from (require web-server/http/response-structs) in typed/racket? I tried wrapping the struct in an opaque require/typed using can-be-response? but this fails: can-be-response?: contract violation any-wrap/c: Unable to protect opaque value passed as `Any` value: #<response> This warning will become an error in a future release. in: the 1st argument of a part of the or/c of (or/c struct-predicate-procedure?/c (-> Any boolean?)) contract from: (interface for can-be-response?)


abbyrjones72
2019-2-22 13:31:16

Thank you, Jerome!


samth
2019-2-22 13:32:00

I think you will need to use a more specific predicate. Can you use response?


abbyrjones72
2019-2-22 13:33:47

@jerome.martin.dev I am also exploring minimalism, and living meaningfully


samth
2019-2-22 14:07:19

@mbutterick two thoughts on the presentation: 1. I think the lindemayer example language would fit nicely in this document, especially since it generates cute pictures and comes with a tutorial paper 2. I think an example earlier on would helpful, perhaps even in the first few paragarphs.


abbyrjones72
2019-2-22 14:09:24

Oh neat, I live right next to Indiana University, so if Daniel Friedman is still there, I could theoretically go say hi.


samth
2019-2-22 14:11:00

@abbyrjones72 Dan is indeed still here, and if you’re into Racket there’s lots of us here and you should definitely come say hi


abbyrjones72
2019-2-22 14:11:40

Perhaps I will :slightly_smiling_face:


abbyrjones72
2019-2-22 14:12:27

I’ve thought about applying to the PhD program at the public health school, but I am not motivated lol


samth
2019-2-22 14:12:29

Luddy hall is very fancy, and you’re welcome to drop by my office anytime


abbyrjones72
2019-2-22 14:12:37

ty samth :slightly_smiling_face:


diego
2019-2-22 14:15:21

So, it’s Hoosier time here? I went to Purdue University :slightly_smiling_face:


abbyrjones72
2019-2-22 14:15:28

I went there for a year


abbyrjones72
2019-2-22 14:16:20

At age 38, I felt like I was 20 years late for the prom, but Dr. Cover was my favorite instructor. Philosophy :slightly_smiling_face:


abmclin
2019-2-22 14:17:04

never too late for some good college classes!


abbyrjones72
2019-2-22 14:17:39

lol


abmclin
2019-2-22 14:17:53

I’m 36 and I’ve debated whether I should consider masters or PhD in PL or computational science topics, it would be wonderful but it’s debatable whether it’s a wise course of action these days…


abbyrjones72
2019-2-22 14:17:58

I kept it going, but at other schools.


abbyrjones72
2019-2-22 14:18:40

@abmclin I was 44 when I started my masters and 45 when I finished. Hasn’t produced anything in the way of work, but I feel accomplished


abmclin
2019-2-22 14:19:07

that’s what counts! and congratulations on your masters


abbyrjones72
2019-2-22 14:19:12

why ty!


abbyrjones72
2019-2-22 14:21:03

Question: If anyone is familiar with the SICP Exercise 1.5, we are analyzing this:

(define (p) (p)) (define (test x y) (if (= x 0) 0 y)) (test 0 (p))

But I am not sure what is happening here. Should the first line be (define (p (p)) if we are defining a procedure p that takes procedure p?


abmclin
2019-2-22 14:22:55

It’s been a long time since I’ve looked at SICP. The first line is defining a procedure p. In the body of p, p is being applied, since it’s surrounded by parentheses, so it is basically calling itself


abbyrjones72
2019-2-22 14:23:14

oh


abmclin
2019-2-22 14:23:15

if you tried it out, it would recur forever since it’s calling itself


abbyrjones72
2019-2-22 14:23:22

yes


abbyrjones72
2019-2-22 14:23:27

I saw that lol


abbyrjones72
2019-2-22 14:23:42

would this be an example of recursion without a base case?


abmclin
2019-2-22 14:23:50

it seems that (test 0 (p)) will never return


abmclin
2019-2-22 14:24:13

yes, that would a good example, it doesn’t have any base case so it never terminates


abbyrjones72
2019-2-22 14:24:26

okay, that helps me understand it. tyvm!


jerome.martin.dev
2019-2-22 14:25:32

it’s equivalent to writing (define p (lambda () (p))), which reveals that p is called inside the lambda


abbyrjones72
2019-2-22 14:28:45

okay i will need to think about that


abbyrjones72
2019-2-22 14:28:58

I haven’t studied lambda yet at all


jerome.martin.dev
2019-2-22 14:35:33

It’s the minimal unit in Scheme languages. It’s unique role is to create a new procedure. I won’t spoil SICP, but keep in a corner of your mind that lambda is a bit magical. It’s one of the rare keywords (usually) defined directly in Scheme interpreters (so not written in scheme, but in the base language used to implement Scheme) because it’s the keyword that allows every other part of Scheme to exist. You could basically reduce any program to only lambda calls.


abbyrjones72
2019-2-22 14:36:18

oooh I like magical stuff :slightly_smiling_face:


jerome.martin.dev
2019-2-22 14:37:35

I guess that’s also why Racket, and a lot of other Lisp languages, use lambda as a logo :racket:


abmclin
2019-2-22 14:40:11

the idea of lambda is borrowed from Alonzo Church’s lambda calculus, it can be thought of an abstract description of how a function is made of parameters and a body. The function is used by giving it arguments which are evaluated and bounded to corresponding variables in the body. Scheme allows you to directly work with lambdas so you can build complicated things with just lambdas


abmclin
2019-2-22 14:42:44

The interesting thing is a lambda can be evaluated different ways, which is why you see discussion about applicative and normal evaluation in SICP, though my understanding is those terms are not standard in current programming language literature, they use different names. SICP was written a long time ago so things have moved long way since then


abbyrjones72
2019-2-22 14:44:07

oh…I was devoting an entire blog entry to Applicative/Normal and hesitating…maybe I should just move on and get to the meaty stuff


abbyrjones72
2019-2-22 14:44:27

are there more current explanations I can read?


jerome.martin.dev
2019-2-22 14:44:39

it’s not really an issue nowadays, apart from research fields


abbyrjones72
2019-2-22 14:44:47

okay


abmclin
2019-2-22 14:45:23

I won’t worry too much about it, I’ll look for a decent explanation for you though


abmclin
2019-2-22 14:47:15

@abbyrjones72 this is not bad overview, https://en.wikipedia.org/wiki/Evaluation_strategy


jerome.martin.dev
2019-2-22 14:47:39

But there’s one interesting thing you could talk about when you’ll be finished with SICP and will try macros (it’s not for now!): In Racket, procedures are applied in the classic order (arguments first, procedure after), but macros are applied in reverse (transformation first, arguments after). But it’s a bit complicated for a beginner.


abbyrjones72
2019-2-22 14:47:58

@abmclin I quoted your explanation on my blog if that is okay


abmclin
2019-2-22 14:49:31

it’s fine with me @abbyrjones72


abbyrjones72
2019-2-22 14:49:35

ty


githree
2019-2-22 14:53:19

Re. 1 IMHO lindenmayer as cool as it is has too much of an academic vibe so it really depends on the desired audience of BR


samth
2019-2-22 14:56:04

@githree do you think the language has an academic vibe (drawing trees for biology) or the paper/racket presentation of it has an academic vibe?


githree
2019-2-22 15:03:45

mostly the former - and nothing wrong with that! But reading Matthew’s “why lop…” post I feel it is mostly targeted at the industry (html, riposte, etc.)


benjamin.clos
2019-2-22 15:21:23

So I’ve been working on the classic perfect/abundant/deficient aliquot sum problem a bit and was experimenting with a couple of ways of completing it. (require racket/stream) (require threading) (require memoize) (define (evenly-divisible? num denom) (equal? 0 (remainder num denom))) (define/memo (factors n) (stream-filter (curry evenly-divisible? n) (in-range 1 n))) (define (aliquot-2-all n) (stream-fold + 0 (factors n))) ; this one seems to run significantly faster than ; the two step filter/reduce (define (aliquot-sum-1 n) (stream-fold (curry aliquot-foldl n) 0 (in-range 1 n))) (define (aliquot-foldl max acc n) (cond [(evenly-divisible? max n) (+ acc n)] [else acc])) (provide classify) (define (classify n) (define al-sum (aliquot-sum-1 (abs n))) (cond [(equal? al-sum n) 'perfect] [(< al-sum n) 'deficient] [(> al-sum n) 'abundant]))


benjamin.clos
2019-2-22 15:21:50

I’m wondering why the filter/foldl is so much slower than the flat foldl when I’m using a stream


benjamin.clos
2019-2-22 15:22:15

It’s ~twice as slow to filter/foldl


ben
2019-2-22 15:37:37

if anyone knows about make-screen-bitmap vs. make-bitmap, please take a look at this pull request: https://github.com/racket/plot/pull/51


slmn.sttr.65
2019-2-22 15:48:03

@slmn.sttr.65 has joined the channel


samth
2019-2-22 16:56:53

@ben I think @mflatt is likely to know the most there


ben
2019-2-22 16:57:41

he commented a few minutes ago :)


pocmatos
2019-2-22 17:39:35

Does anyone know if there is anything out there in Racket to do face recognition? If not, is there anything that could be a stepping stone to that?


samth
2019-2-22 17:49:24

I agree about the focus. I was mostly thinking of it as one of many examples but I can certainly see how it might come off the wrong way


githree
2019-2-22 17:49:51

your best bet would be probably with tensorflow binding that apparently few people have started working on recently: https://groups.google.com/forum/#!searchin/racket-users/tensorflow%7Csort:date/racket-users/SM83PPLlEL4/loe1i8FZAwAJ


githree
2019-2-22 17:50:24


krismicinski
2019-2-22 20:29:40

I’ve been making some dirt-simple #langs that walk over modules and add bindings to them manipulating the AST rather than just defining macros to expand. We needed to do this because in one of the languages we’re planning to write, we need to replace identifiers (they have to be changed to applications of a lookup form to respect a security property of the language). Tiny progress here: https://github.com/kmicinski/tinylangs/blob/master/tinylang1.rkt :slightly_smiling_face:


krismicinski
2019-2-22 20:30:18

Any input or more examples is always appreciated, but this taught me a lot. I’ve only ever written macros that expand forms using things like syntax-case, never manipulating the AST directly, so playing around with the expander was really helpful..


krismicinski
2019-2-22 20:38:19

One thing I don’t really “get” is how when you use with-syntax, it introduces a binding that you can then use in quote-syntax. So for example, if you define x using with-syntax, then #'x is valid (where ’ is backtick but making slack-friendly). This is different than if I just did a regular quasiquote, where (quasiquote x) would just be the symbol x. Why isn’t it the case that #'x for quote-syntax is just the identifier x?


samth
2019-2-22 20:40:18

@krismicinski is your question “why did they design syntax-case/syntax that way”, or “how does that work”?


krismicinski
2019-2-22 20:40:48

I guess I’m trying to reconcile the differences between syntax-quote and regular quasiquoting, since I feel like I’m misunderstanding


krismicinski
2019-2-22 20:41:04

so I suppose a bit of both, largely the second.


soegaard2
2019-2-22 20:41:27

Wait - syntax and syntax-quote is different. Do you mean syntax ?


samth
2019-2-22 20:41:38

First, one thing to know is that there’s quote-syntax which does what quote does


samth
2019-2-22 20:41:59

ie, (quote-syntax x) is exactly the identifier x


krismicinski
2019-2-22 20:42:05

right, ok


krismicinski
2019-2-22 20:42:10

So to be precise about it, on this line here: https://github.com/kmicinski/tinylangs/blob/master/tinylang1.rkt#L26


krismicinski
2019-2-22 20:42:32

I am surprised this expands to the syntax for transformed rather than the identifier transformed


samth
2019-2-22 20:43:03

Second, the basic idea is that “pattern variables” bound by syntax-case are used in the “template” created by the syntax form


samth
2019-2-22 20:43:25

this is to support “macro by example”, as you see in syntax-rules as well


samth
2019-2-22 20:43:45

Further, with-syntax is just a trivial wrapper around syntax-case


krismicinski
2019-2-22 20:43:55

ah, ok, that last thing you said makes it make more sense


krismicinski
2019-2-22 20:44:11

So it looks for pattern variables first and then defaults to an identifier if not found?


krismicinski
2019-2-22 20:44:15

something like that?


samth
2019-2-22 20:44:50

but really syntax-case is just a combination of a pattern matcher and binding pattern variables, which are then available in things constructed with syntax


krismicinski
2019-2-22 20:45:17

I see, that does make more sense.


samth
2019-2-22 20:45:31

you could have a pattern matcher that worked more like match, and then have to use quasisyntax to construct the output


samth
2019-2-22 20:45:47

this is what Common Lisp macros look like, somewhat


krismicinski
2019-2-22 20:46:29

I see. I feel like I’ve got not a ton of intuition for this yet, but that helps!


krismicinski
2019-2-22 20:46:39

sounds like I should mostly read more about syntax-case



soegaard2
2019-2-22 22:22:28

We need a beginners guide to lists in Racket.


abbyrjones72
2019-2-22 22:50:39

What do you all do to combat those “why should I bother with this?” moments?


oldsin
2019-2-22 23:46:35

Do you use scribble/srcdoc for in-source documentation? Or do you always use a new file for documentation?


greg
2019-2-23 00:02:08

I always make a <package-name>.scrbl. I only sometimes use scribble/srcdoc in .rkt files, to create doc submods that I include in the main .scrbl using @include-extracted.


notjack
2019-2-23 00:26:53

@abbyrjones72 say “good point” and not bother with it, usually


notjack
2019-2-23 00:28:57

I do that probably more often than I should


plragde
2019-2-23 01:29:22

@abbyrjones72 It might be important to figure out who thinks you should bother and what their reasons are. Sometimes the reasons are hidden. Sometimes there aren’t really good reasons, it’s just inertia.


rokitna
2019-2-23 01:52:17

Is it specifically something you’re trying to learn that seems to be pointless? I think in that situation, I skim it so I can recall the terminology involved, and if someday I realize it would help, I look it up then.


abbyrjones72
2019-2-23 04:46:37

@plragde I completely understand the inertia part of this. I have been pushing every day to work through it, and also work through the difficult concepts. It is worth it, even if I never work as a programmer again. I need to deprogram myself into thinking this is a way into the 20 somethings rat race. I love this language, and LOP, the more I read about it.

Thanks for asking the question, because it made me think.


hoshom
2019-2-23 06:13:05

I’m trying and failing to get this to type-check: #lang typed/racket/base (struct (A) Prefix ([x : A])) (struct (A) Term ([qual : (Prefix A)] [base : (U (Term A) A)])) (: get-base (All (A) (-> (Term A) A))) (define (get-base term) (let ([maybe-base (Term-base term)]) (cond [(Term? maybe-base) (get-base maybe-base)] [else maybe-base]))) Does anyone know how to do this?


notjack
2019-2-23 06:13:45

@hoshom I’m guessing the problem is the (U (Term A) A) part


hoshom
2019-2-23 06:14:09

I think so


hoshom
2019-2-23 06:14:16

the error I get is: Type Checker: Polymorphic function `get-base' could not be applied to arguments: Argument 1: Expected: (Term A) Given: (U (Term A) (∩ #(struct:Term ((Prefix Any) Any)) A)) Result type: A Expected result: A in: (get-base maybe-base)


notjack
2019-2-23 06:14:59

as a general rule, avoid unions between polymorphic types that aren’t disjoint


notjack
2019-2-23 06:15:10

they almost never work the way you want them to


hoshom
2019-2-23 06:16:46

Hmm I thought this would work since it’s kind of similar to what a list looks like.


notjack
2019-2-23 06:17:59

lists use a special singleton null value as the end-of-list marker, but the (U (Term A) A) type is a union between two sets, not between a set and a singleton


notjack
2019-2-23 06:18:58

someone could instantiate A to (Term Foo), with a resulting union type of (U (Term (Term Foo)) (Term Foo)) - and then it’s ambiguous which case it is


hoshom
2019-2-23 06:19:48

Oh! I knew I must be missing something, and yes, you’re right.


hoshom
2019-2-23 06:19:55

So I think I got my workaround: All I have to do is wrap the base in a struct


notjack
2019-2-23 06:20:19

Yup!


hoshom
2019-2-23 06:20:19

So (U (Term A) (Base A) works, my function now returns (Base A)


notjack
2019-2-23 06:20:27

I got a working version of your thing:


hoshom
2019-2-23 06:20:27

thanks!


notjack
2019-2-23 06:20:33
#lang typed/racket/base

(struct (A) Prefix ([x : A]))

(struct (A) Primitive-Term
  ([value : A]))

(struct (A) Compound-Term
  ([qual : (Prefix A)]
   [base : (Term A)]))

(define-type (Term A)
  (U (Primitive-Term A) (Compound-Term A)))

(: get-base (All (A) (-> (Term A) A)))
(define (get-base term)
  (cond [(Primitive-Term? term)
         (Primitive-Term-value term)]
        [(Compound-Term? term)
         (get-base (Compound-Term-base term))]))

notjack
2019-2-23 06:21:35

as a rule of thumb: be suspicious of (U ... type-variable ...)


hoshom
2019-2-23 06:21:41

haha


hoshom
2019-2-23 06:22:01

my version right now’s a bit simpler so I’m going with it: #lang typed/racket/base (struct (A) Prefix ([x : A])) (struct (A) Term ([qual : (Prefix A)] [base : (U (Term A) (Base A))])) (struct (A) Base ([val : A])) (: get-base (All (A) (-> (Term A) (Base A)))) (define (get-base term) (let ([maybe-base (Term-base term)]) (cond [(Term? maybe-base) (get-base maybe-base)] [else maybe-base])))


notjack
2019-2-23 06:22:23

oh yup that’s a better way


hoshom
2019-2-23 06:36:41

By the way the reason this happened was because I meant A to actually be “one of several subtypes of a struct”, but if I just use the parent struct in the type, I don’t get to say “function X works with a term of only a subtype of the struct”. So I just put type variables everywhere :smile:


hoshom
2019-2-23 06:37:22

rather, “a parent struct or any subtype”


notjack
2019-2-23 06:40:51

oh that makes sense :p