Hacker News new | past | comments | ask | show | jobs | submit login
Advanced programming languages (2009) (might.net)
91 points by swah on Dec 14, 2014 | hide | past | favorite | 39 comments



I'm surprised Prolog is not listed there. here's a simple example, try designing a function that calculates Fibonacci two ways in your favourite language. given fib(N,X). You can supply either N, or X or neither and generate the result.

?- time(fib(N, 703303677114228158218352548771835497701812698363587327426049 050871545371181969335797422494945626117334877504492417659910 881863632654502236471060120533741212738673391111981393731255 98767690091902245245323403501)). % 44,649,335 inferences, 4.182 CPU in 4.193 seconds (100% CPU, 10676854 Lips) N = 1000 .

?- time(fib(1000, F)). % 497,690 inferences, 0.072 CPU in 0.072 seconds (100% CPU, 6935880 Lips) ...


I'll be updating the article at some point to add miniKanren.

Will Byrd is my postdoc, and he's been pushing relational/logic programming with miniKanren:

http://minikanren.org/

If you haven't seen miniKanren, check it out.


Prolog is quite nice, it is the next step for those that already grok functional programming.


Beside dependent types, bidirectional (~relational) programming is the only thing that amaze me.

Dan Friedman gave talks about [mini]kanren, see https://www.youtube.com/watch?v=5Q9x16uIsKA

I couldn't find the one where he asks (eval exp '()) to be 6 and gets many results such as

    6
    ;; duh

    (let ((_ 5)) 
      ((lambda (x) (+ x 1)) _))
    ;; better
Here's an example involving cons cells only https://www.youtube.com/watch?v=kS_2_-E_JjU


