sergej
2017-7-11 09:55:28

the biggest problem I’m having with Racket so far is matching and fixing the damn parentheses…


nadeem
2017-7-11 10:59:47

There’s an ‘automatic parentheses’ mode in DrRacket that might help: preferences -> Editing tab -> General Editing subtab -> ‘Enable automatic parentheses’ . This will automatically add a balanced closing parens every time you type a new open one. You can also select a chunk of text in the editor and press an open parens and it will automatically surround the selection with the matching closing parens. Unfortunately it doesn’t help with deleting or removing extraneous parens if you end up with too many.


zenspider
2017-7-11 14:08:51

@sergej I’m happy to help hook you up with emacs and paredit. You can’t have unbalanced parens that way.


sergej
2017-7-11 14:10:14

Thanks, I’ve actually found parinfer earlier, just didn’t want to switch to Emacs yet


chris-lowen
2017-7-11 14:11:41

@zenspider and anyone else who was interested in coffee - Two Creek Coffee House is open 8–3:30 and is really close to class


zenspider
2017-7-11 14:12:18

@chris-lowen you are a gentleman and a saint


zerusski
2017-7-11 14:17:11

there’s a girl here who delivered food. Guess she’s waiting on @mflatt to sign off


twisol
2017-7-11 15:52:30

So Redex pattern-matching behaves like the Barendregt convention is maintained?


twisol
2017-7-11 15:57:32

I love that phrasing. "[Makes sense] is not the same as [right]", but it can be more useful sometimes! :+1:


twisol
2017-7-11 16:24:29

Would this be a correct #:binding-forms annotation for the progs being added? (prog (defun (x_1 x_2) e_1 #:refers-to x_1) ... e_2 #:refers-to x_1 ...)


twisol
2017-7-11 16:24:55

Oh, wait, mutually recursive.


awe
2017-7-11 16:25:02

I think you can just have a binding form for defun?


twisol
2017-7-11 16:25:31

The defuns need to be mutually recursive, and the main body of the program has to be able to refer to all of the defuns


awe
2017-7-11 16:25:52

When were those requirements specified?


twisol
2017-7-11 16:26:02

Lecture notes for this morning’s session


awe
2017-7-11 16:26:15

:+1:


twisol
2017-7-11 16:26:16

