cdep.illabout_slack
2020-12-19 09:18:22

It looks like I should probably read Andrew’s dissertation as well.


hazel
2020-12-19 22:11:42

with megaparsack, is there a way to balance parentheses?


hazel
2020-12-19 22:11:44

something like (define balanced/p (do (char/p #\() (many/p balanced/p) (char/p #\))))


hazel
2020-12-19 22:13:01

like, have 0 to infinity copies of the parser within the parser


hazel
2020-12-19 22:21:33

…turns out that’s the literal implementation


notjack
2020-12-19 23:42:34

not without the original module’s permission, which it can grant in the form of #:unprotected-submodule


anything
2020-12-20 02:32:50

I do think of cons-lists as linked lists. Is that inadequate?


phanthero
2020-12-20 02:37:00

Not sure. The actual implementation in memory (at the time the course was taught at least), was slightly different from linked lists (according to the professor), so he said to not use the term linked list


phanthero
2020-12-20 02:46:04

So yeah


phanthero
2020-12-20 02:46:13

Actually I think I found the relevant spot in my course notes from that year


phanthero
2020-12-20 02:47:40

So what it’s saying is that say you have this: (define nums '(1 2 3)) (define five-lis (cons 5 nums)) Then five-lis and nums share the same list elements in memory


phanthero
2020-12-20 02:48:00

So if you call a function that mutates nums? Then five-lis will mutate too?


phanthero
2020-12-20 02:48:07

But this isn’t a problem in Racket usually


phanthero
2020-12-20 02:48:11

Since things cannot be mutated


phanthero
2020-12-20 02:48:26

But, this is not true in something like C


phanthero
2020-12-20 02:48:47

So “linked lists” works differently in Racket and C


phanthero
2020-12-20 02:48:50

I think that was the main idea


sorawee
2020-12-20 02:49:00

Not really


sorawee
2020-12-20 02:49:54

(cons A B) is really just:

x = malloc() x->fst = A x->snd = B


sorawee
2020-12-20 02:49:59

It’s the same


sorawee
2020-12-20 02:51:01

While it’s true that in Racket you cannot mutate things, that’s an additional restriction that you impose afterwards. The structure is still the same.


sorawee
2020-12-20 02:52:00

And note that if you use mutable cons (mcons), then you can do everything that you can in C.


sorawee
2020-12-20 02:52:06

E.g., create a circular list.


sorawee
2020-12-20 02:53:59

And in Scheme, mutable cons is the regular variant of cons.


phanthero
2020-12-20 02:56:06

So my Racket example converted to C would be like this right: cons *elem3 = malloc(sizeof(cons)); elem3->car = 3; elem3->cdr = NULL; cons *elem2 = malloc(sizeof(cons)); elem2->car = 2; elem2->cdr = elem3; cons *elem1 = malloc(sizeof(cons)); elem1->car = 1; elem1->cdr = elem2; cons *nums = elem1; cons *five = malloc(sizeof(cons)); five->car = 5; five->cdr = nums;


phanthero
2020-12-20 02:56:28

So calling a function that mutates nums would also mutate five


sorawee
2020-12-20 02:56:38

Yes


phanthero
2020-12-20 02:56:42

yea


phanthero
2020-12-20 02:57:20

Yeah, mcons and Scheme cons do something other than the usual Racket cons that we usually used in that first year introductory course, but yeah


phanthero
2020-12-20 02:57:44

The idea that they were trying to convey was that pure cons Racket type linked lists is usually not what we want in C


phanthero
2020-12-20 02:57:52

Sharing nodes is usually a bad idea


phanthero
2020-12-20 02:57:58

Bad side effects that we probably don’t want


sorawee
2020-12-20 02:58:42

It depends on what you want to do. You can totally create a persistent data structure in C. There’s nothing wrong with that.


sorawee
2020-12-20 02:58:59

In fact, it’s been used to avoid memory blowup in several applications


sorawee
2020-12-20 03:00:09

IIRC, KLEE’s main data structure is persistent (https://klee.github.io/)


phanthero
2020-12-20 03:01:11

Persistent means immutable right?


phanthero
2020-12-20 03:01:16

hmm


sorawee
2020-12-20 03:01:44

Yeah, immutable.


sorawee
2020-12-20 03:02:11

So you can share data without having to copy the whole structure


sorawee
2020-12-20 03:04:54

phanthero
2020-12-20 03:05:39

Yeah I’m not familiar with KLEE or where the relevant code is, but I guess they use some sort of class/object interface and just don’t allow direct modifiction (and have setters and getters instead, only)?


phanthero
2020-12-20 03:05:58

I mean, not even setters then


phanthero
2020-12-20 03:06:01

If it’s immutable


sorawee
2020-12-20 03:06:56

Not everything is needed to be enforced by the language. You can just document that no one should modify it. But yes, having the language to enforce it for you is nice, because people do make mistakes.


phanthero
2020-12-20 03:07:06

Yeah


phanthero
2020-12-20 03:07:14

Haskell is based around that entire principle apparently


phanthero
2020-12-20 03:07:20

The language enforces immutability


phanthero
2020-12-20 03:08:01

(haven’t actually used Haskell but I am going to try and learn it over the next few weeks)


phanthero
2020-12-20 03:08:46

But yes, it is a myth that one can’t do pure functional programming in C


phanthero
2020-12-20 03:08:50

It can be done


phanthero
2020-12-20 03:09:07

Just requires some caution and patience and things


phanthero
2020-12-20 03:09:24

It is true that it isn’t enforced by the language


phanthero
2020-12-20 03:09:36

Just like functional programming is not enforced by Racket


phanthero
2020-12-20 03:09:41

set! and things exist


phanthero
2020-12-20 03:09:48

But usually easy to avoid


phanthero
2020-12-20 03:10:35

I like how they explicitly mark them in Racket by using ! too lol


phanthero
2020-12-20 03:20:58

Question: Is it an accurate statement to say that arguments are passed by reference in Racket?


phanthero
2020-12-20 03:21:12

Seems like it with mcons


phanthero
2020-12-20 03:21:27

?


phanthero
2020-12-20 03:21:39

Wait…?


phanthero
2020-12-20 03:21:39

not sure


sorawee
2020-12-20 03:39:10

No. It’s pass by value, but you pass references around. Same for Java.


sorawee
2020-12-20 03:40:28

If it’s pass by reference, then you would expect:

(define (f x) (set! x 1)) (define y 0) (f y) (println y) to output 1, but it’s not.


phanthero
2020-12-20 03:49:18

??


phanthero
2020-12-20 03:49:31

(define lis (mcons "joe" '())) (define (fun l) (set-mcar! l "jojo")) (fun lis) (displayln lis) This seems to output {jojo}


phanthero
2020-12-20 03:49:40

But yes, set! seems to be doing something different


phanthero
2020-12-20 03:49:44

How is this?


phanthero
2020-12-20 03:50:11

Could you explain this: “It’s pass by value, but you pass references around. Same for Java.”?


phanthero
2020-12-20 03:50:15

Not familiar with Java at all


sorawee
2020-12-20 04:03:06

There are two types of mutation; variable mutation and structure mutation.


sorawee
2020-12-20 04:03:44

In Racket, you mutate variables by using set! and mutate structure by using stuff like vector-set!, hash-set!, set-car!, etc.


sorawee
2020-12-20 04:04:22

In, say, C, you mutate variables by <var> = ..., and mutate structure by A[B] = ... or A.B = ..., etc.


sorawee
2020-12-20 04:07:10

And these are different


sorawee
2020-12-20 04:07:22

To use C as an example (since you seem to be familiar with it)


sorawee
2020-12-20 04:09:16

#include <stdio.h> void f(int x) { x = 2; } int main() { int a = 1; f(a); printf("%d\n", a); return 0; }


sorawee
2020-12-20 04:10:48

This outputs 1, because when you call f, it passes the value of a (1) to f, and f makes a copy of 1 and put it in x. So when you variable-mutate x, a is unaffected.


sorawee
2020-12-20 04:12:33

On the other hand, for

#include <stdio.h> void f(int x[]) { x[0] = 2; } int main() { int arr[] = {1}; f(arr); printf("%d\n", arr[0]); return 0; }


sorawee
2020-12-20 04:13:51

The content of arr is its address. When you call f,  it passes the value of arr (adddress of arr) to f, and f makes a copy of this address and put it in x. So when you structure-mutate xarr is affected.


sorawee
2020-12-20 04:16:02

Racket is the same as C. It’s pass by value.


sorawee
2020-12-20 04:16:34

But when you pass objects to a function, it passes their addresses. Just like the arr example.


sorawee
2020-12-20 04:18:15

Pass by reference is different. When you call f, it doesn’t pass the value. Instead x and a become the “same” variable.


sorawee
2020-12-20 04:18:32

So any variable mutation to x will affect a.


phanthero
2020-12-20 04:19:57

Thank you for the example, it is much clearer now


phanthero
2020-12-20 04:20:06

So are references only for objects?


phanthero
2020-12-20 04:20:15

What is an “object”?


sorawee
2020-12-20 04:20:20

I gotta go now, sorry.


phanthero
2020-12-20 04:20:30

OK


phanthero
2020-12-20 04:24:02

I’m still not entirely clear, so I will type my questions here if anyone else knows though: • In Racket, things are passed by value according to @sorawee • But, for “objects”, alongside the value for the “object”, the reference (address in memory) is also passed. Is this statement true? What is an “object”? Is it passed if we call foo(lis), foo(1) and also for foo(some-number-variable-name) ?


phanthero
2020-12-20 04:24:35

Clearly 1 does not have a reference, but I probably some-number-variable-name and lis (which is a list) both do (right?)


phanthero
2020-12-20 04:24:57

How do you know when the references are passed?


phanthero
2020-12-20 04:25:25

Again, not sure what happens in Java but is it a similar story there then?


me1890
2020-12-20 04:25:56

in java everything is a reference except for primitives (int and such)


phanthero
2020-12-20 04:26:29

I’m more familiar with C++, but is this sort of related to lvalues (things that can be assigned a value, and thus, “mutated”)?


phanthero
2020-12-20 04:26:50

Obviously you can’t assign a value to "string" and 42


me1890
2020-12-20 04:27:09

i’m not familiar with c++’s rules either


me1890
2020-12-20 04:27:23

(i probably should be familiar with c’s rules though)


phanthero
2020-12-20 04:28:04

Yeah, maybe what happens in Racket is that everything that can be assigned a value (things with a name?) are passed by value, but implicitly the reference is passed as well (wondering if someone can confirm)


phanthero
2020-12-20 04:28:30

Yeah, lvalue seems to be a fancy C++ term but it just refers to variable name, not anything fancy really


phanthero
2020-12-20 04:28:46

Things like primitives in Java would be called rvalues


phanthero
2020-12-20 04:28:49

I think


me1890
2020-12-20 04:28:51

I think lvalue and rvalue are C, but things like glvalue are c++ only


phanthero
2020-12-20 04:28:59

I see


me1890
2020-12-20 04:29:02

I think you are correct about the rvalues vs lvalues though


me1890
2020-12-20 04:29:10

I find the concept quite confusing


me1890
2020-12-20 04:29:23

Rust does a much better job at dealing with it i think


me1890
2020-12-20 04:30:35

IIRC the only way to assign a value is to a mutable reference


phanthero
2020-12-20 04:31:02

I see


phanthero
2020-12-20 04:31:09

Like mcons or hash ?


me1890
2020-12-20 04:31:16

like box


me1890
2020-12-20 04:31:19

sort of


phanthero
2020-12-20 04:31:22

Otherwise we can’t do it I guess


me1890
2020-12-20 04:31:33

in rust reference is a type, so it doesn’t quite translate


me1890
2020-12-20 04:31:41

it’s mostly like references in c++


phanthero
2020-12-20 04:31:57

Right


phanthero
2020-12-20 04:32:09

I don’t really use references that often, usually it’s pointer


phanthero
2020-12-20 04:32:13

Forgot that existed lol


me1890
2020-12-20 04:32:25

haha


me1890
2020-12-20 04:32:36

I don’t use c++ much, but i like to use references when i can


me1890
2020-12-20 04:32:42

it makes my code a little neater


phanthero
2020-12-20 04:33:10

Haven’t really used boxes in Racket


me1890
2020-12-20 04:33:29

I haven’t either. I sort of don’t get them


phanthero
2020-12-20 04:33:57

But things that are “objects” like mcons or hash seem to have set-foo! usually, where foo is an “element”


me1890
2020-12-20 04:34:05

As far as i can tell, their use is basically as a structural mutation wrapper


me1890
2020-12-20 04:34:13

yeah


phanthero
2020-12-20 04:34:36

Yeah. I think I mostly get it. Two types of mutation. Variable and structure


phanthero
2020-12-20 04:34:56

Structures can be mutated within a function since their location in memory is also passed


phanthero
2020-12-20 04:35:20

Variables don’t have their locations in memory passed I guess then


phanthero
2020-12-20 04:35:26

They might?


phanthero
2020-12-20 04:35:45

But when you enter a function like (foo x), x is just a local variable


phanthero
2020-12-20 04:36:04

if you assign that local variable to something else, the original stuff is gone, no matter where is was before


phanthero
2020-12-20 04:36:18

The original caller to that function doesn’t know anything about x


me1890
2020-12-20 04:36:24

~i think i know where to read about this more in the manual~ nvm


phanthero
2020-12-20 04:37:47

Yeah I think this makes sense if you think about how functions are called in C


phanthero
2020-12-20 04:38:10

The caller stores everything it needs on it’s own stack frame


phanthero
2020-12-20 04:38:19

The callee just does it’s own thing


phanthero
2020-12-20 04:38:31

Unless a reference is passed, the callee and caller live on different worlds


phanthero
2020-12-20 04:38:49

I think the reference is only passed for “objects” in Racket


phanthero
2020-12-20 04:38:57

But I’m not sure what an “object” is though


phanthero
2020-12-20 04:40:21

Even I’m confused now. I think even if “objects” are passed, variable mutation won’t do anything to them


phanthero
2020-12-20 04:40:33

You need to go into their memory location, and modify their contents


phanthero
2020-12-20 04:40:38

idk


me1890
2020-12-20 04:41:35

ah


me1890
2020-12-20 04:43:31

From the guide page https://docs.racket-lang.org/guide/set_.html?q=mutation#%28part._using-set%21%29 > The use of mutable values, such as vectors and hash tables, raises fewer suspicions about the style of a program than using set! directly. Nevertheless, simply replacing set!s in a program with vector-set!s obviously does not improve the style of the program.


me1890
2020-12-20 04:43:47

So think there is a notion of “mutable values” and normal (immutable) values


me1890
2020-12-20 04:44:30

I think this is the same as the rust concept of “interior mutability”


phanthero
2020-12-20 04:45:17

Hmm


phanthero
2020-12-20 04:45:27

When it comes to hash tables, there really are a few types


phanthero
2020-12-20 04:45:34

The one I usually use is mutable


phanthero
2020-12-20 04:45:39

The other category is immutable


phanthero
2020-12-20 04:46:06

So things like set-hash! will only work for mutable ones


phanthero
2020-12-20 04:46:17

I guess I break functional programming paradigms when I use mutable hash tables


phanthero
2020-12-20 04:46:20

Didn’t realize


phanthero
2020-12-20 04:47:05

Yep


phanthero
2020-12-20 04:47:11

make-hash makes a mutable hash


me1890
2020-12-20 04:47:28

the naming conventions there are confusing to me


me1890
2020-12-20 04:49:04

because hash makes an immutable map, but make-hash makes a mutable map so i need to use make-immutable-hash if i want an immutable hash, but constructing it with the make- conventions


phanthero
2020-12-20 04:50:23

I think you can pass a mutable hash to make-immutable-hash and it will give you an immutable hash


phanthero
2020-12-20 04:50:37

Yeah, it is slightly confusing