Haskell -

  fib (Just n) Nothing = Just (fibs !! n)
  fib Nothing (Just x) = let (n, x') = head (filter (\(_,y) -> y >= x) (enumerate fibs))
    in if x == x' then Just n else Nothing

  fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

  enumerate = zip [0..]
I think that should work! It's a bit undefined what happens if you supply both arguments, or neither. It would be better to use Either Integer Integer as the input instead of a pair of Maybe Integer.

Of course there's always the LogicT monad if you want to do it "properly".


the same prolog problem is defined for what happens when you supply both arguments, if the statement is true it will eval to true, if it is false, it will eval to false. if neither, it will generate all possible solutions, one at a time.

:-use_module(library(clpq)).

  fib_aux(N, A, Sum,, F) :-
    { N = 0, F = 1};
    { N = 1, F = 1};
    { N >= 2, 
      N1 = N - 1,
      Acc = Sum,
      NewSum = A + Sum,
      F = F1 + Acc,
      F1 >= N1 % to not run infinitly for unsatisfiable question clp_fib(N, 4).
    },
   fib_aux(N1, Acc, NewSum, F1).

   fib(N, F) :-
     fib_aux(N, 0, 1, F).


I am a programming newbie. We just started learning CS topics through Python. Everything was fine up until we hit "Objects and Graphics". That has to be the most inefficient and inelegant way of doing anything at all. At this point I am not even sure if I ever want to touch graphics in Python. What are some languages where dealing with graphics and objects is closer to working with purely mathematical objects rather than doing insanely tedious engineering style plug-n-chug work? Sorry, if it offends some. Didn't mean that. Thanks.


What sort of "graphics" are you looking for?

I generally use Numpy NDarrays and Scipy's NDimage functions for graphics & image processing in Python. Aside from the NDarray data-structure itself, there's almost no O-O; everything in Numpy is either a method of this one workhorse data-type, or module-level functions that operate upon this data-type.

NDarrays are great because they can represent all of: - images (using 2-D arrays for binary or greyscale images, and 3-D arrays for colour images); - the vectors & matrices used in 3-D computer graphics; - the masks used in spatial image filtering; - the "structuring elements" used in morphological image processing.

Once you get used to the syntax, NDarray indexing & slicing are very efficient in both keystrokes & CPU cycles to get/set the values of pixels or arbitrary rectangular regions.

NDarray methods & the related Numpy functions offer element-wise operations (like pixel-wise Boolean logical ops, or "square every element in the matrix" / "square-root every element in the matrix" as part of the Euclidean distance calculation) and operations that can run over any dimension of the image (including the colour dimension, which is useful for calculations like the N-dimensional sum in dot-products or Euclidean distance). And the for-loops are in C, so they're blindingly fast.

NDimage functions provide filters and morphological processing capabilities. Plus, Numpy integrates nicely with Matplotlib so you can display images and plot histograms.


Processing (https://processing.org) is an excellent language and development environment for playing with graphics.


You should definitely check out Brent Yorgey's diagrams package (see examples here http://projects.haskell.org/diagrams/gallery.html) which is a declarative drawing library. Graphics are described in an essentially "mathematical" way, and as you can see, many of the examples come from mathematics.


Check out Elm: http://elm-lang.org/


That's odd - normally Python libraries tend to be simple to interact.

I wanted to stitch a few photos on friday and used Python w/ the Pillow library, and was once again impressed for easy and pleasurable the experience was (using mostly C and Go nowadays).


Wolfram Mathematica has a really nice model, and it's not that expensive for students.


Here's a hint. Write a Windows 3.1 program in C (don't worry, it runs fine in windows 8). In those programs the event loop is extremely visible, and you'll understand how everything works even in modern languages.

Effectively, even things like Android and IOS still use the same basic principle, and if you dig deep enough this is exactly the structure you'll see.

Plus cooperatively multitasked servers wipe the floor with almost any other kind. It's good to know how they are structured at a very low level and be able to write code to cooperate with them.


The actual drawing API can also vary a lot.

Cairo is quite nice and very different from Win3.1. It is more like GDI+ but nicer (and probably slower).

The GUI/event handling can also be done in different ways: functional reactive programming is very different from Win3.1/X/Old-Skool Macs.


Could you give an example of working with graphics as purely mathematical objects?


That is the part of the point I was making. I have no idea what that would look like. Maybe something like simple proofs from Number Theory or Abstract Algebra? I read up a little on Lisp family of languages on Wiki and they look vaguely close to being 100% purely mathematical, syntax-wise. I wonder what it's like doing graphics/objects(?) work in Lisp.


It's interesting that graphics and objects are so connected, in your posts. I'll say that in general, EVERYTHING in Python is objects, and they're an extremely general programming paradigm. It sounds like Haskell might be a language you'd like, if you're into abstract algebra (although I don't think Haskell's graphics support is super great).


Bluntly put, Haskell's graphics support sucks. There are different libraries with different levels of support, but none are complete or high level. There are also Haskell like alternatives like Elm and PureScript, but they're experimental. And finally there are some Haskell to JavaScript compilers, but I'm not sure what DOM manipulation is like with them (and they're all experimental).

I'm building a Haskell desktop app over winter break (DMX and light show controls), but after a fair bit of research, I came to the conclusion that its best to do the GUI in JavaScript and speak with a Haskell server over a WebSocket.


For 2D, I don't see how Gloss[0] isn't complete or high level (what are you comparing it to?). There's a cool example of drawing a clock[1] as well as others[2].

The package is on hackage[3] and has a website[4], but the github seemed more approachable/clear to me. There's also an awesome tutorial on making tic tac toe[5] by ocharles of the 24 days of hackage fame.

0: https://github.com/benl23x5/gloss

1: https://github.com/benl23x5/gloss/blob/master/gloss-examples...

2: https://github.com/benl23x5/gloss/blob/master/gloss-examples

3: http://hackage.haskell.org/package/gloss

4: http://gloss.ouroborus.net/

5: https://ocharles.org.uk/blog/posts/2013-12-10-24-days-of-hac...


Ok, I was asking because if you meant "math" as in "geometry" you could just go directly into how OpenGL does his stuff or many of the higher level graphics languages like (the preivously mentioned) Processing or three.js.

