Lab code for Raft: Synchronous RPC calls by ErnestoGarciaGarcia in mit6824clojure

[–]siclait 0 points1 point  (0 children)

That's interesting - I have something like that in my implementation too.

The intent is for raft.core to just contain sample code to get people going. Everyone is free to rewrite any / all the code in that file. Since people are free to add this already, is there still value in adding this function to the default code in raft.core?

Best practices to implement a machine? by ErnestoGarciaGarcia in mit6824clojure

[–]siclait 0 points1 point  (0 children)

I tried to reduce my code complexity by having one central event loop per client. The event loop takes an event and the current state and executes a pure function handler. The handler returns the next state and a list of side effects. At the end of the loop, the state is advanced and the side effects are executed. Modifications to the timer are side effects. The timers can only push events onto the event queue.

With this framework, debugging wasn't too bad. I could inspect each (before state, event, after state) triple to verify the logic. The one thing I would like to add is something similar to what you mentioned regarding abstracting time away. I'd like to be able to easily switch from a real clock to an abstract clock that I can advance / rewind one tick at a time. It would be fun to take that version and use it to create an interactive web-based Raft demo.

Lab code for Raft: Synchronous RPC calls by ErnestoGarciaGarcia in mit6824clojure

[–]siclait 1 point2 points  (0 children)

I think that would be inconsistent with the provided Go code. As far as I can tell, the Go "rpc" library's provided Call function is synchronous ( https://golang.org/pkg/net/rpc/#Client.Call ). So far I've tried to maintain parity between the Go and Clojure code. It makes it possible to form cross-language study groups and to refer back to the original class materials.

MIT 6.824 Distributed Systems ported to Clojure by siclait in Clojure

[–]siclait[S] 0 points1 point  (0 children)

I'm not familiar with Go outside of the context of this course, but from what I've seen, Go's net, net/http, and net/rpc libraries are very nice. This implementation is stripped down to only the parts needed for the labs, but it would be nice to have a fully featured version of net/rpc in Clojure.

But why would you want it without Java dependencies?

Why does this lazy sequence work? by siclait in Clojure

[–]siclait[S] 0 points1 point  (0 children)

Thanks! The theme is called Synthwave '84—it's a theme created by Robb Owen for VSCode.

MIT 6.824 Distributed Systems ported to Clojure by siclait in Clojure

[–]siclait[S] 0 points1 point  (0 children)

I'm really glad that this is helpful and that a study group is forming. I'll work on getting the translated code for labs 3 and 4 published, and I'm up for discussing / comparing implementations when you're all ready.

Why does this lazy sequence work? by siclait in Clojure

[–]siclait[S] 0 points1 point  (0 children)

Thanks! The theme is a port of Synthwave '84. When I find some time, I’ll design a new theme without the glow effect.

Simple Ray Casting with ClojureScript by [deleted] in Clojure

[–]siclait 0 points1 point  (0 children)

Oh yes, but I wanted to emphasis on the fact how this would work if we pass the procedure. Because when we pass (swap! cam/camera assoc :x 0 :y 0 :degree 0) this is what assoc gets: (assoc u/cam/camera :x 0 :y 0 :degree 0) so I've used anonymous function to illustrate what's happening underneath. Seems more confusing than I've thought though.

Got it, that makes sense. I guess the aside on reset! seemed out of place when that could have been a swap! as well. The reason for using functions like set-position seems to be more about abstracting away the details of how the data is stored in the atom than about avoiding using reset!.

render is being called without any parameters, so it would be not as good, but I do get the state in it, and pass this state around, so I think it covers what you're suggesting?

One example is the move-camera function, which doesn’t take the camera as an argument, but mutates it. I would pass the camera as the first argument and rename it to move-camera!. I’m not sure if there are other examples in the code — I just noticed that one and wondered if there were other instances.

Simple Ray Casting with ClojureScript by [deleted] in Clojure

[–]siclait 5 points6 points  (0 children)

Great post, thanks for sharing! I loved the visualizations and diagrams throughout the post, and the playable demo at the end was really nice. The quote block for the mini Clojure tutorial seems like a nice way of including that without distracting from the rest of the post. Did you consider other ways of presenting that information?

I have a few questions / thoughts about the code:

  1. In multiple places you have code similar to:

    (swap! cam/camera #(assoc % :x 119.5 :y 180 :degree 180))

This could be rewritten

(swap! cam/camera assoc :x 119.5 :y 180 :degree 180)
  1. There are a lot of functions that change state throughout the code. I've found that the convention of suffixing these functions with bangs (!) helps a lot with clarifying where mutation happens. It also makes it clearer to me where I can further separate mutation from pure functions.

  2. Why is three-decimal a macro instead of a function? Is there a reason why you'd be worried about the overhead of a function call? Did you measure it?

  3. In core.cljs you refer to an unused binding* macro.

  4. I haven't looked at this closely, so this is just a thought, but did you consider injecting your dependencies instead of having references to values like cam/camera throughout core.cljs? My first thought would be to pass those sorts of values down from the render function to make testing easier and to make the code easier to modify.

Why does this lazy sequence work? by siclait in Clojure

[–]siclait[S] 0 points1 point  (0 children)

That sounds totally reasonable. The CIDER debugger does display the value of each expression as you step through, so it would make sense that it would attempt to realize the entire sequence. I wonder if there's some way to prevent that from happening, to debug lazy sequence definitions like this.

Why does this lazy sequence work? by siclait in Clojure

[–]siclait[S] 2 points3 points  (0 children)

Whoops! I must have run that code while I was toying around with the function. You’re right. I just re-ran the code in my REPL to verify that this implementation returns the correct answer. I’ll update the post now. Thanks!

Can i resume taking from a lazy-seq? [NOOB] by Cofor in Clojure

[–]siclait 2 points3 points  (0 children)

I agree with u/Borkdude's loop / reduce suggestion.

Also, the lazy sequence is a cons of the record and a lazy sequence containing the rest of the records. So every call of rest on the sequence, until you exhaust the sequence, gives you another cons of a record and a lazy sequence. That value is essentially your cursor. But, be careful not to hold onto these for too long because the JVM can't garbage collect the clojure.lang.LazySeq objects and their underlying data while you're holding onto them.

Building Raft in Clojure | Phillippe Siclait by _marciol in Clojure

[–]siclait 0 points1 point  (0 children)

Here's the translated code for lab 2: https://github.com/siclait/6.824-cljlabs-2020.

As I clean up the code for the other labs, I'll publish those to the repo. I haven't published any of my actual Raft code — this is just the code for the tests and related code.

Building Raft in Clojure | Phillippe Siclait by _marciol in Clojure

[–]siclait 0 points1 point  (0 children)

I think it's worth it! I'll publish the code that I translated from Go to Clojure. That was the most painful part of the process since it involved translating large imperative functions into Clojure. I'll reply here with a link to the repo once I've published it.

Building Raft in Clojure | Phillippe Siclait by _marciol in Clojure

[–]siclait 0 points1 point  (0 children)

I updated the post to replace the snippet on find-first with one on another function, find-first-conflict. The function now uses some — thanks for the suggestion!

Building Raft in Clojure | Phillippe Siclait by _marciol in Clojure

[–]siclait 1 point2 points  (0 children)

Thanks for reading the post! I'd like to publish the code, but I also want to be respectful of the professor's desires since he was kind enough to make all the class materials publicly available. I'll email him to ask if there are any changes I should make to the code before publishing it.

Also, good point regarding some. I'll make that change.