|
ultrafilter posted:Speaking of functional languages for web development, there's a (very early) OCaml to Javascript compiler that might be interesting. There is also this from the Ocsigen project, which is more mature: http://ocsigen.org/js_of_ocaml/
|
# ? Feb 12, 2016 02:32 |
|
|
# ? Jun 5, 2024 04:43 |
|
Charlie Mopps posted:The first Elm book will be coming: About a year and a half ago, I got an email from some UK book publisher asking if I would be interested in writing an Elm book.
|
# ? Feb 16, 2016 08:40 |
|
The Lisp thread got archived or something, so I'm gonna guess that this is where we ask Clojure questions. I've been trying to implement the card game War in Clojure. It's very simple: technically, there's two players, but there are basically no decisions made by either player so it can be programmed as a zero-player game. This boils the game down to an initial state, and a certain pipeline it goes through for each "tick" of the game. That means you can play the game by just pushing the state through the pipeline over and over, and rendering it to the screen when it comes out of the pipe. I understand the logic of the game, and know what steps need to be taken, but the code I wrote for it is goddamn awful: Lisp code:
How can I improve this code, and the project in general? How would someone who's better at programming in Lisp than I am approach a problem like this? Does what I'm doing make sense, or is it in need of serious refactoring?
|
# ? Feb 18, 2016 20:07 |
|
Excuse me, but in War you can count your opponent's cards and secretly put your cards in a certain order when shuffling your winnings back in.
|
# ? Feb 18, 2016 20:20 |
|
Almost every function is the same: extract players off game state, do an operation on one or the other, and then replace the players in the game state. I'd probably make an abstract function for these that takes care of doing that. Pass in a pair of players, expect a pair back. Then the function that calls it just has to deal with extracting/reinserting them. That will save up a bunch of lines on repeated abstractions.
|
# ? Feb 18, 2016 20:30 |
|
I think part of the problem is that I'm constantly associng things into game-state as the return value for every function. I feel like if I have to do that so often, I might be doing it wrong. Functional data structures are kind of a pain to work with in my experience since you constantly have to haul around a reference to the top-level data structure and assoc new attributes into it, which can reach several layers deep. But maybe that's just because of how I approached the problem
|
# ? Feb 18, 2016 23:26 |
|
How would you explain polymorphic lambda calculus well enough for another person to be able to derive typing judgements by hand? Let's say that this person is a Java programmer that is loosely familiar with prop logic. I can't do it without puking out formalisms or being too vague.
|
# ? Feb 19, 2016 01:01 |
|
Do they already understand untyped/simply-typed lambda calculus, or are you trying to bypass those?
|
# ? Feb 19, 2016 01:51 |
|
I can probably assume untyped. I'm trying to help a fellow student, but I took a bunch of logic courses so it's new to me also, but I wouldn't know what it would be like to start out by learning lambda calculus.
dougdrums fucked around with this message at 04:36 on Feb 19, 2016 |
# ? Feb 19, 2016 04:31 |
|
Pollyanna posted:I feel like I'm doing something horribly wrong here. There's lets everywhere, a whole bunch of code repetition, and overall the whole thing feels way too verbose and weird. I tried to take a top-down approach with programming the game, but I feel like I totally missed the mark. I'm not entirely sure if my approach of making Player and Card records was a good one, and I don't feel like I'm really taking advantage of Clojure's strengths here. Here's a pretty great talk from the last Clojure/conj about implementing a card/board game from the bottom-up. Maybe this kind of approach would work better for you? https://www.youtube.com/watch?v=Tb823aqgX_0
|
# ? Feb 21, 2016 07:27 |
|
dougdrums posted:How would you explain polymorphic lambda calculus well enough for another person to be able to derive typing judgements by hand? Let's say that this person is a Java programmer that is loosely familiar with prop logic. I can't do it without puking out formalisms or being too vague. I would start by constructing proof trees using typing rules for simply-typed lambda calculus, unless there's some pressing need to skip straight into System F. I don't see any way to avoid the formalism - in the simply-typed case, it is straightforward and easy to apply. The typing rules have fairly obvious interpretations which might make them easier to remember and understand.
|
# ? Feb 24, 2016 09:44 |
|
The only pressing need is that we're taking it as a course. Regular human math is just nonsense to me and I just had to drop a course due to this, so I have a ton of sympathy for this fella who helped me in a previous math course but is finding lambda calculus to be absolutely opaque, and he isn't the only one. I had the idea of trying to write up a little crash course and a little index of notations with how their semantics work, try to approach it like programming a computer with funny symbols, but beyond, "follow the god drat simple rules, and if you gently caress up, which you will, do it again." I am at a loss, but I know this is exactly how my god drat math tutor feels and I know how it feels to look at a page of symbolism and go fuuuuuuuuk in my head. We're starting to get into System F in class so I kinda wanted to make it as fast as possible. The most useful advice I seem to have given was, "imagine the term as a little computer program, what types would you assign the variables?" I mean, I don't think I really had an intuition for what domain and range were until I did the proofs (and it is mentioned in passing, confusing those who might not be so solid on functions in the first place), so it's hard for me to backtrack and approach it from the top-down, since I didn't even learn it that way. Really after writing this, I think the only way to learn is to do proofs and gently caress them up over and over again, but that seems like useless advice to give someone. I think I'll just have to let them struggle ... :-/ After learning all of that higher order stuff I love lambda calculus. It is so deceptively simple, and there are a ton of variations with interesting properties. It's just that fuckin learnin and teaching and learning in general is such a god drat frustrating exercise. To keep this somewhat on topic: I understand Racket uses GNU Lightning, but I haven't done a lot of functional programming beyond F#. Generally speaking how does it compare in speed to other implementations? Also I've never actually tried Haskell up until this moment, despite having read a poo poo-ton about it. http://tryhaskell.org/ output is great! Maybe I should just try to explain it using Haskell, duh! dougdrums fucked around with this message at 01:34 on Feb 25, 2016 |
# ? Feb 25, 2016 01:16 |
|
I'm looking for an FP language to learn and eventually do actual work in. My current day job is ruby mostly but it seems we will be moving towards jruby / jvm based dev and deployment. I have poked around with haskell in the past and done the first 6 or so adventofcode problems in haskell but I don't really see how I would be able to use it productively or teach it to my coworkers. I initially thought that maybe scala would be the way to go but it seems that it would be really easy for someone to fall back to writing imperative code in scala. Would typed clojure be a good middle ground / starting point between dynamically typed imperative code and typed functional code? Does typed clojure have a mechanism for 'typeclasses' like haskell, ie, can I specify a "monad" interface for types and have separate implementations per type?
|
# ? Feb 25, 2016 14:23 |
|
Pollyanna posted:
Some hints: You can use the update and update-in functions to modify entries directly: Lisp code:
code:
|
# ? Feb 25, 2016 14:30 |
|
Lunixnerd posted:I initially thought that maybe scala would be the way to go but it seems that it would be really easy for someone to fall back to writing imperative code in scala. I'm in the camp that considers this a good thing, although I don't know anything about Scala or Clojure specifically.
|
# ? Feb 25, 2016 21:18 |
|
GrumpyDoctor posted:I'm in the camp that considers this a good thing, although I don't know anything about Scala or Clojure specifically. When you're trying to learn functional programming for the first time I think it's a good idea to use a language that forces you to use it.
|
# ? Feb 25, 2016 21:32 |
|
Yeah, I thought I knew functional programming pretty well until I started forcing myself to actually use Haskell for new hobby projects.
|
# ? Feb 26, 2016 01:52 |
|
Once you get used to them, it's nice to use pure functional languages that force you to cordon off side effects.
|
# ? Feb 26, 2016 02:02 |
|
I learned to program in Haskell, and the worst thing about having to use other languages in school (Java, C, Ruby, OCaml) is the lack of typed side effects (and the entire apparatus Haskell uses to accomplish this). I'm pretty convinced that monads should be Haskell's selling point (from a software development standpoint), but I might just be brainwashed or something.
quickly fucked around with this message at 05:30 on Feb 27, 2016 |
# ? Feb 27, 2016 05:25 |
|
Haskell is easily my favorite imperative language. There's just so many tools available to express your intentions and reason about your code, even without getting into the really clever abstractions. Also, lens is amazing.
|
# ? Feb 27, 2016 08:21 |
|
drat, what's your favorite functional language then?
|
# ? Feb 27, 2016 16:27 |
|
My favorite functional language is Python. It has lambdas and list comprehensions.
|
# ? Mar 1, 2016 01:27 |
|
Doc Hawkins posted:drat, what's your favorite functional language then? Mostly I'm trying to make a point about paradigm availability.
|
# ? Mar 1, 2016 02:07 |
I'm going to harken back to the Sieve of Eratosthenes question from page 4. I'm starting to fiddle with Clojure (I'd started in Racket but didn't like the docs). One of my biggest motivations was being able to more simply implement symbolic differentiation and machine learning stuff. The tricky part with that is I'm generally only familiar with the cases where you have really big matrices which are updated a whole bunch of times. I've heard Clojure keeps around old references, and that worries me. I know they don't use copy-on-write, but something more efficient. All the same, when you've got structures that don't fit into memory and require dozens of updates, it makes me a little concerned about how that's going to work out in a purely functional language, or if it's not objectionable to have side-effects by design. Does the matrix become the mutable state of the application?
|
|
# ? Mar 4, 2016 23:15 |
|
My experience in Haskell, at least, has been that purity isn't so much about never having side effects but rather quantifying them as precisely as possible, e.g. with various monads. I don't know what the idiomatic approach to that is in Closure, but if your computational task really demands mutable state that certainly doesn't mean it's poorly suited to implementation in a pure functional language.
|
# ? Mar 5, 2016 01:16 |
|
Jo posted:I'm going to harken back to the Sieve of Eratosthenes question from page 4. Clojure is totally cool with your mutable state. If you want to mutate a huge matrix while using idiomatic code, I'd recommend that you use "transients" (http://clojure.org/reference/transients). Clojure's vectors are capable of transient operations, so you should be able to represent your matrix as a transient vector of transient vectors. You can code like it's Clojure and consume memory like it's imperative code manipulating one global blob of memory! There are also matrix libraries you could look at, like https://github.com/mikera/core.matrix. I have no experience with it, but you might take a look. Finally, I suggest that you not worry about memory consumption before writing the code. Instead, I think you should write your code first, then determine if it's too slow or too memory-heavy, and then consider ways to deal with it. Unless you've already written some code and observed a memory problem, you are currently engaged in premature optimization.
|
# ? Mar 7, 2016 01:51 |
Tequila Bob posted:Clojure is totally cool with your mutable state. If you want to mutate a huge matrix while using idiomatic code, I'd recommend that you use "transients" (http://clojure.org/reference/transients). Clojure's vectors are capable of transient operations, so you should be able to represent your matrix as a transient vector of transient vectors. You can code like it's Clojure and consume memory like it's imperative code manipulating one global blob of memory! I had no idea about transients! That seems to be precisely what I need. It's going to take me a while to figure out how to re-fit my mental model of the problem to use them, but I'm thinking that will handle it. I've been bitten by memory consumption problems with this problem domain before, so I'm always on the lookout. Our production server has 128 gigs of ram and I'm still bumping up against that limit when I run the application full tilt. I'd love to get utilization down, but there's only so much that you can do when you've got a giant multi-gigabyte matrix that you're constantly rebuilding. EDIT: Follow-up question because I don't want to bump. I wrote a simple automatic differentiation method and was wondering about a certain operator comparison. code:
Is there a consistent way to check operators? Sometimes they seem to go to clojure.core/+, sometimes to +, and sometimes to #<native method blah blah.> Jo fucked around with this message at 23:48 on Mar 10, 2016 |
|
# ? Mar 8, 2016 07:09 |
|
If people are looking for some lunchtime videos to watch, both Erlang Solutions 2016 and Lambda Days 2016 recently took place and videos of the various talks have been posted on the Erlang Solutions youtube channel: https://www.youtube.com/user/ErlangSolutions/videos. And there was also a virtual F# conference whose videos can also be watched now: https://channel9.msdn.com/events/FSharp-Events/fsharpConf-2016
|
# ? Mar 11, 2016 08:55 |
|
Jo posted:I'm pleased with how small it is, but the operator comparison (or (= op 'clojure.core/+) (= op '+)) looks messy to me. This is a job for case: code:
|
# ? Mar 11, 2016 18:32 |
|
Okay, I'm having trouble writing idiomatic Clojure code in terms of architecture and top-down vs. bottom-up programming. I'm scaling way the gently caress back and just making a plain library that plays War. The idea is that there is one data structure: the game. Lisp code:
The hard part is coming up with the functions. I want to just do something like this to advance the game state one tick: Lisp code:
Lisp code:
Lisp code:
Lisp code:
You can tell that I'm not terribly satisfied with the results. Sure, it theoretically works, but I'm not sure how to test and debug it. lein repl doesn't seem to have any step-debugging or breakpoints, so I have to rely on println, which sucks butt. And in terms of application architecture, this ended up being top-down as opposed to bottom-up, because that's just how I'm used to doing things. It's a lot more straightforward to go from a full representation of the game as opposed to individually defining cards, then decks, then players, then the game. I'm also realizing that most of these functions should be marked private, outside of tick-game. Plus, some of them are just plain awful. award-winnings and resolve-match are particularly ugly, and I don't feel like I understand Clojure (or Lisp in general) well enough to write these functions right the first time. What am I missing here? Did I take a sensible approach to developing this program? What should my workflow be? What do I need to learn to be good at this language, and make things that are better than just endlessly nested functions on a data structure or two? I see people putting together loving, like, graphs and nodes and channels and systems everywhere, and I have no idea how I'd do that in Ruby, let alone Clojure.
|
# ? Mar 11, 2016 19:09 |
|
Pollyanna posted:You can tell that I'm not terribly satisfied with the results. Sure, it theoretically works, but I'm not sure how to test and debug it. lein repl doesn't seem to have any step-debugging or breakpoints, so I have to rely on println, which sucks butt. And in terms of application architecture, this ended up being top-down as opposed to bottom-up, because that's just how I'm used to doing things. It's a lot more straightforward to go from a full representation of the game as opposed to individually defining cards, then decks, then players, then the game. I'm also realizing that most of these functions should be marked private, outside of tick-game. One thing I've found invaluable for Scheme is trace-define, and it looks like Clojure has its own version. Look at that for debugging. The architecture is close, IMO. Here are some suggestions. I'd expect resolve-match to look more like this, though (keeping in mind I know Scheme but not Clojure so the syntax probably isn't right): code:
code:
code:
|
# ? Mar 12, 2016 02:08 |
|
gonadic io posted:Then you'd have 5(?) problems. Lenses have 5 type param these days right? Apparently, one of the lenses they were going to implement started taking type arguments in the form i m a s t a b u. They took the hint and decided not to implement it.
|
# ? Mar 13, 2016 07:01 |
|
Is this code readable by functional standards? I'm in the middle of writing my first non-trivial project in haskell and I don't know if it's total spaghetti or I'm just not used to reading functional code. I know it would be less clunky if I used a more appropriate data structure but that's what I've got to work with for now.code:
e: noticed a mistake right after I posted Magissima fucked around with this message at 18:01 on Mar 13, 2016 |
# ? Mar 13, 2016 17:58 |
|
I don't know about the structure of the code as a whole, but I'd probably clean it up to be like this:code:
|
# ? Mar 13, 2016 18:19 |
|
I think you're right that the problems originate from the data structure. The reason I have it that way is that this is from an assignment that was originally meant to be in java until the professor changed his mind and said we could use whatever, so I just directly took the java data structure and used that. It's obvious to me now that it makes a lot more sense to have a meaningful list index when you're working with loops than with functions, so lesson learned on that front. Thanks for the feedback!
|
# ? Mar 13, 2016 19:17 |
|
Puella Magissima posted:I think you're right that the problems originate from the data structure. The reason I have it that way is that this is from an assignment that was originally meant to be in java until the professor changed his mind and said we could use whatever, so I just directly took the java data structure and used that. It's obvious to me now that it makes a lot more sense to have a meaningful list index when you're working with loops than with functions, so lesson learned on that front. Thanks for the feedback! The data structure isn't even the problem. You can do this just fine without explicit indicies and still get what you want because your edges are the indicies. Assuming an input that looks like: code:
code:
If you need node names for some reason (like strings or something), just zip them with numbers, build a list of number-number edges, run this, then translate them all back. gonadic io is right, though, that this should really use Data.Map (or at least a vector) because this sort of implementation is comparatively inefficient.
|
# ? Mar 13, 2016 19:25 |
|
Whoa, that's way better than what I had. I don't think it even occurred to me to recurse to the correct list instead of manually indexing, but when you put it like that it makes total sense. I guess I'm still not used to thinking functionally. I probably should have come here before spending an hour banging my head against the wall coming up with my lovely solution. Thanks a lot for your help. I'll look into Data.Map as well.
|
# ? Mar 13, 2016 20:00 |
|
I disagree with your last point - you "banging your head" was you learning Haskell, and you seeing QuantumNinja's solution without having come up with your own wouldn't be nearly as helpful. It'd, of course, be entirely different if you just needed a solution and didn't care how it worked. In that case I'd recommend that you use Data.Graph instead of reimplementing it.
|
# ? Mar 13, 2016 20:10 |
|
Reading The Little Schemer helped me think more "functionally" and that was before I even started using functional languages for real.
|
# ? Mar 13, 2016 20:13 |
|
|
# ? Jun 5, 2024 04:43 |
|
AWWNAW posted:Reading The Little Schemer helped me think more "functionally" and that was before I even started using functional languages for real. I also found Scheme to be a good intro, although I read SICP (or part of it anyway).
|
# ? Mar 13, 2016 21:15 |