BUT, if you mean "math" as in "abstract math" (which I believe is what you do) I don't think there's anything suitable for that ATM. You see, the thing is that computers behave in a certain way and languages/libraries are pretty much just tools that help you abstract away all the boilerplate associated to the many common tasks that you may want to do in a particular subject. That said, you can't easily escape the underlying paradigm, the "way of the machine"; which in this is case is pretty much "light on and off particular pixels on the screen in order to create shapes/effects".

There is not, however, anything stopping you from creating a new set of tools designed to do exactly whatever you'd imagine these tools should be. For what I see, you are at one of the most important stages anyone has throughout his life in order to innovate, that is, when you're barely starting and your mind is full of your ideas instead of someone else's. Take note of everything that comes up to your head and try to find a way to code it later, my only suggestions would be:

1) Don't give up, it's gonna be a very long and tedious process but don't give up.

2) Try to find the tools you feel are helping you in solving this problem, never the other way around (i.e. trying to adapt the problem to the tools). If you ever feel that you are not making any more progress with the toolset that you chose and have better options in mind just go for it; even if you have to recode everything from zero again just rinse and repeat until it's perfect.

You could be at the start of somethin very interesting, who knows; best of luck and don't forget to post your progress back here.


Functional reactive animation is one such example. A constructive solid geometry used in many CADs is also pretty pure.


I'm learning two of the five "advanced programming languages" mentioned here (Ocaml and Haskell). I started with Ocaml but these days I'm spending more time with Haskell. I find the materials and activity around Haskell to be more abundant and approachable than for Ocaml. Also, a lot of the things I learn from Haskell are transferable to coding in Ocaml. Both languages share a lot of concepts.

Now that I've done some Haskell I can't believe I originally dismissed it not because of its non-strict evaluation but because of... the significative white space.

Something else exciting about Haskell is all the activity around compile-to-js languages that are inspired/derived from it (and some of them are implemented in Haskell too): purescript, fay, elm, idris, and others!


FWIW, the HN title says (2009) but there's some newer material in the Scheme section at least. I think Matt updated his original blog post.


Where is clojure?


It was mentioned right at the start, the article is also from 2009 when Clojure was very new


You don't have to go to a 'research' programming language to find one bursting with opportunity for enlightenment. Ruby offers a path to that just as it offers a useful career. Its object model is a sight to behold, a thing of sublime beauty. Everything that should be an object is an object, you can treat code as data almost as fluidly as you can in the homoiconic Lisp dialects.

It's got the solid library support you need to code at whatever level of abstraction you're inclined to do in your domain, and the possibilities for refactoring and metaprogramming are just limitless.

You don't have to compromise when you use Ruby, so long as you're not in a domain that requires cutting-edge performance, Ruby will take care of whatever it is you need to take care of while preserving the ability to abstract, redefine, and redesign.

Ruby is the ultimate in object-oriented languages, every law and technique invented by greybeards in the seventies works better when done in Ruby. Lots of design patterns that require overly verbose naming and hideously unreadable and hard-to-maintain implementations in other languages have eminently readable idiomatic expressions in Ruby as well as clear paths to refactoring to them.

Ruby's biggest weakness is not a Ruby weakness at all, it's the fact that gradual typing hasn't been well-defined mathematically yet enough to be able to usefully include it in Ruby. Once it has, I think Ruby will be the go-to option for just about everything save embedded applications. I can't think of anything that would make my life more awesome than being able to easily refactor to static typing.


Enlightenment comes from exposure to alternate paradigms and being forced out of your comfort zone. When you must do without, you will learn, and you will be ready to rely on alternate approaches to problems. Example: I thought I understood the importance of decoupling policy from implementation, but Haskell reminds me frequently that I often overlook this detail when hacking. Rather than tying the side effects (send this HTTP request) to the algorithm that produces what I need to send, I should split them apart, and have a tiny bit of glue code for them both.

It's also worth examining and trying out a particular language community's values to see if they mesh with yours. I found it hard to stay with the Ruby community because of certain stances that are made concerning program design. Everything seems tailored for easy, rather than simple.