This is at least superficially accepted by Redex: (prog (defun (x_1 x_2) e_1 #:refers-to x_1 ...) ... e_2 #:refers-to x_1 ...)


twisol
2017-7-11 16:26:22

(added moar ellipses)


awe
2017-7-11 16:26:49

I think your function body needs to refer to the argument too.


twisol
2017-7-11 16:27:05

good point!


twisol
2017-7-11 16:27:40

I did #:refers-to x_1 ... x_2, but I’m not sure of the rightward extent of #:refers-to


dan
2017-7-11 16:34:47

If you want a list in a refers-to clause I think you need to use the shadow form, as in #:refers-to (shadow x_1 ... x_2)


twisol
2017-7-11 16:37:59

Yeah, I added that and I’m running into some problems with substitute


twisol
2017-7-11 16:44:47

Re: lecture — There’s a whole host of reasons why there wouldn’t be a name clash here, I think


twisol
2017-7-11 16:45:47

A language-agnostic answer is that binding forms make sure this doesn’t happen. Even though we don’t have a binding form for defun, I believe we still can’t collide with any lambda bindings, because lambda itself has a binding form.


twisol
2017-7-11 16:46:06

A language-specific answer is that we just can’t face that situation in this language, because we can’t reduce under lambdas to begin with.


zeeshanlakhani
2017-7-11 16:59:25

@zeeshanlakhani has joined the channel


johnazariah
2017-7-11 17:18:34

quite a bunch of us from the Seattle area :slightly_smiling_face:


dan
2017-7-11 17:23:06

For those interested, here’s a binding specification for a PCF-like language that seems to do the right thing #lang racket (require redex) (define-language PCF (p ::= (program (d ...) e)) (d ::= (defun (f x) e)) (e ::= (lambda (x) e) (e e) (e + e) natural x) (f x ::= variable-not-otherwise-mentioned) #:binding-forms (lambda (x) e #:refers-to x) (defun (f x) e #:refers-to x) #:exports f (program (d ...) #:refers-to (shadow d ...) e_2 #:refers-to (shadow d ...))) (define-term t1 (program (defun (f x) (g (1 + x))) (defun (g x) (f x)) (f (g (y))))) (default-language PCF) (term (substitute t1 g w)) (term (substitute t1 x w))


florence
2017-7-11 17:24:35

(For those of you I talked to about this earlier, dan is smart and figured out how to do this with out that magic undocumented #:...bind thing.)


twisol
2017-7-11 17:26:23

That’s not far from what I had, except defun and program are separated and there’s an #:exports clause


twisol
2017-7-11 17:26:39

What are the material differences between that and: (prog (defun (x_1 x_2) e_1 #:refers-to (shadow x_1 ... x_2)) ... e_2 #:refers-to (shadow x_1 ...)) ?


twisol
2017-7-11 17:27:00

(other than getting weird errors from substitute in the latter)


dan
2017-7-11 17:29:43

@twisol what errors are you getting with that?it seems like it works for me


twisol
2017-7-11 17:29:57
(term (substitute (prog (defun (f x) (f x)) (f f)) x x))
. . second: contract violation
  expected: list?
  given: 'f«0»

twisol
2017-7-11 17:30:03

my grammar is slightly different from yours though


twisol
2017-7-11 17:30:06

lemme snippet it


twisol
2017-7-11 17:30:34

twisol
2017-7-11 17:32:38

Oops, I forgot to undo some experimental changes I did after I saw yours


twisol
2017-7-11 17:33:06

mflatt
2017-7-11 19:03:23

Dinner tonight is 6:00pm at Porcupine Pub & Grille https://goo.gl/maps/hHemMtjTGoz


twisol
2017-7-11 19:59:05

Doing the JS-like semantics (like ({"11": "foo"})[11]) is fun! :smile: Spoilers in thread below


twisol
2017-7-11 20:01:49

I added a show metafunction that takes numbers, strings, and booleans to their string representations, and allowed the key parameter to @ to be any of those things. Then I added a (where s_key (show k)) clause and pattern-matched on s_key in the record.


dan
2017-7-11 20:23:46

@twisol to follow up on the binding-forms issue from earlier, I think that’s a bug in redex’s binding-forms and I filed an issue https://github.com/racket/redex/issues/118


twisol
2017-7-11 20:25:31

@dan ooh, cool. Thanks!


fluffywaffles
2017-7-11 20:25:56

Does it toString functions the way JavaScript does?


fluffywaffles
2017-7-11 20:26:03

That is, function x () { return 5 } x.toString() // => function x() { return 5 }


twisol
2017-7-11 20:26:51

No, I didn’t implement show for functions.


fluffywaffles
2017-7-11 20:27:05

JavaScript does :slightly_smiling_face:


twisol
2017-7-11 20:27:15

I only wanted a proof of concept that I could reasonably match non-string keys to string elements in a record. You can expand this by adding more things to show.


fluffywaffles
2017-7-11 20:27:46

I was just thinking about how bonkers JavaScript is. Didn’t mean to imply you missed something, just wondered how closely you tried to replicate!


twisol
2017-7-11 20:29:16

Oh yeah, JS is so bonkers I tried not to do everything it does. I discussed the possibility with my seat neighbor, actually


twisol
2017-7-11 20:29:38

You could use the static distance transformation from yesterday to convert lambdas to a normal form, then recurse on that structure to produce a canonical string for that function


twisol
2017-7-11 20:29:52

It might be fun to do. It’s just way more work than I really wanted in order to get the behavior I needed.


twisol
2017-7-11 20:51:13

@dan Does the binding form you posted earlier allow the bodies of defuns to call other defuns? So you get mutual recursion?


dan
2017-7-11 20:53:33

@twisol I thought it did, but substitute is still not doing the right thing


dan
2017-7-11 21:48:41

@twisol I’ve edited the program too many times to keep it straight, but this version should have the correct mutually recursive binding structure



fbie
2017-7-11 23:02:02

@fbie has joined the channel


twisol
2017-7-12 04:44:36

Semi-spoilery observations about the semantics of RacketSchool/Functions3 under this thread. (Warning: it’s practically essay-length…)


twisol
2017-7-12 04:44:45

Is it fair to say that #lang RacketSchool/Functions3 is characterized by each function having a single “return address” register? That would mean that when a function calls itself, it forgets where to go when it itself returns, so it always returns to the point where it was called.

I think this might actually be testable! Compare the following functions:

(defun (f x)
  (if (zero? x)
      (++ 4 5)
      (++ 4 (f x))))

(defun (g x)
  (if (zero? x)
      (++ 4 5)
      (g (+ x -1))))

(defun (p x)
  (if (zero? (+ x -50))
      (++ 1 1)
      (+ x 1)))
(defun (h x)
  (if (zero? x)
      0
      (p (h (+ x -1)))))

If I call (f 4), the function never hits a base case, and so never returns. If it did, we would observe a ’stuck state. This is a bog-standard infinite loop in any language.

If I call (g 4), the function does hit a base case, and it gets ’stuck there. This demonstrates that recursive calls behave as expected: everything is normal up to this point.

If I call (h 4), the function eventually gets stuck! However, notice that the only way for it to get stuck is for the return value of h to eventually become 50. However, the function returns 0 at the base case, and since we passed 4, we should have no more than four recursive calls. But p is applied 50 times! This demonstrates that functions store their return address at a fixed location, not on the stack.


twisol
2017-7-12 04:47:22

Oh yeah, and I give a halting program that distinguishes all three languages.


twisol
2017-7-12 04:47:52

I think it was conjectured today that there was no such halting program for Functions3? :slightly_smiling_face: (To be fair, Dr. Felleisen specifically mentioned exceptions as an.. exception.. and that’s exactly what this program rests on.)


twisol
2017-7-12 04:48:01
4
0
'stuck