
Advanced programming languages (2009) - swah
http://matt.might.net/articles/best-programming-languages/
======
segmondy
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) ...

~~~
ctaylor001
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".

~~~
segmondy
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).

------
VectorSpace
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.

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

~~~
VectorSpace
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.

~~~
praccu
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).

~~~
rjayatilleka
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.

~~~
codygman
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](https://github.com/benl23x5/gloss)

1: [https://github.com/benl23x5/gloss/blob/master/gloss-
examples...](https://github.com/benl23x5/gloss/blob/master/gloss-
examples/picture/Clock/Main.hs)

2: [https://github.com/benl23x5/gloss/blob/master/gloss-
examples](https://github.com/benl23x5/gloss/blob/master/gloss-examples)

3:
[http://hackage.haskell.org/package/gloss](http://hackage.haskell.org/package/gloss)

4: [http://gloss.ouroborus.net/](http://gloss.ouroborus.net/)

5: [https://ocharles.org.uk/blog/posts/2013-12-10-24-days-of-
hac...](https://ocharles.org.uk/blog/posts/2013-12-10-24-days-of-hackage-
gloss.html)

------
emmanueloga_
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!

------
hudibras
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.

------
edem
Where is clojure?

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

------
vinceguidry
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.

~~~
mattgreenrocks
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.

~~~
vinceguidry
> 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.

~~~
mattgreenrocks
> 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.

~~~
vinceguidry
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.