I learned a lot from Ruby, but I never found the metaprogramming/DSL creation to be particularly inspiring. I've made some pretty wacky/cool stuff with it, I just got bored with it ultimately -- it felt like it was piling more things on for people to learn, rather than actually abstracting things away.


> I never found the metaprogramming/DSL creation to be particularly inspiring

This is only because it's a totally broken thing in Ruby. Try a proper metalanguage instead, you'll see a huge difference.


> I never found the metaprogramming/DSL creation to be particularly inspiring. I've made some pretty wacky/cool stuff with it, I just got bored with it ultimately -- it felt like it was piling more things on for people to learn, rather than actually abstracting things away.

DSL creation is all about firming up your domain model. If all you're doing is shifting complexity around, then sure, you won't get anything from the easy refactoring/metaprogramming. But if you're gradually learning more and more about how concepts work outside of programming and inside the underlying business, (Ruby works best when you're supporting a revenue-generating business rather than something more abstract) then you're actually getting somewhere.

So what you do is you leave your complex methods where they are and think really hard about exactly what it is you're trying to do, what semantics you need to have. Then when you do refactor/redesign, the language you're using to create your classes isn't arbitrary, it's well-thought out and reflective of something that is needed.

Ruby does seem tailored for easy rather than simple, I'll give you that. But you don't have to accept that lying down. Simplicity is well within the ability of the programmer to attain, he doesn't have to rely on the community.


> Then when you do refactor/redesign, the language you're using to create your classes isn't arbitrary, it's well-thought out and reflective of something that is needed.

This is how I generally like to design systems. But it also sounds more like DDD than a DSL; especially the concept of ubiquitous language. I prefer OOP to DSLs, mostly because OOP composes well since it's a first-class citizen in the paradigm.


I find myself refactoring to DSLs when I have a lot of composition to do and I want to cut the verbosity out of doing all of it. I'll take everything and turn it into something I can compose with and the DSL just knits everything together.

For example, I made an application that generates different kinds of feeds from a database. I found myself making a bunch of classes that responded to .call with similar interfaces, arrays of hashes. So I refactored everything to composable method classes and even identified and extracted concepts inside the composable methods so that I could compose even the method classes.

All the DSL does is compose the feed objects from the method classes. Each feed is composed of transformers, each transformer is a class with a .call method that takes an array of hashes and returns an array of hashes, unless it's pulling directly from the database, one of these is always the first of the transformers in the list. Or it's returning the end product, in which case it's always the last in the list.

That app is just way too much fun to work on now. It has the kind of design I would have thought of if I'd done it in BDUF fashion, only instead of coming up with it up front, I refactored working code to it. And I would not have wanted to do it in anything but Ruby.


DSLs compose much better than anything OOP.

OOP is not nearly a replacement for DSLs. Mind designing, say, an OO parser generator?


"Ruby is the ultimate in object-oriented languages,"

There is this small thing called smalltalk.

With that said, claiming Ruby is the ultimate 'enlightenment language' is a little mindboggling. I vote for javascript ;-)

That said, it is a great article. Matt Might writes very well and has a lot of insight. Fwiw he doesn't include Ruby in his list of advanced languages, but does call it a 'hot' language.


I didn't say it was the ultimate enlightenment language, I said it was the ultimate object-oriented language. There's no such thing as an ultimate approach to enlightenment.

Smalltalk's nice, but Ruby's nicer. There's a reason one's more popular than the other.


Smalltalk was already out of the scene when Rails happened, nothing to do with Ruby features.


  > nothing to do with Ruby features.
How about this part:

  > Its creator, Yukihiro “Matz” Matsumoto, blended parts of his
  > favorite languages (Perl, Smalltalk, Eiffel, Ada, and Lisp)
  > to form a new language that balanced functional programming
  > with imperative programming.
Taken from https://www.ruby-lang.org/en/about/ . Being out of the scene does not mean that it could no longer inspire.


Yes and that reason is Rails, not because ruby is more "enlightened" than smalltalk.


Why didn't they write Rails in Smalltalk?




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: