11 ms·
Taking an SICP-like class in Racket and playing with recursive constructs for the first time was one of the highlights of my CS education. This language gave mo
by sohamsankaran 6y ago
Taking an SICP-like class in Racket and playing with recursive constructs for the first time was one of the highlights of my CS education. This language gave more unalloyed joy than anything else I've done as a programmer, though I've yet to build anything practically useful in it.
- onemoresoop 6y agoI feel the same but unlike you I don’t care much about doing something practical. Well, I do, but am forgiving if the efficiency is not there. Just playing around with bigbang I came up with some game ideas that would not have come in a different environment. My take is that it is an environment fertile with creativity and ideas due to simplicity of scheme. Those can be taken and rebuilt elsewhere if needed. To me the joy is in the playground.
- billfruit 6y agoI thought similarly too, until I spent some time with Prolog. Lisp seems wonderful and clever, but Prolog feels even more magical. Even a simple thing like concatenation of two lists, that in Prolog it could be done purely declaratively, without expressing how it needs to be performed, seems levels more magical than how it is done in lisps.
- JadeNB 6y ago> Even a simple thing like concatenation of two lists, that in Prolog it could be done purely declaratively, without expressing how it needs to be performed, seems levels more magical than how it is done in lisps. Not to argue with the claim—Prolog does feel magic sometimes—and maybe I'm not sufficiently idiomatic in Prolog, but I would express them similarly: something like concat([], Bs, Bs). concat([A|As], Bs, [A|Cs]) :- concat(As, Bs, Cs). I don't have Lisp code at my fingertips, but that's quite like how I'd do it in Haskell: concat [] bs = bs concat (a:as) bs = a:(concat as bs) (I just looked up a Scheme primer to refresh myself, and I think there I'd do (define (concat as bs) (if (null? as) bs (cons (car as) (concat (cdr as) bs)))) … but don't hold me to it. Certainly not using pattern matching makes the Scheme more verbose, but I think the algorithms are the same.) Is one of these an un-idiomatic way to do it? (If you downvote, of course that's your right, but I'm not being sarcastic or dismissive; I really would like to know, as not a professional programmer in or fluent speaker of any of these languages, if I'm not writing idiomatically, so I'd be grateful if the downvote came with a comment!)
- junke 6y agoWhat is magical apart from pattern matching is how you can invocate it with mixed ground terms and variables, and it computes values that makes the relationship holds. For example: [eclipse 2]: concat(A,[_,_],[0,1,2,3,4]). A = [0, 1, 2] Yes (0.00s cpu, solution 1, maybe more) ? ; No (0.00s cpu) Or iterate over all lists that concatenate as [0,1,2] [eclipse 3]: concat(A,B,[0,1,2]). A = [] B = [0, 1, 2] Yes (0.00s cpu, solution 1, maybe more) ? ; A = [0] B = [1, 2] Yes (0.00s cpu, solution 2, maybe more) ? ; A = [0, 1] B = [2] Yes (0.00s cpu, solution 3, maybe more) ? ; A = [0, 1, 2] B = [] Yes (0.00s cpu, solution 4)
- ookdatnog 6y agoAs far as I (not a Prolog expert) know, your Prolog is idiomatic. But it is more declarative than your Haskell or Scheme implementations: you didn't just define a concat function, but a concat relation, which means you can use it in many more ways. Here are just a few examples from the top of my head. - The head function (with X unknown and L known): concat([X],_,L). - Produce all splits of a list (with X and Y unknown): concat(X,Y,L). - Does this list start with the prefix [a,b]? If yes, let Y be the tail (Y unknown): concat([a,b],Y,L). ... and many more.
- mturmon 6y agoThis is one of the most magical things about Prolog. From my functional/imperative programming experience, when originally picking up Prolog, I conceptualized the kind of operations you describe (e.g., “all splits”) as “running the function backwards” — going from output L to inputs X, Y. But as you write, the truth is that Prolog is modeling the relation of concatenation.
- masklinn 6y ago> Is one of these an un-idiomatic way to do it? I think the Scheme version might be considered unidiomatic due to the inefficiency: because it's not tail recursive, you're building a huge stack of cons calls (whose depth is the length of `as`) which only resolve once you reach the end of `as`. On the other hand, the version with accumulator would need to traverse as and bs in full, twice (once for the accumulation and once for the terminal reverse).
- deleted 6y ago[deleted]
- sedachv 6y agoThe good thing is you can have both: https://mitpress.mit.edu/books/reasoned-schemer https://mitpress.mit.edu/books/reasoned-schemer
- efxz 6y agoThere is newer, second edition! https://mitpress.mit.edu/books/reasoned-schemer-second-edition https://mitpress.mit.edu/books/reasoned-schemer-second-editi...
- jrumbut 6y agoSomething I would like to see is Prolog/logic programming embedded in a general purpose programming language, rather than as a standalone system. Racket and Perl 6 are the only small userbase languages in the last 8-10 years to amaze me with their feature sets and to make me want to learn them just for the sake of experiencing them.
- FPGAhacker 6y agoProbably doesn’t fit what you mean by mainstream, but even so: https://github.com/clojure/core.logic https://github.com/clojure/core.logic > A logic programming library for Clojure & ClojureScript. core.logic offers Prolog-like relational programming, constraint logic programming, and nominal logic programming for Clojure.
- jrumbut 6y agoThis is cool but less what I'm looking for, which is to actually write Prolog inside my Clojure source, or be able to include a Prolog file. Minikanren seems to be closer to the mark, and I thank the commenters who pointed it out!
- harperlee 6y agoI think you oversaw that core.logic is basically a minikanren (plus c-kanren, plus alpha-kanren) implementation in clojure instead of scheme; it even points to the papers and to The Reasoned Schemer for documentation and reference. That is, saying that minikanren seems to be closer to the mark than core.logic is a little bit nonsensical (please read that in a good sense!)
- jrumbut 6y agoYou're right, although I think what I was actually wrong about was what minikanren is (probably by looking at examples in languages I was less familiar with). I don't want to do logic programming in clojure (or whatever other language), I want to do logic programming in Prolog and drop it into my clojure project and have to do as little plumbing as possible. The nearest analogy I can come up with is LINQ. In the examples in [1] the experience of the developer is closer to writing SQL in the middle of a C# or VB file, rather than having a good C# database query library. [1] https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/ https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
- opnitro 6y agoOne of the coolest libraries I've ever had the pleasure of using is for Racket: Redex (https://redex.racket-lang.org/ https://redex.racket-lang.org/)
- sohamsankaran 6y agoThis is really neat. Is any of your code that uses this open source?
- opnitro 6y agoNot yet, but here's a great tutorial that introduces a really cool technique called Abstracting Abstract Machines: https://docs.racket-lang.org/tutorial/index.html https://docs.racket-lang.org/tutorial/index.html
- dntbnmpls 6y ago> This language gave more unalloyed joy than anything else I've done as a programmer, though I've yet to build anything practically useful in it. Ain't that the truth. Scheme/Racket, ML and other primarily academic functional languages are fun, but rarely used in business/industry. It's great for learning programming language ideas like scope, thunks, closures, etc but very little opportunity beyond that. But maybe that's why it was a joy to program with racket. No pressure to create anything practical with it. Just tinker and learn using it.
- vmchale 6y agoI've found J joyful! I still need to pick up SICP again :)